Skip to content

Commit

Permalink
chore(astro-tests): Add debug logging
Browse files Browse the repository at this point in the history
  • Loading branch information
Fryuni committed Sep 14, 2024
1 parent 6fdad15 commit 81db094
Show file tree
Hide file tree
Showing 7 changed files with 79 additions and 14 deletions.
5 changes: 5 additions & 0 deletions .changeset/unlucky-spies-turn.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@inox-tools/astro-tests': patch
---

Add debug logging
1 change: 1 addition & 0 deletions packages/astro-tests/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
"@astrojs/markdown-remark": "^5.2.0",
"@inox-tools/utils": "workspace:^",
"astro": "catalog:",
"debug": "catalog:",
"shiki": "^1.14.1",
"fast-glob": "^3.3.2",
"strip-ansi": "^7.1.0",
Expand Down
52 changes: 44 additions & 8 deletions packages/astro-tests/src/astroFixture.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ import { validateConfig } from '../node_modules/astro/dist/core/config/validate.
import { getViteConfig } from 'astro/config';
import { callsites } from './utils.js';
import type { App } from 'astro/app';
import { getDebug } from './internal/log.js';

const debug = getDebug('fixture');

// Disable telemetry when running tests
process.env.ASTRO_TELEMETRY_DISABLED = 'true';
Expand Down Expand Up @@ -136,10 +139,13 @@ type Fixture = {
export async function loadFixture(inlineConfig: InlineConfig): Promise<Fixture> {
if (!inlineConfig?.root) throw new Error("Must provide { root: './fixtures/...' }");

debug('Setting default log level to "silent"');
// Silent by default during tests to not pollute the console output
inlineConfig.logLevel = 'silent';
inlineConfig.logLevel ??= 'silent';
inlineConfig.vite ??= {};
inlineConfig.vite.logLevel = 'silent';
inlineConfig.vite.logLevel ??= 'silent';

debug('Disabling Vite discovery for dependency optimization');
// Prevent hanging when testing the dev server on some scenarios
inlineConfig.vite.optimizeDeps ??= {};
inlineConfig.vite.optimizeDeps.noDiscovery = true;
Expand All @@ -149,19 +155,28 @@ export async function loadFixture(inlineConfig: InlineConfig): Promise<Fixture>
// Handle URL, should already be absolute so just convert to path
root = fileURLToPath(root);
} else if (root.startsWith('file://')) {
debug('Root is a file URL, converting to path');
// Handle "file:///C:/Users/fred", convert to "C:/Users/fred"
root = fileURLToPath(new URL(root));
} else if (!path.isAbsolute(root)) {
debug('Root is a relative path, resolving to absolute path relative to caller');
const [caller] = callsites().slice(1);
let callerUrl = caller.getScriptNameOrSourceURL() || undefined;
if (callerUrl?.startsWith('file:') === false) {
callerUrl = pathToFileURL(callerUrl).toString();
}
debug(`Fixture loaded from ${callerUrl}`);
// Handle "./fixtures/...", convert to absolute path relative to the caller of this function.
root = fileURLToPath(new URL(root, callerUrl));
debug(`Resolved fixture root to ${root}`);
}

inlineConfig.root = root;
const config = await validateConfig(inlineConfig, root, 'dev');

debug('Output dir:', inlineConfig.outDir);
debug('Src dir:', inlineConfig.srcDir);

const viteConfig = await getViteConfig(
{},
{ ...inlineConfig, root }
Expand Down Expand Up @@ -193,7 +208,10 @@ export async function loadFixture(inlineConfig: InlineConfig): Promise<Fixture>

const onNextChange = () =>
devServer
? new Promise((resolve) => devServer.watcher.once('change', resolve))
? new Promise<void>((resolve) =>
// TODO: Implement filter to only resolve on changes to a given file.
devServer.watcher.once('change', () => resolve())
)
: Promise.reject(new Error('No dev server running'));

// Also do it on process exit, just in case.
Expand All @@ -203,48 +221,58 @@ export async function loadFixture(inlineConfig: InlineConfig): Promise<Fixture>
config,
startDevServer: async (extraInlineConfig = {}) => {
process.env.NODE_ENV = 'development';
debug(`Starting dev server for fixture ${root}`);
devServer = await dev(
mergeConfig(inlineConfig, {
...extraInlineConfig,
force: true,
})
);
viteServerOptions.host = parseAddressToHost(devServer.address.address)!; // update host
viteServerOptions.port = devServer.address.port; // update port
viteServerOptions.host = parseAddressToHost(devServer.address.address)!;
viteServerOptions.port = devServer.address.port;
debug(`Dev server for ${root} running at ${resolveUrl('/')}`);
return devServer;
},
build: async (extraInlineConfig = {}) => {
process.env.NODE_ENV = 'production';
debug(`Building fixture ${root}`);
return build(mergeConfig(inlineConfig, extraInlineConfig));
},
preview: async (extraInlineConfig = {}) => {
process.env.NODE_ENV = 'production';
debug(`Starting preview server for fixture ${root}`);
const previewServer = await preview(mergeConfig(inlineConfig, extraInlineConfig));
viteServerOptions.host = parseAddressToHost(previewServer.host)!; // update host
viteServerOptions.port = previewServer.port; // update port
viteServerOptions.host = parseAddressToHost(previewServer.host)!;
viteServerOptions.port = previewServer.port;
debug(`Preview server for ${root} running at ${resolveUrl('/')}`);
return previewServer;
},
sync,

clean: async () => {
debug(`Cleaning fixture ${root}`);
debug(`Removing outDir`);
await fs.promises.rm(config.outDir, {
maxRetries: 10,
recursive: true,
force: true,
});

debug(`Removing node_modules/.astro`);
await fs.promises.rm(new URL('./node_modules/.astro', config.root), {
maxRetries: 10,
recursive: true,
force: true,
});

debug(`Removing cacheDir`);
await fs.promises.rm(config.cacheDir, {
maxRetries: 10,
recursive: true,
force: true,
});

debug(`Removing .astro`);
await fs.promises.rm(new URL('./.astro', config.root), {
maxRetries: 10,
recursive: true,
Expand All @@ -254,6 +282,7 @@ export async function loadFixture(inlineConfig: InlineConfig): Promise<Fixture>
resolveUrl,
fetch: async (url, init) => {
if (config.vite?.server?.https) {
debug('Injecting agent to enable HTTPS and HTTP/2 support');
init = {
// Use a custom fetch dispatcher. This is an undici option that allows
// us to customize the fetch behavior. We use it here to allow h2.
Expand Down Expand Up @@ -289,7 +318,7 @@ export async function loadFixture(inlineConfig: InlineConfig): Promise<Fixture>
} catch (err: any) {
// node fetch throws a vague error when it fails, so we log the url here to easily debug it
if (err.message?.includes('fetch failed')) {
console.error(`[astro test] failed to fetch ${resolvedUrl}`);
console.error(`[astro-tests] failed to fetch ${resolvedUrl}`);
console.error(err);
}
throw err;
Expand All @@ -303,13 +332,16 @@ export async function loadFixture(inlineConfig: InlineConfig): Promise<Fixture>
const fileUrl = new URL(filePath.replace(/^\//, ''), config.root);
const contents = await fs.promises.readFile(fileUrl, 'utf-8');
const reset = () => {
debug(`Resetting ${filePath}`);
fs.writeFileSync(fileUrl, contents);
};
// Only save this reset if not already in the map, in case multiple edits happen
// to the same file.
if (!fileEdits.has(fileUrl.toString())) {
fileEdits.set(fileUrl.toString(), reset);
}

debug(`Editing ${filePath}`);
const newContents =
typeof newContentsOrCallback === 'function'
? newContentsOrCallback(contents)
Expand All @@ -327,8 +359,11 @@ export async function loadFixture(inlineConfig: InlineConfig): Promise<Fixture>
}),
loadTestAdapterApp: async () => {
const url = new URL(`./server/entry.mjs?id=${fixtureId}`, config.outDir);
debug(`Importing test adapter entrypoint from ${url.toString()}`);
const { createApp, manifest } = await import(url.toString());
debug('Instantiating test adapter app');
const app = createApp();
debug('Manifest:', manifest);
app.manifest = manifest;
return {
render: (req) => app.render(req),
Expand All @@ -337,6 +372,7 @@ export async function loadFixture(inlineConfig: InlineConfig): Promise<Fixture>
},
loadNodeAdapterHandler: async () => {
const url = new URL(`./server/entry.mjs?id=${fixtureId}`, config.outDir);
debug(`Importing node adapter handler from ${url.toString()}`);
const { handler } = await import(url.toString());
return handler;
},
Expand Down
12 changes: 12 additions & 0 deletions packages/astro-tests/src/internal/log.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import debugC from 'debug';

debugC.inspectOpts = {
colors: true,
depth: null,
};

export const debug = debugC('inox-tools:astro-tests');

export function getDebug(name: string): debugC.Debugger {
return debug.extend(name);
}
18 changes: 13 additions & 5 deletions packages/astro-tests/src/testAdapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
*/

import type { AstroIntegration, HookParameters } from 'astro';
import { getDebug } from './internal/log.js';

const debug = getDebug('testAdapter');

type EntryPoints = HookParameters<'astro:build:ssr'>['entryPoints'];
type MiddlewareEntryPoint = HookParameters<'astro:build:ssr'>['middlewareEntryPoint'];
Expand Down Expand Up @@ -43,6 +46,8 @@ export type Options = {
};

export default function (options: Options = {}): AstroIntegration {
debug('New test adapter created', options);

const {
env,
provideAddress = true,
Expand All @@ -52,7 +57,7 @@ export default function (options: Options = {}): AstroIntegration {
} = options;

return {
name: 'test-ssr-adapter',
name: debug.name,
hooks: {
'astro:config:setup': ({ updateConfig }) => {
updateConfig({
Expand All @@ -71,14 +76,13 @@ export default function (options: Options = {}): AstroIntegration {
import { App } from 'astro/app';
import fs from 'fs';
${
env != null
? `
${env != null
? `
const $$env = ${JSON.stringify(env)};
await import('astro/env/setup')
.then(mod => mod.setGetEnv((key) => $$env[key]))
.catch(() => {});`
: ''
: ''
}
class MyApp extends App {
Expand Down Expand Up @@ -116,6 +120,7 @@ export default function (options: Options = {}): AstroIntegration {
});
},
'astro:config:done': ({ setAdapter }) => {
debug('Applying adapter');
setAdapter({
name: 'my-ssr-adapter',
serverEntrypoint: '@my-ssr',
Expand All @@ -136,14 +141,17 @@ export default function (options: Options = {}): AstroIntegration {
},
'astro:build:ssr': ({ entryPoints, middlewareEntryPoint }) => {
if (setEntryPoints) {
debug('Collecting entry points');
setEntryPoints(entryPoints);
}
if (setMiddlewareEntryPoint) {
debug('Collecting middleware entry point');
setMiddlewareEntryPoint(middlewareEntryPoint);
}
},
'astro:build:done': ({ routes }) => {
if (setRoutes) {
debug('Collecting routes');
setRoutes(routes);
}
},
Expand Down
2 changes: 1 addition & 1 deletion packages/astro-tests/tsup.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ const devDependencies = [...Object.keys(packageJson.devDependencies || {})]
.map((name) => new RegExp(`^${name}/?$`));

export default defineConfig({
entry: ['src/**/*.ts'],
entry: ['src/*.ts'],
format: ['esm'],
target: 'node18',
bundle: true,
Expand Down
3 changes: 3 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 81db094

Please sign in to comment.