summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packages/astro/test/config-path.test.js13
-rw-r--r--packages/astro/test/config-port.test.js20
-rw-r--r--packages/astro/test/helpers.js72
-rw-r--r--packages/astro/test/snowpack-integration.test.js102
4 files changed, 100 insertions, 107 deletions
diff --git a/packages/astro/test/config-path.test.js b/packages/astro/test/config-path.test.js
index 5d78e7027..14cbef4d9 100644
--- a/packages/astro/test/config-path.test.js
+++ b/packages/astro/test/config-path.test.js
@@ -3,8 +3,17 @@ import * as assert from 'uvu/assert';
import { runDevServer } from './helpers.js';
const ConfigPath = suite('Config path');
+const MAX_TEST_TIME = 10000; // max time this test suite may take
const root = new URL('./fixtures/config-path/', import.meta.url);
+const timers = {};
+
+ConfigPath.before.each(({ __test__ }) => {
+ timers[__test__] = setTimeout(() => {
+ throw new Error(`Test "${__test__}" did not finish within allowed time`);
+ }, MAX_TEST_TIME);
+});
+
ConfigPath('can be passed via --config', async (context) => {
const configPath = new URL('./config/my-config.mjs', root).pathname;
const args = ['--config', configPath];
@@ -21,4 +30,8 @@ ConfigPath('can be passed via --config', async (context) => {
assert.ok(true, 'Server started');
});
+ConfigPath.after.each(({ __test__ }) => {
+ clearTimeout(timers[__test__]);
+});
+
ConfigPath.run();
diff --git a/packages/astro/test/config-port.test.js b/packages/astro/test/config-port.test.js
index b8e2d3ee9..f87951fee 100644
--- a/packages/astro/test/config-port.test.js
+++ b/packages/astro/test/config-port.test.js
@@ -5,8 +5,16 @@ import { runDevServer } from './helpers.js';
import { loadConfig } from '#astro/config';
const ConfigPort = suite('Config path');
+const MAX_TEST_TIME = 10000; // max time this test suite may take
const root = new URL('./fixtures/config-port/', import.meta.url);
+const timers = {};
+
+ConfigPort.before.each(({ __test__ }) => {
+ timers[__test__] = setTimeout(() => {
+ throw new Error(`Test "${__test__}" did not finish within allowed time`);
+ }, MAX_TEST_TIME);
+});
ConfigPort('can be specified in the astro config', async (context) => {
const astroConfig = await loadConfig(fileURLToPath(root));
@@ -15,17 +23,21 @@ ConfigPort('can be specified in the astro config', async (context) => {
ConfigPort('can be specified via --port flag', async (context) => {
const args = ['--port', '3002'];
- const process = runDevServer(root, args);
+ const proc = runDevServer(root, args);
- process.stdout.setEncoding('utf8');
- for await (const chunk of process.stdout) {
+ proc.stdout.setEncoding('utf8');
+ for await (const chunk of proc.stdout) {
if (/Local:/.test(chunk)) {
assert.ok(/:3002/.test(chunk), 'Using the right port');
break;
}
}
- process.kill();
+ proc.kill();
+});
+
+ConfigPort.after.each(({ __test__ }) => {
+ clearTimeout(timers[__test__]);
});
ConfigPort.run();
diff --git a/packages/astro/test/helpers.js b/packages/astro/test/helpers.js
index f3bb0a7e0..904cb0345 100644
--- a/packages/astro/test/helpers.js
+++ b/packages/astro/test/helpers.js
@@ -3,65 +3,87 @@ import { build as astroBuild } from '#astro/build';
import { readFile } from 'fs/promises';
import { createRuntime } from '#astro/runtime';
import { loadConfig } from '#astro/config';
-import * as assert from 'uvu/assert';
import execa from 'execa';
+const MAX_STARTUP_TIME = 7000; // max time startup may take
+const MAX_TEST_TIME = 10000; // max time an individual test may take
+const MAX_SHUTDOWN_TIME = 3000; // max time shutdown() may take
+
/** setup fixtures for tests */
export function setup(Suite, fixturePath) {
- let runtime, setupError;
+ let runtime;
+ const timers = {};
Suite.before(async (context) => {
- const astroConfig = await loadConfig(fileURLToPath(new URL(fixturePath, import.meta.url)));
+ let timeout = setTimeout(() => {
+ throw new Error('Startup did not complete within allowed time');
+ }, MAX_STARTUP_TIME);
- const logging = {
- level: 'error',
- dest: process.stderr,
- };
+ const astroConfig = await loadConfig(fileURLToPath(new URL(fixturePath, import.meta.url)));
- try {
- runtime = await createRuntime(astroConfig, { logging });
- } catch (err) {
- console.error(err);
- setupError = err;
- }
+ runtime = await createRuntime(astroConfig, {
+ logging: { level: 'error', dest: process.stderr },
+ });
context.runtime = runtime;
+
+ clearTimeout(timeout);
+ });
+
+ Suite.before.each(({ __test__ }) => {
+ if (timers[__test__]) throw new Error(`Test "${__test__}" already declared`);
+ timers[__test__] = setTimeout(() => {
+ throw new Error(`"${__test__}" did not finish within allowed time`);
+ }, MAX_TEST_TIME);
});
Suite.after(async () => {
+ let timeout = setTimeout(() => {
+ throw new Error('Shutdown did not complete within allowed time');
+ }, MAX_SHUTDOWN_TIME);
+
(await runtime) && runtime.shutdown();
+
+ clearTimeout(timeout);
});
- Suite('No errors creating a runtime', () => {
- assert.equal(setupError, undefined);
+ Suite.after.each(({ __test__ }) => {
+ clearTimeout(timers[__test__]);
});
}
export function setupBuild(Suite, fixturePath) {
- let build, setupError;
+ const timers = {};
Suite.before(async (context) => {
- const astroConfig = await loadConfig(fileURLToPath(new URL(fixturePath, import.meta.url)));
+ let timeout = setTimeout(() => {
+ throw new Error('Startup did not complete within allowed time');
+ }, MAX_STARTUP_TIME);
- const logging = {
- level: 'error',
- dest: process.stderr,
- };
+ const astroConfig = await loadConfig(fileURLToPath(new URL(fixturePath, import.meta.url)));
- build = () => astroBuild(astroConfig, logging);
- context.build = build;
+ context.build = () => astroBuild(astroConfig, { level: 'error', dest: process.stderr });
context.readFile = async (path) => {
const resolved = fileURLToPath(new URL(`${fixturePath}/${astroConfig.dist}${path}`, import.meta.url));
return readFile(resolved).then((r) => r.toString('utf8'));
};
+
+ clearTimeout(timeout);
+ });
+
+ Suite.before.each(({ __test__ }) => {
+ if (timers[__test__]) throw new Error(`Test "${__test__}" already declared`);
+ timers[__test__] = setTimeout(() => {
+ throw new Error(`"${__test__}" did not finish within allowed time`);
+ }, MAX_TEST_TIME);
});
Suite.after(async () => {
// Shutdown i guess.
});
- Suite('No errors creating a runtime', () => {
- assert.equal(setupError, undefined);
+ Suite.after.each(({ __test__ }) => {
+ clearTimeout(timers[__test__]);
});
}
diff --git a/packages/astro/test/snowpack-integration.test.js b/packages/astro/test/snowpack-integration.test.js
index abb06517f..24388c49b 100644
--- a/packages/astro/test/snowpack-integration.test.js
+++ b/packages/astro/test/snowpack-integration.test.js
@@ -1,91 +1,37 @@
+import path from 'path';
+import glob from 'tiny-glob/sync.js';
import { fileURLToPath } from 'url';
import { suite } from 'uvu';
import * as assert from 'uvu/assert';
-import { createRuntime } from '#astro/runtime';
-import { loadConfig } from '#astro/config';
-import { promises as fsPromises } from 'fs';
-import { relative as pathRelative } from 'path';
-
-const { readdir, stat } = fsPromises;
+import { setup } from './helpers.js';
const SnowpackDev = suite('snowpack.dev');
-
-const snowpackDir = new URL('../../../examples/snowpack/', import.meta.url);
-
-let runtime, cwd, setupError;
-
-SnowpackDev.before(async () => {
- // Bug: Snowpack config is still loaded relative to the current working directory.
- cwd = process.cwd();
- process.chdir(fileURLToPath(snowpackDir));
-
- const astroConfig = await loadConfig(fileURLToPath(snowpackDir));
-
- const logging = {
- level: 'error',
- dest: process.stderr,
- };
-
- try {
- runtime = await createRuntime(astroConfig, { logging });
- } catch (err) {
- console.error(err);
- setupError = err;
- }
-});
-
-SnowpackDev.after(async () => {
- process.chdir(cwd);
- (await runtime) && runtime.shutdown();
-});
-/** create an iterator for all page files */
-async function* allPageFiles(root) {
- for (const filename of await readdir(root)) {
- const fullpath = new URL(filename, root);
- const info = await stat(fullpath);
-
- if (info.isDirectory()) {
- yield* allPageFiles(new URL(fullpath + '/'));
- } else {
- yield fullpath;
- }
- }
+setup(SnowpackDev, '../../../examples/snowpack');
+
+// convert file path to its final url
+function formatURL(filepath) {
+ return filepath
+ .replace(/^\/?/, '/') // add / to beginning, if missing
+ .replace(/(index)?\.(astro|md)$/, '') // remove .astro and .md extensions
+ .replace(/\/$/, ''); // remove trailing slash, if any
}
-/** create an iterator for all pages and yield the relative paths */
-async function* allPages(root) {
- for await (let fileURL of allPageFiles(root)) {
- let bare = fileURLToPath(fileURL)
- .replace(/\.(astro|md)$/, '')
- .replace(/index$/, '');
- yield '/' + pathRelative(fileURLToPath(root), bare);
- }
-}
+// declaring routes individually helps us run many quick tests rather than one giant slow test
+const root = path.join(path.dirname(fileURLToPath(import.meta.url)), '../../../examples/snowpack/src/pages');
+let pages = glob('**/*.{astro,md}', { cwd: root, onlyFiles: true })
+ .filter((page) => !page.includes('proof-of-concept-dynamic'))
+ .map(formatURL);
-SnowpackDev('No error creating the runtime', () => {
- assert.equal(setupError, undefined);
+SnowpackDev('Pages successfully scanned', () => {
+ assert.ok(pages.length > 0);
});
-SnowpackDev('Can load every page', async () => {
- const failed = [];
-
- const pageRoot = new URL('./src/pages/', snowpackDir);
- for await (let pathname of allPages(pageRoot)) {
- if (pathname.includes('proof-of-concept-dynamic')) {
- continue;
- }
+for (const pathname of pages) {
+ SnowpackDev(`Loads "${pathname}"`, async ({ runtime }) => {
const result = await runtime.load(pathname);
- if (result.statusCode === 500) {
- failed.push({ ...result, pathname });
- continue;
- }
- assert.equal(result.statusCode, 200, `Loading ${pathname}`);
- }
-
- if (failed.length > 0) {
- console.error(failed);
- }
- assert.equal(failed.length, 0, 'Failed pages');
-});
+ assert.equal(result.statusCode, 200);
+ return;
+ });
+}
SnowpackDev.run();