Skip to content

Commit

Permalink
Document all APIs
Browse files Browse the repository at this point in the history
  • Loading branch information
Fryuni committed Sep 5, 2024
1 parent d199df5 commit 134b3d2
Show file tree
Hide file tree
Showing 4 changed files with 204 additions and 33 deletions.
162 changes: 150 additions & 12 deletions docs/src/content/docs/astro-tests.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import { PackageManagers } from 'starlight-package-managers';

<p>**Type:** `AstroConfig`</p>

The final config passed to [Astro's programatic CLI entrypoints][advanced APIs]. This configuration can be overriden on each method call.
The final config passed to [Astro's programatic CLI entrypoints](https://docs.astro.build/en/reference/cli-reference/#advanced-apis-experimental). This configuration can be overriden on each method call.
Will be automatically passed to the methods below:

- [`startDevServer()`](#startdevserver)
Expand Down Expand Up @@ -138,76 +138,214 @@ Equivalent to running [`astro sync`](https://docs.astro.build/en/reference/cli-r
**Type:** `() => Promise<void>`
</p>

Deletes the generated files from the fixture directory. Specifically, it deletes:

- The output directory (`outDir` config)
- The cache directory (`cacheDir` config)
- The `.astro` directory generated in the project
- the `.astro` directory generated in the `node_modules`

### `resolveUrl`

<p>**Type:** `(url: string) => string`</p>

Resolves a relative URL to the full url of the running server.

This can only be called after either [`.startDevServer()`](#startdevserver) or [`.preview()`](#preview) is called.

### `fetch`

{(

<p>
**Type:** `(url: string, opts?: Parameters<typeof request>[1]) => Promise<Response>`
<strong>Type: </strong>
<code dir="auto" style="padding-right: 0;">
(url: string, opts?:{' '}
</code>
<a href="https://developer.mozilla.org/en-US/docs/Web/API/RequestInit">
<code dir="auto" style="padding-left: 0;padding-right: 0;">
RequestInit
</code>
</a>
<code dir="auto" style="padding-left: 0;padding-right: 0;">
) =&gt; Promise&lt;
</code>
<a href="https://developer.mozilla.org/en-US/docs/Web/API/Response">
<code dir="auto" style="padding-left: 0;padding-right: 0;">
Response
</code>
</a>
<code dir="auto" style="padding-left: 0;">
&gt;
</code>
</p>
)}

Send a request to the given URL. If the URL is relative, it will be resolved relative to the root of the server (without a base path).

This can only be called after either [`.startDevServer()`](#startdevserver) or [`.preview()`](#preview) is called.

### `pathExists`

<p>**Type:** `(path: string) => boolean`</p>

Checks whether the given path exists on the build output (`outDir` config).

### `readFile`

<p>
**Type:** `(path: string) => Promise<string>`
</p>

Read a file from the build (relative to `outDir` config).

### `editFile`

<p>
**Type:** `(path: string, updater: string | ((content: string) => string)) => Promise<() => void>`
</p>

Edit a file in the fixture directory.

The first parameter is a path relative to the root of the fixture.

The second parameter can be the new content of the file or a function that takes the current content and returns the new content.

This function returns a Promise that resolves to another function. This resolved function can be called to revert the changes.

All changes made with `editFile` are automatically reverted before the [process exits](https://nodejs.org/api/process.html#event-exit).

### `resetAllFiles`

<p>**Type:** `() => void`</p>

Reset all changes made with [`.editFile()`](#editfile)

### `readdir`

<p>
**Type:** `(path: string) => Promise<string[]>`
</p>

Read a directory from the build output (relative to `outDir` config).

This is a convenience wrapper around [readdir from Node's FS Promise API](https://nodejs.org/api/fs.html#fspromisesreaddirpath-options).

### `glob`

<p>
**Type:** `(pattern: string) => Promise<string[]>`
</p>

### `loadTestAdapterApp`
Find entries in the build output matching the glob pattern.

The glob syntax used is from [`fast-glob`](https://www.npmjs.com/package/fast-glob#pattern-syntax).

### `loadNodeAdapterHandler`

{(

<p>
**Type:** `() => Promise<App>`
<strong>Type: </strong>
<code dir="auto" style="padding-right: 0;">
() =&gt; Promise&lt;(req:{' '}
</code>
<a href="https://nodejs.org/api/http.html#class-httpincomingmessage">
<code dir="auto" style="padding-left: 0;padding-right: 0;">
http.IncomingMessage
</code>
</a>
<code dir="auto" style="padding-left: 0;padding-right: 0;">
, res:{' '}
</code>
<a href="https://nodejs.org/api/http.html#class-httpserverresponse">
<code dir="auto" style="padding-left: 0;padding-right: 0;">
http.ServerResponse
</code>
</a>
<code dir="auto" style="padding-left: 0;">
) =&gt; void&gt;
</code>
</p>
)}

### `loadNodeAdapterHandler`
Load the handler for an app built using the [Node Adapter](https://docs.astro.build/en/guides/integrations-guide/node/).

The handler is the same as a listener for the [`request` event](https://nodejs.org/api/http.html#event-request) from Node's native HTTP module.

### `loadTestAdapterApp`

<p>
**Type:** `() => Promise<(req: NodeRequest, res: NodeResponse) => void>`
**Type:** `() => Promise<TestApp>`
</p>

#### `TestApp`

```ts
type TestApp = {
render: (req: Request) => Promise<Response>;
toInternalApp: () => App;
};
```

A minimal proxy to the underlying Astro App using the test adapter.

##### `render`

Renders a [`Response`](https://developer.mozilla.org/en-US/docs/Web/API/Response) from the given [`Request`](https://developer.mozilla.org/en-US/docs/Web/API/Request).

##### `toInternalApp`

Returns the underlying [Astro App](https://github.com/withastro/astro/blob/ca54e3f819fad009ac3c3c8b57a26014a2652a73/packages/astro/src/core/app/index.ts#L77-L518).

:::danger
This class is internal, undocumented and highly unstable. Use it at your own risk.
:::

## Test Adapter

### `env`
An [Astro Adapter](https://docs.astro.build/en/guides/server-side-rendering/) that exposes the rendering process to be called directly.

### `provideAddress`
It also collects information about the build passed to the adapter to be inspected.

### `extendAdapter`
None of the options are required.

### `setEntryPoints`
### `env`

### `setMiddlewareEntryPoint`
<p>
**Type:** `Record<string, string | undefined>`
</p>

Server-side environment variables to be used by [`astro:env`](https://docs.astro.build/en/reference/configuration-reference/#experimentalenv).

### `setRoutes`

{(

<p>
<strong>Type: </strong>
<code dir="auto" style="padding-right: 0;">
(routes:{' '}
</code>
<a href="https://docs.astro.build/en/reference/integrations-reference/#routedata-type-reference">
<code dir="auto" style="padding-left: 0;padding-right: 0;">
RouteData
</code>
</a>
<code dir="auto" style="padding-left: 0;">
[]) =&gt; Promise&lt;void&gt;
</code>
</p>
)}

A callback function that will receive the final value of the project routes.

## Utilities

### No Node checker

[advanted APIs]: https://docs.astro.build/en/reference/cli-reference/#advanced-apis-experimental
A Vite plugin to ensure no module in the final bundle relies on the built-in Node modules.

If the generated bundle contains any reference to a Node module the build will fail.

The checked modules are those from the built-in module list provided as [part of `node:modules`](https://nodejs.org/api/module.html#modulebuiltinmodules), both with an without the `node:` prefix, as well as the [prefix-only modules](https://nodejs.org/api/modules.html#built-in-modules-with-mandatory-node-prefix).
58 changes: 42 additions & 16 deletions packages/astro-tests/src/astroFixture.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ import { build, dev, preview, sync } from 'astro';
import type { AstroConfig, AstroInlineConfig } from 'astro';
import { mergeConfig } from '../node_modules/astro/dist/core/config/merge.js';
import { validateConfig } from '../node_modules/astro/dist/core/config/validate.js';
import type { App } from 'astro/app';
import { getViteConfig } from 'astro/config';
import { callsites } from './utils.js';
import type { App } from 'astro/app';

// Disable telemetry when running tests
process.env.ASTRO_TELEMETRY_DISABLED = 'true';
Expand All @@ -20,6 +20,11 @@ export type NodeResponse = import('node:http').ServerResponse;
export type DevServer = Awaited<ReturnType<typeof dev>>;
export type PreviewServer = Awaited<ReturnType<typeof preview>>;

type TestApp = {
render: (req: Request) => Promise<Response>;
toInternalApp: () => App;
};

type Fixture = {
/**
* Returns the final config.
Expand Down Expand Up @@ -62,17 +67,25 @@ type Fixture = {
sync: typeof sync;

/**
* Removes the project's dist folder.
* Removes generated directories from the fixture directory.
*/
clean: () => Promise<void>;
/**
* Resolves a relative URL to the full url of the running server.
*
* This can only be called after either .startDevServer() or .preview() is called.
*/
resolveUrl: (url: string) => string;
/**
* Returns a URL from the running server.
* Send a request to the given URL. If the URL is relative, it will be resolved relative to the root of the server (without a base path).
*
* Must have called .dev() or .preview() before.
* This can only be called after either .startDevServer() or .preview() is called.
*/
fetch: (url: string, opts?: Parameters<typeof request>[1]) => Promise<Response>;

/**
* Checks whether the given path exists on the build output.
*/
pathExists: (path: string) => boolean;
/**
* Read a file from the build.
Expand All @@ -92,7 +105,7 @@ type Fixture = {
*/
resetAllFiles: () => void;
/**
* Read a directory from the build.
* Read a directory from the build output.
*/
readdir: (path: string) => Promise<string[]>;

Expand All @@ -103,9 +116,9 @@ type Fixture = {
/**
* Load an app built using the Test Adapter.
*/
loadTestAdapterApp: () => Promise<App>;
loadTestAdapterApp: () => Promise<TestApp>;
/**
* Load an app built using the Node Adapter.
* Load the handler for an app built using the Node Adapter.
*/
loadNodeAdapterHandler: () => Promise<(req: NodeRequest, res: NodeResponse) => void>;
};
Expand Down Expand Up @@ -223,14 +236,24 @@ export async function loadFixture(inlineConfig: InlineConfig): Promise<Fixture>
recursive: true,
force: true,
});
const astroCache = new URL('./node_modules/.astro', config.root);
if (fs.existsSync(astroCache)) {
await fs.promises.rm(astroCache, {
maxRetries: 10,
recursive: true,
force: true,
});
}

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

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

await fs.promises.rm(new URL('./.astro', config.root), {
maxRetries: 10,
recursive: true,
force: true,
});
},
resolveUrl,
fetch: async (url, init) => {
Expand Down Expand Up @@ -311,7 +334,10 @@ export async function loadFixture(inlineConfig: InlineConfig): Promise<Fixture>
const { createApp, manifest } = await import(url.toString());
const app = createApp();
app.manifest = manifest;
return app;
return {
render: (req) => app.render(req),
toInternalApp: () => app,
};
},
loadNodeAdapterHandler: async () => {
const url = new URL(`./server/entry.mjs?id=${fixtureId}`, config.outDir);
Expand Down
11 changes: 9 additions & 2 deletions packages/astro-tests/src/noNodeModule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,20 @@
import type { Plugin } from 'vite';
import { builtinModules } from 'node:module';

const nodeModules = [
...builtinModules,
...builtinModules.map((modName) => `node:${modName}`),
'node:test',
'node:test/reporters',
'node:sea',
];

export function preventNodeBuiltinDependencyPlugin(): Plugin {
// Verifies that `astro:content` does not have a hard dependency on Node builtins.
// Verifies that the final bundle does not have a hard dependency on Node builtins.
// This is to verify it will run on Cloudflare and Deno
return {
name: 'verify-no-node-stuff',
generateBundle() {
const nodeModules = builtinModules.map((modName) => `node:${modName}`).concat(builtinModules);
nodeModules.forEach((name) => {
const mod = this.getModuleInfo(name);
if (mod) {
Expand Down
Loading

0 comments on commit 134b3d2

Please sign in to comment.