astro/packages/create-astro/test/create-astro.test.js

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

134 lines
4.1 KiB
JavaScript
Raw Normal View History

import fs from 'fs';
import path from 'path';
import http from 'http';
2021-06-11 21:07:30 +00:00
import { green, red } from 'kleur/colors';
import { execa } from 'execa';
import glob from 'tiny-glob';
2021-06-08 15:12:07 +00:00
import { TEMPLATES } from '../dist/templates.js';
import { GITHUB_SHA, FIXTURES_DIR } from './helpers.js';
2021-06-11 21:07:30 +00:00
// helpers
async function fetch(url) {
2021-06-11 21:07:30 +00:00
return new Promise((resolve, reject) => {
http
.get(url, (res) => {
2021-06-11 21:07:30 +00:00
// not OK
if (res.statusCode !== 200) {
reject(res.statusCode);
return;
}
2021-12-22 21:11:05 +00:00
2021-06-11 21:07:30 +00:00
// OK
let body = '';
res.on('data', (chunk) => {
body += chunk;
});
res.on('end', () => resolve({ statusCode: res.statusCode, body }));
})
.on('error', (err) => {
2021-06-11 21:07:30 +00:00
// other error
reject(err);
});
});
}
2021-06-11 21:07:30 +00:00
function assert(a, b, message) {
if (a !== b) throw new Error(red(`${message}`));
}
async function testTemplate(template) {
const templateDir = path.join(FIXTURES_DIR, template);
2021-12-22 21:11:05 +00:00
2021-06-11 21:07:30 +00:00
// test 1: install
const DOES_HAVE = ['.gitignore', 'package.json', 'public', 'src'];
const DOES_NOT_HAVE = ['.git', 'meta.json'];
2021-12-22 21:11:05 +00:00
2021-06-11 21:07:30 +00:00
// test 1a: expect template contains essential files & folders
for (const file of DOES_HAVE) {
assert(fs.existsSync(path.join(templateDir, file)), true, `[${template}] has ${file}`);
}
// test 1b: expect template DOES NOT contain files supposed to be stripped away
for (const file of DOES_NOT_HAVE) {
assert(fs.existsSync(path.join(templateDir, file)), false, `[${template}] cleaned up ${file}`);
}
2021-12-22 21:11:05 +00:00
2021-06-11 21:07:30 +00:00
// test 2: build
const MUST_HAVE_FILES = ['index.html', '_astro'];
await execa('npm', ['run', 'build'], { cwd: templateDir });
const builtFiles = await glob('**/*', { cwd: path.join(templateDir, 'dist') });
// test 2a: expect all files built successfully
for (const file of MUST_HAVE_FILES) {
assert(builtFiles.includes(file), true, `[${template}] built ${file}`);
}
2021-12-22 21:11:05 +00:00
2021-06-11 21:07:30 +00:00
// test 3: dev server (should happen after build so dependency install can be reused)
2021-12-22 21:11:05 +00:00
2021-06-11 21:07:30 +00:00
// TODO: fix dev server test in CI
if (process.env.CI === true) {
return;
}
2021-12-22 21:11:05 +00:00
2021-06-11 21:07:30 +00:00
// start dev server in background & wait until ready
const templateIndex = TEMPLATES.findIndex(({ value }) => value === template);
const port = 3000 + templateIndex; // use different port per-template
const devServer = execa('npm', ['run', 'start', '--', '--port', port], { cwd: templateDir });
let sigkill = setTimeout(() => {
throw new Error(`Dev server failed to start`); // if 10s has gone by with no update, kill process
}, 10000);
2021-12-22 21:11:05 +00:00
2021-06-11 21:07:30 +00:00
// read stdout until "Server started" appears
await new Promise((resolve, reject) => {
devServer.stdout.on('data', (data) => {
clearTimeout(sigkill);
sigkill = setTimeout(() => {
reject(`Dev server failed to start`);
}, 10000);
if (data.toString('utf8').includes('Server started')) resolve();
});
devServer.stderr.on('data', (data) => {
reject(data.toString('utf8'));
});
});
clearTimeout(sigkill); // done!
2021-12-22 21:11:05 +00:00
2021-06-11 21:07:30 +00:00
// send request to dev server that should be ready
const { statusCode, body } = (await fetch(`http://localhost:${port}`)) || {};
2021-12-22 21:11:05 +00:00
2021-06-11 21:07:30 +00:00
// test 3a: expect 200 status code
assert(statusCode, 200, `[${template}] 200 response`);
// test 3b: expect non-empty response
assert(body.length > 0, true, `[${template}] non-empty response`);
2021-12-22 21:11:05 +00:00
2021-06-11 21:07:30 +00:00
// clean up
devServer.kill();
}
2021-06-11 21:07:30 +00:00
async function testAll() {
// setup
await Promise.all(
TEMPLATES.map(async ({ value: template }) => {
2021-06-11 21:07:30 +00:00
// setup: `npm init astro`
await execa('../../create-astro.mjs', [template, '--template', template, '--commit', GITHUB_SHA, '--force-overwrite'], {
cwd: FIXTURES_DIR,
});
Move from yarn to pnpm (#2455) * chore: `yarn` => `pnpm` * docs: `yarn` => `pnpm` * chore(ci): yarn => pnpm * chore(ci): update pnpm cache path * fix: add missing deps * fix: add missing deps * test: add package.json to all test fixtures * chore: improve hoisting behavior * chore: move turbo into package.json * chore: update npmrc * fix: add missing `debug` dependency * chore: remove prepare script * test: fix new tests * fix: fully resolve renderer paths and `astro/internal` path * chore: update lockfile * chore: remove log * fix: resolve renderers in vite-plugin-jsx * fix: prefer public-hoist-pattern to shamefully-hoist * chore: ignore @babel/core peer warning * chore: update dependencies * test: add autoprefixer as explicit dep * chore: update `.npmrc` file in examples * chore: update dependencies * fix: resolve renderer dependencies in static build * fix: static build renderer resolution * chore: fix smoke tests * chore: hoist autoprefixer * chore: update lockfile * attempt: use full file:// path on Windows * attempt: use astro/internal * attempt: optimize astro/internal * attempt: expose ./internal.js * chore: add missing package.json files * attempt: resolve astro/internal path * chore: tidy package.json * chore: update lockfile * chore: update deps * chore: update deps * chore: yarn -> pnpm * attempt: explicit /@fs urls * attempt: explicit /@fs urls * chore: update all examples for pnpm * chore: fix hoisting for with-vite-plugin-pwa * chore(ci): fix sharp install * chore: update with-vite-plugin-pwa example * fix: pin vite-plugin-pwa to 0.11.11 * fix: add workbox-window to vite-plugin-pwa deps * refactor: use pnpm update --recursive Co-authored-by: JuanM04 <me@juanm04.com> * chore: yarn => pnpm * chore: yarn => pnpm * fix: update smoke test to skip examples which don't work in static build * update lockfile * chore: update .npmrc files * chore: update lockfile * fix: smoke script * chore: update .npmrc file * fix: return to shamefully-hoist (shamefully) * chore: update lockfile * fix(smoke): ignore scripts for smoke tests * fix: update example to disable renderers * chore: bump version * chore(ci): fix smoke tests * attempt: disable --frozen-lockfile for smoke tests * chore: update smoke test * chore: fix rebase issue * chore: update lockfile * fix: smoke tests * fix(ci): run external smoke tests first * fix(ci): run syntax * chore: update lockfile * fix(ci): ensure submodules are up-to-date * fix(ci): ensure submodules are up-to-date * chore: update lockfile * chore: update for webapi * chore: silence node:* warnings * chore: update deps * fix(ci): persist generated webapi assets * fix(ci): webapi build script * chore(ci): remove custom node caching * chore: keep turbo.json * chore: update turbo, ignore create-astro * chore: update deps * fix(ci): test command * chore(ci): update test script Co-authored-by: JuanM04 <me@juanm04.com>
2022-03-08 21:46:11 +00:00
// setup: `pnpm install` (note: running multiple `pnpm`s in parallel in CI will conflict)
await execa('pnpm', ['install', '--no-package-lock', '--silent'], { cwd: path.join(FIXTURES_DIR, template) });
})
);
2021-12-22 21:11:05 +00:00
2021-06-11 21:07:30 +00:00
// test (note: not parallelized because Snowpack HMR reuses same port in dev)
for (let n = 0; n < TEMPLATES.length; n += 1) {
const template = TEMPLATES[n].value;
2021-12-22 21:11:05 +00:00
2021-06-11 21:07:30 +00:00
try {
await testTemplate(template);
} catch (err) {
console.error(red(`✘ [${template}]`));
throw err;
}
2021-12-22 21:11:05 +00:00
2021-06-11 21:07:30 +00:00
console.info(green(`✔ [${template}] All tests passed (${n + 1}/${TEMPLATES.length})`));
}
}
2021-06-11 21:07:30 +00:00
testAll();