aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/nodejs.yml1
-rw-r--r--examples/blog/meta.json5
-rw-r--r--examples/starter/meta.json5
-rw-r--r--package.json2
-rw-r--r--packages/create-astro/README.md12
-rw-r--r--packages/create-astro/package.json2
-rw-r--r--packages/create-astro/src/index.ts22
-rw-r--r--packages/create-astro/test/create-astro.test.js108
-rw-r--r--tools/astro-vscode/package.json2
-rw-r--r--www/package.json1
10 files changed, 128 insertions, 32 deletions
diff --git a/.github/workflows/nodejs.yml b/.github/workflows/nodejs.yml
index 1e958547b..8b362e7a1 100644
--- a/.github/workflows/nodejs.yml
+++ b/.github/workflows/nodejs.yml
@@ -70,3 +70,4 @@ jobs:
- run: yarn test
env:
CI: true
+ GITHUB_SHA: $GITHUB_SHA
diff --git a/examples/blog/meta.json b/examples/blog/meta.json
deleted file mode 100644
index caa6852e5..000000000
--- a/examples/blog/meta.json
+++ /dev/null
@@ -1,5 +0,0 @@
-{
- "title": "Blog",
- "description": "an SEO-optimized blog starter",
- "rank": 1
-}
diff --git a/examples/starter/meta.json b/examples/starter/meta.json
deleted file mode 100644
index e9f3778c7..000000000
--- a/examples/starter/meta.json
+++ /dev/null
@@ -1,5 +0,0 @@
-{
- "title": "Getting Started",
- "description": "a friendly starting point for new astronauts",
- "rank": 999
-}
diff --git a/package.json b/package.json
index 171dd94d6..d2535653a 100644
--- a/package.json
+++ b/package.json
@@ -8,7 +8,7 @@
"build": "yarn build:core",
"build:all": "lerna run build",
"build:one": "lerna run build --scope",
- "build:core": "lerna run build --scope astro --scope @astrojs/parser --scope @astrojs/markdown-support",
+ "build:core": "lerna run build --scope astro --scope @astrojs/parser --scope @astrojs/markdown-support --scope create-astro",
"build:vscode": "lerna run build --scope astro-languageserver --scope astro-vscode --scope @astrojs/parser",
"dev:vscode": "lerna run dev --scope astro-languageserver --scope astro-vscode --scope @astrojs/parser --parallel --stream",
"format": "prettier -w \"**/*.{js,jsx,ts,tsx,md,json}\"",
diff --git a/packages/create-astro/README.md b/packages/create-astro/README.md
index 0c3982ed5..4a90b7eb4 100644
--- a/packages/create-astro/README.md
+++ b/packages/create-astro/README.md
@@ -26,5 +26,15 @@ npm init astro my-astro-project -- --template starter
# yarn
yarn create astro my-astro-project --template starter
```
+[Check out the full list][examples] of example starter templates, available on GitHub.
-[Check out the full list](https://github.com/snowpackjs/astro/tree/main/examples) of example starter templates, available on GitHub.
+### CLI Flags
+
+May be provided in place of prompts
+
+| Name | Description |
+|:-------------|:----------------------------------------------------|
+| `--template` | Specify the template name ([list][examples]) |
+| `--commit` | Specify a specific Git commit or branch to use from this repo (by default, `main` branch of this repo will be used) |
+
+[examples]: https://github.com/snowpackjs/astro/tree/main/examples
diff --git a/packages/create-astro/package.json b/packages/create-astro/package.json
index 04df2fdde..b4cc2a7e9 100644
--- a/packages/create-astro/package.json
+++ b/packages/create-astro/package.json
@@ -11,7 +11,7 @@
"scripts": {
"build": "astro-scripts build \"src/*.ts\"",
"prepare": "yarn build",
- "test": "uvu"
+ "test": "uvu -i test/fixtures"
},
"files": [
"dist",
diff --git a/packages/create-astro/src/index.ts b/packages/create-astro/src/index.ts
index 0d1d834f3..240faf7c0 100644
--- a/packages/create-astro/src/index.ts
+++ b/packages/create-astro/src/index.ts
@@ -19,6 +19,8 @@ export function mkdirp(dir: string) {
const { version } = JSON.parse(fs.readFileSync(new URL('../package.json', import.meta.url), 'utf-8'));
+const POSTPROCESS_FILES = ['package.json']; // some files need processing after copying.
+
export async function main() {
console.log('\n' + bold('Welcome to Astro!') + gray(` (create-astro v${version})`));
console.log(`If you encounter a problem, visit ${cyan('https://github.com/snowpack/astro/issues')} to search or file a new issue.\n`);
@@ -52,12 +54,14 @@ export async function main() {
},
]);
- const emitter = degit(`snowpackjs/astro/examples/${options.template}`, {
+ const hash = args.commit ? `#${args.commit}` : '';
+ const emitter = degit(`snowpackjs/astro/examples/${options.template}${hash}`, {
cache: false,
force: true,
verbose: false,
});
+ // Copy
try {
// emitter.on('info', info => { console.log(info.message) });
console.log(green(`>`) + gray(` Copying project files...`));
@@ -68,6 +72,22 @@ export async function main() {
process.exit(1);
}
+ // Post-process in parallel
+ await Promise.all(
+ POSTPROCESS_FILES.map(async (file) => {
+ const fileLoc = path.join(cwd, file);
+
+ switch (file) {
+ case 'package.json': {
+ const packageJSON = JSON.parse(await fs.promises.readFile(fileLoc, 'utf8'));
+ delete packageJSON.snowpack; // delete snowpack config only needed in monorepo (can mess up projects)
+ await fs.promises.writeFile(fileLoc, JSON.stringify(packageJSON, undefined, 2));
+ break;
+ }
+ }
+ })
+ );
+
console.log(bold(green('✔ Copied project files')));
console.log('\nNext steps:');
diff --git a/packages/create-astro/test/create-astro.test.js b/packages/create-astro/test/create-astro.test.js
index 3b9e4f013..4335f77e1 100644
--- a/packages/create-astro/test/create-astro.test.js
+++ b/packages/create-astro/test/create-astro.test.js
@@ -1,46 +1,120 @@
import fs from 'fs';
import path from 'path';
import { fileURLToPath } from 'url';
+import http from 'http';
import { suite } from 'uvu';
import execa from 'execa';
import del from 'del';
+import glob from 'tiny-glob';
import * as assert from 'uvu/assert';
import { TEMPLATES } from '../dist/templates.js';
-const CreateAstro = suite('npm init astro');
+// config
+const GITHUB_SHA = process.env.GITHUB_SHA || execa.sync('git', ['rev-parse', 'HEAD']).stdout; // process.env.GITHUB_SHA will be set in CI; if testing locally execa() will gather this
+const MAX_TEST_TIME = 60000; // maximum time a test may take (60s)
+const TIMER = {}; // keep track of every test’s run time (uvu requires manual setup for this)
+const FIXTURES_DIR = path.join(fileURLToPath(path.dirname(import.meta.url)), 'fixtures');
-const cwd = fileURLToPath(path.dirname(import.meta.url));
-const fixturesDir = path.join(cwd, 'fixtures');
+// helper
+async function fetch(url) {
+ return new Promise((resolve) => {
+ http
+ .get(url, (res) => {
+ let body = '';
+ res.on('data', (chunk) => {
+ body += chunk;
+ });
+ res.on('end', () => resolve({ statusCode: res.statusCode, body }));
+ })
+ .on('error', (err) => {
+ reject(err);
+ });
+ });
+}
+
+// test
+const CreateAstro = suite('npm init astro');
CreateAstro.before(async () => {
- await del(fixturesDir);
- await fs.promises.mkdir(fixturesDir);
+ // clean install dir
+ await del(FIXTURES_DIR);
+ await fs.promises.mkdir(FIXTURES_DIR);
+
+ // install all templates & deps before running tests
+ await Promise.all(
+ TEMPLATES.map(async ({ value: template }) => {
+ const templateDir = path.join(FIXTURES_DIR, template);
+ await execa('../../create-astro.mjs', [templateDir, '--template', template, '--commit', GITHUB_SHA, '--force-overwrite'], {
+ cwd: FIXTURES_DIR,
+ });
+ await execa('yarn', ['--frozen-lockfile', '--silent'], { cwd: templateDir });
+ })
+ );
});
-for (const { value: template } of TEMPLATES) {
- // TODO: Unskip once repo is made public. Because the repo is private, the templates can't yet be downloaded.
- CreateAstro.skip(template, async () => {
- const testDirectory = path.join(fixturesDir, template);
- const { stdout } = await execa('../../create-astro.mjs', [testDirectory, '--template', template, '--force-overwrite'], { cwd: path.join(cwd, 'fixtures') });
+// enforce MAX_TEST_TIME
+CreateAstro.before.each(({ __test__ }) => {
+ if (TIMER[__test__]) throw new Error(`Test "${__test__}" already declared`);
+ TIMER[__test__] = setTimeout(() => {
+ throw new Error(`"${__test__}" did not finish within allowed time`);
+ }, MAX_TEST_TIME);
+});
+CreateAstro.after.each(({ __test__ }) => {
+ clearTimeout(TIMER[__test__]);
+});
- console.log(stdout);
- // test: path should formatted as './{dirName}'
- assert.not.match(stdout, '././');
+for (let n = 0; n < TEMPLATES.length; n++) {
+ const template = TEMPLATES[n].value;
+ const templateDir = path.join(FIXTURES_DIR, template);
+ CreateAstro(`${template} (install)`, async () => {
const DOES_HAVE = ['.gitignore', 'package.json', 'public', 'src'];
- const DOES_NOT_HAVE = ['meta.json', 'node_modules', 'yarn.lock'];
+ const DOES_NOT_HAVE = ['.git', 'meta.json'];
// test: template contains essential files & folders
for (const file of DOES_HAVE) {
- console.log(path.join(testDirectory, file));
- assert.ok(fs.existsSync(path.join(testDirectory, file)), `has ${file}`);
+ assert.ok(fs.existsSync(path.join(templateDir, file)), `missing ${file}`);
}
// test: template DOES NOT contain files supposed to be stripped away
for (const file of DOES_NOT_HAVE) {
- assert.not.ok(fs.existsSync(path.join(testDirectory, file)), `does not have ${file}`);
+ assert.not.ok(fs.existsSync(path.join(templateDir, file)), `failed to clean up ${file}`);
+ }
+ });
+
+ CreateAstro(`${template} (dev)`, async () => {
+ // start dev server
+ const port = 3000 + n; // start new port per test
+ const devServer = execa('yarn', ['start', '--port', port], { cwd: templateDir });
+ await new Promise((resolve) => {
+ setTimeout(() => resolve(), 15000);
+ }); // give dev server flat 15s to set up
+ // TODO: try to ping dev server ASAP rather than waiting flat 15s
+
+ // ping dev server
+ const { statusCode, body } = await fetch(`http://localhost:${port}`);
+
+ // expect 200 to be returned with some response
+ assert.equal(statusCode, 200, 'didn’t respond with 200');
+ assert.ok(body, 'returned empty response');
+
+ // clean up
+ devServer.kill();
+ });
+
+ CreateAstro(`${template} (build)`, async () => {
+ const MUST_HAVE_FILES = ['index.html', '_astro'];
+
+ // build template
+ await execa('yarn', ['build'], { cwd: templateDir });
+
+ // scan build dir
+ const builtFiles = await glob('**/*', { cwd: path.join(templateDir, 'dist') });
+ for (const file of MUST_HAVE_FILES) {
+ assert.ok(builtFiles.includes(file), `didn’t build ${file}`);
}
});
}
+// run tests
CreateAstro.run();
diff --git a/tools/astro-vscode/package.json b/tools/astro-vscode/package.json
index be3460977..d947c90ee 100644
--- a/tools/astro-vscode/package.json
+++ b/tools/astro-vscode/package.json
@@ -24,7 +24,7 @@
"onLanguage:astro"
],
"dependencies": {
- "astro-languageserver": "file:../astro-languageserver"
+ "astro-languageserver": "^0.4.0"
},
"devDependencies": {
"@types/vscode": "^1.52.0",
diff --git a/www/package.json b/www/package.json
index e9426b700..3734e3461 100644
--- a/www/package.json
+++ b/www/package.json
@@ -1,6 +1,7 @@
{
"name": "www",
"version": "1.1.0",
+ "private": true,
"scripts": {
"start": "astro dev",
"build": "astro build"