@dotpress/testing 2.0.0-alpha.3 → 2.0.0-alpha.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/chunk-MUWNILMA.js +51 -0
- package/dist/chunk-MUWNILMA.js.map +1 -0
- package/dist/conformance.d.ts +28 -0
- package/dist/conformance.js +1266 -0
- package/dist/conformance.js.map +1 -0
- package/dist/index.d.ts +17 -52
- package/dist/index.js +43 -1310
- package/dist/index.js.map +1 -1
- package/dist/target-BZC-J2SE.d.ts +25 -0
- package/package.json +7 -3
package/README.md
CHANGED
|
@@ -5,7 +5,7 @@ Testing helpers for [Dotpress](https://dotpress.dev): a test app in memory, the
|
|
|
5
5
|
> 🚧 Dotpress V2 is in alpha (`2.0.0-alpha`): the API may still change before 2.0.0.
|
|
6
6
|
|
|
7
7
|
```sh
|
|
8
|
-
npm install --save-dev @dotpress/testing
|
|
8
|
+
npm install --save-dev @dotpress/testing vitest
|
|
9
9
|
```
|
|
10
10
|
|
|
11
11
|
```ts
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
// src/logger.ts
|
|
2
|
+
var createMemoryLogger = () => {
|
|
3
|
+
const entries = [];
|
|
4
|
+
const create = () => ({
|
|
5
|
+
debug: (...args) => void entries.push({ level: "debug", args }),
|
|
6
|
+
info: (...args) => void entries.push({ level: "info", args }),
|
|
7
|
+
warn: (...args) => void entries.push({ level: "warn", args }),
|
|
8
|
+
error: (...args) => void entries.push({ level: "error", args }),
|
|
9
|
+
child: () => create()
|
|
10
|
+
});
|
|
11
|
+
return Object.assign(create(), { entries });
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
// src/request.ts
|
|
15
|
+
var toRequest = async (path, init) => {
|
|
16
|
+
const request = new Request(new URL(path, "http://localhost"), init);
|
|
17
|
+
if (!(init?.body instanceof FormData)) return request;
|
|
18
|
+
return new Request(request, { body: await request.arrayBuffer() });
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
// src/target.ts
|
|
22
|
+
var OPTIONS = ["close"];
|
|
23
|
+
var closeOf = (label, options, known = OPTIONS) => {
|
|
24
|
+
if (typeof options !== "object" || options === null) {
|
|
25
|
+
throw new TypeError(`${label}: options must be an object.`);
|
|
26
|
+
}
|
|
27
|
+
for (const key of Object.keys(options)) {
|
|
28
|
+
if (!known.includes(key)) {
|
|
29
|
+
throw new TypeError(`${label}: unknown option "${key}".`);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
return options.close ?? (async () => {
|
|
33
|
+
});
|
|
34
|
+
};
|
|
35
|
+
var createHttpTarget = (baseUrl, options = {}) => ({
|
|
36
|
+
fetch: (path, init) => fetch(new URL(path, baseUrl), init),
|
|
37
|
+
close: closeOf("createHttpTarget()", options)
|
|
38
|
+
});
|
|
39
|
+
var createFetchTarget = (handle, options = {}) => ({
|
|
40
|
+
fetch: async (path, init) => handle(await toRequest(path, init)),
|
|
41
|
+
close: closeOf("createFetchTarget()", options)
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
export {
|
|
45
|
+
createMemoryLogger,
|
|
46
|
+
toRequest,
|
|
47
|
+
closeOf,
|
|
48
|
+
createHttpTarget,
|
|
49
|
+
createFetchTarget
|
|
50
|
+
};
|
|
51
|
+
//# sourceMappingURL=chunk-MUWNILMA.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/logger.ts","../src/request.ts","../src/target.ts"],"sourcesContent":["import type { Logger } from '@dotpress/core'\n\nexport interface LogEntry {\n readonly level: 'debug' | 'info' | 'warn' | 'error'\n readonly args: readonly unknown[]\n}\n\nexport interface MemoryLogger extends Logger {\n /** Entries logged by this logger and its children. */\n readonly entries: LogEntry[]\n}\n\n/**\n * Logger that records entries instead of printing them.\n */\nexport const createMemoryLogger = (): MemoryLogger => {\n const entries: LogEntry[] = []\n\n const create = (): Logger => ({\n debug: (...args: unknown[]) => void entries.push({ level: 'debug', args }),\n info: (...args: unknown[]) => void entries.push({ level: 'info', args }),\n warn: (...args: unknown[]) => void entries.push({ level: 'warn', args }),\n error: (...args: unknown[]) => void entries.push({ level: 'error', args }),\n child: () => create(),\n })\n\n return Object.assign(create(), { entries })\n}\n","/**\n * Creates the request sent by an in-memory target. Form data bodies are\n * serialized first, as HTTP clients do: on Node.js 24, cancelling a body\n * built from a `FormData` (body limit) raises an unhandled rejection in\n * undici.\n */\nexport const toRequest = async (\n path: string,\n init?: RequestInit\n): Promise<Request> => {\n const request = new Request(new URL(path, 'http://localhost'), init)\n if (!(init?.body instanceof FormData)) return request\n return new Request(request, { body: await request.arrayBuffer() })\n}\n","import { toRequest } from './request.js'\n\n/**\n * Running application under test.\n */\nexport interface TestTarget {\n /** Sends a request to the application. `path` includes the query. */\n fetch(path: string, init?: RequestInit): Promise<Response>\n /** Stops the application. */\n close(): Promise<void>\n}\n\nexport interface TargetOptions {\n /** Stops the application. Defaults to doing nothing. */\n close?: () => Promise<void>\n}\n\nconst OPTIONS = ['close'] satisfies (keyof TargetOptions)[]\n\n/** Checks the options of a target, and returns its `close()`. */\nexport const closeOf = (\n label: string,\n options: TargetOptions,\n known: readonly string[] = OPTIONS\n): (() => Promise<void>) => {\n if (typeof options !== 'object' || options === null) {\n throw new TypeError(`${label}: options must be an object.`)\n }\n for (const key of Object.keys(options)) {\n if (!known.includes(key)) {\n throw new TypeError(`${label}: unknown option \"${key}\".`)\n }\n }\n return options.close ?? (async () => {})\n}\n\n/**\n * Target for adapters listening on an HTTP port.\n */\nexport const createHttpTarget = (\n baseUrl: string,\n options: TargetOptions = {}\n): TestTarget => ({\n fetch: (path, init) => fetch(new URL(path, baseUrl), init),\n close: closeOf('createHttpTarget()', options),\n})\n\n/**\n * Target for adapters handling Web requests in memory (`fetch()` of the\n * adapter, serverless handlers). `path` is relative to `http://localhost`.\n */\nexport const createFetchTarget = (\n handle: (request: Request) => Promise<Response>,\n options: TargetOptions = {}\n): TestTarget => ({\n fetch: async (path, init) => handle(await toRequest(path, init)),\n close: closeOf('createFetchTarget()', options),\n})\n"],"mappings":";AAeO,IAAM,qBAAqB,MAAoB;AACpD,QAAM,UAAsB,CAAC;AAE7B,QAAM,SAAS,OAAe;AAAA,IAC5B,OAAO,IAAI,SAAoB,KAAK,QAAQ,KAAK,EAAE,OAAO,SAAS,KAAK,CAAC;AAAA,IACzE,MAAM,IAAI,SAAoB,KAAK,QAAQ,KAAK,EAAE,OAAO,QAAQ,KAAK,CAAC;AAAA,IACvE,MAAM,IAAI,SAAoB,KAAK,QAAQ,KAAK,EAAE,OAAO,QAAQ,KAAK,CAAC;AAAA,IACvE,OAAO,IAAI,SAAoB,KAAK,QAAQ,KAAK,EAAE,OAAO,SAAS,KAAK,CAAC;AAAA,IACzE,OAAO,MAAM,OAAO;AAAA,EACtB;AAEA,SAAO,OAAO,OAAO,OAAO,GAAG,EAAE,QAAQ,CAAC;AAC5C;;;ACrBO,IAAM,YAAY,OACvB,MACA,SACqB;AACrB,QAAM,UAAU,IAAI,QAAQ,IAAI,IAAI,MAAM,kBAAkB,GAAG,IAAI;AACnE,MAAI,EAAE,MAAM,gBAAgB,UAAW,QAAO;AAC9C,SAAO,IAAI,QAAQ,SAAS,EAAE,MAAM,MAAM,QAAQ,YAAY,EAAE,CAAC;AACnE;;;ACIA,IAAM,UAAU,CAAC,OAAO;AAGjB,IAAM,UAAU,CACrB,OACA,SACA,QAA2B,YACD;AAC1B,MAAI,OAAO,YAAY,YAAY,YAAY,MAAM;AACnD,UAAM,IAAI,UAAU,GAAG,KAAK,8BAA8B;AAAA,EAC5D;AACA,aAAW,OAAO,OAAO,KAAK,OAAO,GAAG;AACtC,QAAI,CAAC,MAAM,SAAS,GAAG,GAAG;AACxB,YAAM,IAAI,UAAU,GAAG,KAAK,qBAAqB,GAAG,IAAI;AAAA,IAC1D;AAAA,EACF;AACA,SAAO,QAAQ,UAAU,YAAY;AAAA,EAAC;AACxC;AAKO,IAAM,mBAAmB,CAC9B,SACA,UAAyB,CAAC,OACV;AAAA,EAChB,OAAO,CAAC,MAAM,SAAS,MAAM,IAAI,IAAI,MAAM,OAAO,GAAG,IAAI;AAAA,EACzD,OAAO,QAAQ,sBAAsB,OAAO;AAC9C;AAMO,IAAM,oBAAoB,CAC/B,QACA,UAAyB,CAAC,OACV;AAAA,EAChB,OAAO,OAAO,MAAM,SAAS,OAAO,MAAM,UAAU,MAAM,IAAI,CAAC;AAAA,EAC/D,OAAO,QAAQ,uBAAuB,OAAO;AAC/C;","names":[]}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { AppOptions } from '@dotpress/core';
|
|
2
|
+
import { T as TestTarget } from './target-BZC-J2SE.js';
|
|
3
|
+
export { a as TargetOptions, c as createFetchTarget, b as createHttpTarget } from './target-BZC-J2SE.js';
|
|
4
|
+
|
|
5
|
+
type ConformanceAppOptions = Omit<AppOptions, 'adapter'>;
|
|
6
|
+
interface ConformanceSuiteOptions {
|
|
7
|
+
/** Adapter name, used in test titles. */
|
|
8
|
+
name: string;
|
|
9
|
+
/**
|
|
10
|
+
* Creates an app with the adapter under test and the given options, and
|
|
11
|
+
* starts it. Called once per test.
|
|
12
|
+
*/
|
|
13
|
+
setup(options: ConformanceAppOptions): Promise<TestTarget>;
|
|
14
|
+
/**
|
|
15
|
+
* The adapter sends responses once complete (AWS Lambda without response
|
|
16
|
+
* streaming). The scenarios that need incremental streaming or client
|
|
17
|
+
* disconnects are skipped.
|
|
18
|
+
*/
|
|
19
|
+
bufferedResponses?: boolean;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Registers the adapter conformance suite (vitest). An adapter is ready
|
|
23
|
+
* when it passes every test.
|
|
24
|
+
*/
|
|
25
|
+
declare const runConformanceSuite: (options: ConformanceSuiteOptions) => void;
|
|
26
|
+
|
|
27
|
+
export { TestTarget, runConformanceSuite };
|
|
28
|
+
export type { ConformanceAppOptions, ConformanceSuiteOptions };
|