@frida/injest 0.1.0
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/LICENSE.md +21 -0
- package/README.md +184 -0
- package/dist/agent/expect.d.ts +56 -0
- package/dist/agent/expect.d.ts.map +1 -0
- package/dist/agent/expect.js +235 -0
- package/dist/agent/expect.js.map +1 -0
- package/dist/agent/runtime.d.ts +29 -0
- package/dist/agent/runtime.d.ts.map +1 -0
- package/dist/agent/runtime.js +180 -0
- package/dist/agent/runtime.js.map +1 -0
- package/dist/host/bundle.d.ts +9 -0
- package/dist/host/bundle.d.ts.map +1 -0
- package/dist/host/bundle.js +95 -0
- package/dist/host/bundle.js.map +1 -0
- package/dist/host/cli.d.ts +3 -0
- package/dist/host/cli.d.ts.map +1 -0
- package/dist/host/cli.js +214 -0
- package/dist/host/cli.js.map +1 -0
- package/dist/host/config.d.ts +27 -0
- package/dist/host/config.d.ts.map +1 -0
- package/dist/host/config.js +35 -0
- package/dist/host/config.js.map +1 -0
- package/dist/host/index.d.ts +4 -0
- package/dist/host/index.d.ts.map +1 -0
- package/dist/host/index.js +3 -0
- package/dist/host/index.js.map +1 -0
- package/dist/host/run.d.ts +50 -0
- package/dist/host/run.d.ts.map +1 -0
- package/dist/host/run.js +270 -0
- package/dist/host/run.js.map +1 -0
- package/dist/host/session.d.ts +13 -0
- package/dist/host/session.d.ts.map +1 -0
- package/dist/host/session.js +55 -0
- package/dist/host/session.js.map +1 -0
- package/dist/host/source.d.ts +14 -0
- package/dist/host/source.d.ts.map +1 -0
- package/dist/host/source.js +83 -0
- package/dist/host/source.js.map +1 -0
- package/package.json +73 -0
- package/schema/injest.config.schema.json +92 -0
package/LICENSE.md
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Håvard Sørbø
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
# injest
|
|
2
|
+
|
|
3
|
+
The test runner for code that runs inside Frida's **GumJS** runtime — CLI + agent test API.
|
|
4
|
+
Point it at a target (device + session) in JSON; it bundles your tests with the code under
|
|
5
|
+
test, injects them, runs the suite in GumJS, and reports to the terminal or as NDJSON.
|
|
6
|
+
Subject- and target-agnostic: anything that runs in GumJS works.
|
|
7
|
+
|
|
8
|
+
## Quick start
|
|
9
|
+
|
|
10
|
+
In the project under test, add `injest` and a config:
|
|
11
|
+
|
|
12
|
+
```jsonc
|
|
13
|
+
// package.json
|
|
14
|
+
{ "type": "module", "devDependencies": { "@frida/injest": "^0.1.0" } }
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
```jsonc
|
|
18
|
+
// injest.config.json
|
|
19
|
+
{ "default": "local", "targets": { "local": { "device": "local", "session": "system" } } }
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
```ts
|
|
23
|
+
// tests/example.test.ts
|
|
24
|
+
import { test, expect } from "@frida/injest/agent";
|
|
25
|
+
|
|
26
|
+
test("platform must be linux", () => {
|
|
27
|
+
expect(Process.platform).toBe("linux");
|
|
28
|
+
});
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
```sh
|
|
32
|
+
npx injest --target local
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
> Test files are discovered from `tests/**/*.test.{ts,js}` by default — set `include`/`exclude`
|
|
36
|
+
> in the config to put them elsewhere (e.g. colocated `src/**/*.test.ts`). The runner writes a
|
|
37
|
+
> temporary `.injest-*` build dir in the project; add `.injest-*` to your `.gitignore`.
|
|
38
|
+
|
|
39
|
+
## Targets
|
|
40
|
+
|
|
41
|
+
A target is a **device** + **session**, with an optional **runtime**:
|
|
42
|
+
|
|
43
|
+
```jsonc
|
|
44
|
+
{
|
|
45
|
+
"default": "local",
|
|
46
|
+
"targets": {
|
|
47
|
+
"local": { "device": "local", "session": "system" },
|
|
48
|
+
"local-v8": { "device": "local", "session": "system", "runtime": "v8" },
|
|
49
|
+
"usb": { "device": "usb", "session": "system" },
|
|
50
|
+
"phone": { "device": { "id": "<udid>" }, "session": "system" },
|
|
51
|
+
"app": { "device": { "id": "<udid>" }, "session": { "spawn": "<bundle-id>" } },
|
|
52
|
+
},
|
|
53
|
+
// optional — where test files live (defaults to ["tests/**/*.test.{ts,js}"])
|
|
54
|
+
"include": ["tests/**/*.test.ts"],
|
|
55
|
+
"exclude": ["tests/wip/**"],
|
|
56
|
+
}
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
- `device`: `"local"`, `"usb"` (first USB device), or `{ "id": "<udid>" }` (a specific
|
|
60
|
+
device).
|
|
61
|
+
- `session`: `"system"` or `{ "spawn": "<program-or-bundle-id>", "args": [...] }`.
|
|
62
|
+
- `runtime`: `qjs` (default) or `v8`.
|
|
63
|
+
- `timeout`: default per-test timeout in ms (default `10000`); a test can override it with
|
|
64
|
+
`test(name, fn, { timeout })`.
|
|
65
|
+
|
|
66
|
+
## Test discovery
|
|
67
|
+
|
|
68
|
+
Test files are matched by the `include` globs in the config (default
|
|
69
|
+
`["tests/**/*.test.{ts,js}"]`), minus any `exclude` globs. Globs are matched against
|
|
70
|
+
project-relative paths and support `**`, `*`, `?`, and `{a,b}` alternation;
|
|
71
|
+
`node_modules` and dot-directories are always skipped. Positional CLI args narrow the
|
|
72
|
+
matched files further by path substring.
|
|
73
|
+
|
|
74
|
+
## Selecting tests
|
|
75
|
+
|
|
76
|
+
```sh
|
|
77
|
+
npx injest foo # files whose path contains "foo"
|
|
78
|
+
npx injest -t "digest" # tests whose name matches the regex
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
The GumJS runtime is a property of the target (`runtime`, default `qjs`); to run
|
|
82
|
+
the suite on both, define one target per runtime.
|
|
83
|
+
|
|
84
|
+
```ts
|
|
85
|
+
test.skip("park", () => {});
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## Launch modes
|
|
89
|
+
|
|
90
|
+
Tests share one session by default. A test can opt into its own fresh process — required
|
|
91
|
+
for tests that mutate global/native state or need launch-time control. Both forms need a
|
|
92
|
+
`spawn` target; on a non-spawnable target (e.g. `system`) they're reported skipped.
|
|
93
|
+
|
|
94
|
+
```ts
|
|
95
|
+
// own fresh spawn, killed afterwards — isolation is by process, not cleanup
|
|
96
|
+
test.isolated("runs in a clean process", () => {
|
|
97
|
+
expect(Process.mainModule.name.length > 0).toBeTruthy();
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
// spawn starts suspended: instrument before the app runs, then resume() it.
|
|
101
|
+
// `resume` is injected — it exists only in this launch mode.
|
|
102
|
+
test.suspended("hooks before main runs", async ({ resume }) => {
|
|
103
|
+
const open = Module.getGlobalExportByName("open");
|
|
104
|
+
const fired = new Promise<void>((done) => {
|
|
105
|
+
Interceptor.attach(open, { onEnter: () => done() });
|
|
106
|
+
});
|
|
107
|
+
await resume();
|
|
108
|
+
await fired;
|
|
109
|
+
});
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
A test can also bail out at runtime via the injected `skip`, reporting itself skipped
|
|
113
|
+
(not a false pass) with an optional reason:
|
|
114
|
+
|
|
115
|
+
```ts
|
|
116
|
+
test("apple-silicon only", ({ skip }) => {
|
|
117
|
+
if (Process.arch !== "arm64") skip(`needs arm64, got ${Process.arch}`);
|
|
118
|
+
expect(Process.pointerSize).toBe(8);
|
|
119
|
+
});
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
## CLI
|
|
123
|
+
|
|
124
|
+
```
|
|
125
|
+
injest [file-filters...] [options]
|
|
126
|
+
|
|
127
|
+
--target <name> target profile (else "default")
|
|
128
|
+
-c, --config <path> config file (default: ./injest.config.json)
|
|
129
|
+
-t, --testNamePattern <re> run only tests whose name matches
|
|
130
|
+
--only <id> run only the test(s) with this stable id (repeatable)
|
|
131
|
+
--reporter <pretty|json> output format (json = NDJSON on stdout)
|
|
132
|
+
--list list tests (id, location) without running
|
|
133
|
+
-h, --help show help
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
## Test API (`@frida/injest/agent`)
|
|
137
|
+
|
|
138
|
+
- `test(name, fn, opts?)` — register a test; may be `async`. `opts.launch` is
|
|
139
|
+
`"shared"` (default) | `"isolated"` | `"suspended"`; `opts.timeout` (ms) overrides the
|
|
140
|
+
target's default timeout for this test.
|
|
141
|
+
- `test.skip` — statically skip a test.
|
|
142
|
+
- `test.isolated(name, fn, opts?)` — run in a fresh spawn, killed afterwards.
|
|
143
|
+
- `test.suspended(name, async ({ resume }) => …, opts?)` — run in a spawn started suspended;
|
|
144
|
+
call the injected `resume()` to release the main thread.
|
|
145
|
+
- `describe(label, fn)` — group tests; names are qualified (`label › test`) and groups nest.
|
|
146
|
+
- `beforeEach(fn)` / `afterEach(fn)` — run around each test in the enclosing `describe`
|
|
147
|
+
(and any nested one). `beforeEach` runs outermost→innermost; `afterEach` unwinds
|
|
148
|
+
innermost→outermost and always runs (for cleanup) even when the test fails. A throwing
|
|
149
|
+
hook fails the test; a `beforeEach` failure skips the body, an `afterEach` failure fails
|
|
150
|
+
an otherwise-passing test.
|
|
151
|
+
- Every `fn` receives a context: `({ skip })` for normal tests, `({ skip, resume })` for
|
|
152
|
+
`suspended`. `skip(reason?)` reports the test as skipped at runtime. Hooks receive no
|
|
153
|
+
context.
|
|
154
|
+
- `expect(value)` matchers:
|
|
155
|
+
- equality / truthiness: `toBe`, `toEqual` (structural deep equality), `toBeTruthy`,
|
|
156
|
+
`toBeFalsy`, `toBeNull`, `toBeUndefined`, `toBeDefined`, `toBeNaN`.
|
|
157
|
+
- numbers: `toBeGreaterThan`, `toBeGreaterThanOrEqual`, `toBeLessThan`,
|
|
158
|
+
`toBeLessThanOrEqual`, `toBeCloseTo(n, numDigits = 2)`.
|
|
159
|
+
- strings / collections: `toContain` (string substring or array member), `toMatch`
|
|
160
|
+
(regex or substring), `toHaveLength`.
|
|
161
|
+
- `toThrow(expected?)` — `expected` may be a message substring, a `RegExp` matched
|
|
162
|
+
against the message, or an error class (`instanceof`).
|
|
163
|
+
- `.not` negates any matcher; `.rejects` / `.resolves` await a promise and apply the
|
|
164
|
+
matcher to the rejection reason / resolved value (e.g.
|
|
165
|
+
`await expect(p).rejects.toThrow("boom")`).
|
|
166
|
+
- `toBe`/`toEqual` failures carry `expected`/`actual` for editor diffs.
|
|
167
|
+
|
|
168
|
+
## JSON output
|
|
169
|
+
|
|
170
|
+
`--reporter json` emits one object per line on stdout (diagnostics on stderr):
|
|
171
|
+
|
|
172
|
+
```
|
|
173
|
+
{"type":"start","total":2}
|
|
174
|
+
{"type":"output","level":"info","text":"hello","name":"…","file":"tests/x.test.ts","line":10}
|
|
175
|
+
{"type":"test","name":"…","status":"passed","durationMs":0,"file":"tests/x.test.ts","line":10}
|
|
176
|
+
{"type":"test","name":"boom","status":"failed","durationMs":1,"file":"tests/x.test.ts","line":12,"error":{"name":"AssertionError","message":"…","expected":"…","actual":"…"}}
|
|
177
|
+
{"type":"end","passed":1,"failed":1,"skipped":0,"total":2}
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
`status`: `passed | failed | skipped | timeout | crashed | incomplete`. `console.*` from a
|
|
181
|
+
test is streamed live as `{"type":"output",…}` between that test's events (with `name`/`file`
|
|
182
|
+
absent for output emitted outside any test). `--list --reporter json` emits
|
|
183
|
+
`{"type":"list","tests":[…]}`. Exit code is non-zero on any failure/timeout/crash/incomplete;
|
|
184
|
+
`skipped` never fails the run.
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
export declare class AssertionError extends Error {
|
|
2
|
+
readonly expected?: string;
|
|
3
|
+
readonly actual?: string;
|
|
4
|
+
readonly operator?: string;
|
|
5
|
+
readonly showDiff: boolean;
|
|
6
|
+
constructor(message: string, detail?: {
|
|
7
|
+
expected: unknown;
|
|
8
|
+
actual: unknown;
|
|
9
|
+
operator: string;
|
|
10
|
+
});
|
|
11
|
+
}
|
|
12
|
+
export type ThrowMatcher = string | RegExp | (new (...args: never[]) => unknown) | Error;
|
|
13
|
+
export interface Matchers {
|
|
14
|
+
toBe(expected: unknown): void;
|
|
15
|
+
toEqual(expected: unknown): void;
|
|
16
|
+
toBeTruthy(): void;
|
|
17
|
+
toBeFalsy(): void;
|
|
18
|
+
toBeNull(): void;
|
|
19
|
+
toBeUndefined(): void;
|
|
20
|
+
toBeDefined(): void;
|
|
21
|
+
toBeNaN(): void;
|
|
22
|
+
toBeGreaterThan(n: number): void;
|
|
23
|
+
toBeGreaterThanOrEqual(n: number): void;
|
|
24
|
+
toBeLessThan(n: number): void;
|
|
25
|
+
toBeLessThanOrEqual(n: number): void;
|
|
26
|
+
toBeCloseTo(n: number, numDigits?: number): void;
|
|
27
|
+
toContain(item: unknown): void;
|
|
28
|
+
toMatch(expected: string | RegExp): void;
|
|
29
|
+
toHaveLength(length: number): void;
|
|
30
|
+
toThrow(expected?: ThrowMatcher): void;
|
|
31
|
+
readonly not: Matchers;
|
|
32
|
+
readonly rejects: AsyncMatchers;
|
|
33
|
+
readonly resolves: AsyncMatchers;
|
|
34
|
+
}
|
|
35
|
+
export interface AsyncMatchers {
|
|
36
|
+
toBe(expected: unknown): Promise<void>;
|
|
37
|
+
toEqual(expected: unknown): Promise<void>;
|
|
38
|
+
toBeTruthy(): Promise<void>;
|
|
39
|
+
toBeFalsy(): Promise<void>;
|
|
40
|
+
toBeNull(): Promise<void>;
|
|
41
|
+
toBeUndefined(): Promise<void>;
|
|
42
|
+
toBeDefined(): Promise<void>;
|
|
43
|
+
toBeNaN(): Promise<void>;
|
|
44
|
+
toBeGreaterThan(n: number): Promise<void>;
|
|
45
|
+
toBeGreaterThanOrEqual(n: number): Promise<void>;
|
|
46
|
+
toBeLessThan(n: number): Promise<void>;
|
|
47
|
+
toBeLessThanOrEqual(n: number): Promise<void>;
|
|
48
|
+
toBeCloseTo(n: number, numDigits?: number): Promise<void>;
|
|
49
|
+
toContain(item: unknown): Promise<void>;
|
|
50
|
+
toMatch(expected: string | RegExp): Promise<void>;
|
|
51
|
+
toHaveLength(length: number): Promise<void>;
|
|
52
|
+
toThrow(expected?: ThrowMatcher): Promise<void>;
|
|
53
|
+
readonly not: AsyncMatchers;
|
|
54
|
+
}
|
|
55
|
+
export declare function expect(actual: unknown): Matchers;
|
|
56
|
+
//# sourceMappingURL=expect.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"expect.d.ts","sourceRoot":"","sources":["../../src/agent/expect.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
import deepEqual from "deep-eql";
|
|
2
|
+
export class AssertionError extends Error {
|
|
3
|
+
expected;
|
|
4
|
+
actual;
|
|
5
|
+
operator;
|
|
6
|
+
showDiff;
|
|
7
|
+
constructor(message, detail) {
|
|
8
|
+
super(message);
|
|
9
|
+
this.name = "AssertionError";
|
|
10
|
+
if (detail) {
|
|
11
|
+
this.expected = fmtDiff(detail.expected);
|
|
12
|
+
this.actual = fmtDiff(detail.actual);
|
|
13
|
+
this.operator = detail.operator;
|
|
14
|
+
this.showDiff = true;
|
|
15
|
+
}
|
|
16
|
+
else {
|
|
17
|
+
this.showDiff = false;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
export function expect(actual) {
|
|
22
|
+
return makeMatchers(actual, false);
|
|
23
|
+
}
|
|
24
|
+
function makeMatchers(actual, negated) {
|
|
25
|
+
const check = (pass, summary, detail) => {
|
|
26
|
+
if (pass !== negated)
|
|
27
|
+
return;
|
|
28
|
+
const verb = negated ? `not ${summary}` : summary;
|
|
29
|
+
throw new AssertionError(`expected ${fmt(actual)} ${verb}`, negated ? undefined : detail);
|
|
30
|
+
};
|
|
31
|
+
const asNumber = () => {
|
|
32
|
+
if (typeof actual !== "number") {
|
|
33
|
+
throw new AssertionError(`expected a number, got ${fmt(actual)}`);
|
|
34
|
+
}
|
|
35
|
+
return actual;
|
|
36
|
+
};
|
|
37
|
+
return {
|
|
38
|
+
toBe(expected) {
|
|
39
|
+
check(actual === expected, `to be ${fmt(expected)}`, { expected, actual, operator: "toBe" });
|
|
40
|
+
},
|
|
41
|
+
toEqual(expected) {
|
|
42
|
+
check(deepEqual(actual, expected), `to equal ${fmt(expected)}`, {
|
|
43
|
+
expected,
|
|
44
|
+
actual,
|
|
45
|
+
operator: "toEqual",
|
|
46
|
+
});
|
|
47
|
+
},
|
|
48
|
+
toBeTruthy() {
|
|
49
|
+
check(!!actual, "to be truthy");
|
|
50
|
+
},
|
|
51
|
+
toBeFalsy() {
|
|
52
|
+
check(!actual, "to be falsy");
|
|
53
|
+
},
|
|
54
|
+
toBeNull() {
|
|
55
|
+
check(actual === null, "to be null");
|
|
56
|
+
},
|
|
57
|
+
toBeUndefined() {
|
|
58
|
+
check(actual === undefined, "to be undefined");
|
|
59
|
+
},
|
|
60
|
+
toBeDefined() {
|
|
61
|
+
check(actual !== undefined, "to be defined");
|
|
62
|
+
},
|
|
63
|
+
toBeNaN() {
|
|
64
|
+
check(typeof actual === "number" && Number.isNaN(actual), "to be NaN");
|
|
65
|
+
},
|
|
66
|
+
toBeGreaterThan(n) {
|
|
67
|
+
check(asNumber() > n, `to be greater than ${fmt(n)}`);
|
|
68
|
+
},
|
|
69
|
+
toBeGreaterThanOrEqual(n) {
|
|
70
|
+
check(asNumber() >= n, `to be greater than or equal to ${fmt(n)}`);
|
|
71
|
+
},
|
|
72
|
+
toBeLessThan(n) {
|
|
73
|
+
check(asNumber() < n, `to be less than ${fmt(n)}`);
|
|
74
|
+
},
|
|
75
|
+
toBeLessThanOrEqual(n) {
|
|
76
|
+
check(asNumber() <= n, `to be less than or equal to ${fmt(n)}`);
|
|
77
|
+
},
|
|
78
|
+
toBeCloseTo(n, numDigits = 2) {
|
|
79
|
+
const tolerance = Math.pow(10, -numDigits) / 2;
|
|
80
|
+
check(Math.abs(asNumber() - n) < tolerance, `to be close to ${fmt(n)} (±${tolerance})`);
|
|
81
|
+
},
|
|
82
|
+
toContain(item) {
|
|
83
|
+
if (typeof actual !== "string" && !Array.isArray(actual)) {
|
|
84
|
+
throw new AssertionError(`toContain() expects a string or array, got ${fmt(actual)}`);
|
|
85
|
+
}
|
|
86
|
+
const has = typeof actual === "string" ? actual.includes(String(item)) : actual.includes(item);
|
|
87
|
+
check(has, `to contain ${fmt(item)}`);
|
|
88
|
+
},
|
|
89
|
+
toMatch(expected) {
|
|
90
|
+
if (typeof actual !== "string") {
|
|
91
|
+
throw new AssertionError(`toMatch() expects a string, got ${fmt(actual)}`);
|
|
92
|
+
}
|
|
93
|
+
const matched = expected instanceof RegExp ? expected.test(actual) : actual.includes(expected);
|
|
94
|
+
check(matched, `to match ${describeMatch(expected)}`);
|
|
95
|
+
},
|
|
96
|
+
toHaveLength(length) {
|
|
97
|
+
const len = actual?.length;
|
|
98
|
+
if (typeof len !== "number") {
|
|
99
|
+
throw new AssertionError(`toHaveLength() expects a value with a numeric length, got ${fmt(actual)}`);
|
|
100
|
+
}
|
|
101
|
+
check(len === length, `to have length ${fmt(length)} (got ${len})`);
|
|
102
|
+
},
|
|
103
|
+
toThrow(expected) {
|
|
104
|
+
if (typeof actual !== "function") {
|
|
105
|
+
throw new AssertionError("toThrow() expects a function");
|
|
106
|
+
}
|
|
107
|
+
let thrown;
|
|
108
|
+
let threw = false;
|
|
109
|
+
try {
|
|
110
|
+
actual();
|
|
111
|
+
}
|
|
112
|
+
catch (e) {
|
|
113
|
+
threw = true;
|
|
114
|
+
thrown = e;
|
|
115
|
+
}
|
|
116
|
+
checkThrow("function", threw, thrown, expected, negated);
|
|
117
|
+
},
|
|
118
|
+
get not() {
|
|
119
|
+
return makeMatchers(actual, !negated);
|
|
120
|
+
},
|
|
121
|
+
get rejects() {
|
|
122
|
+
return makeAsync(actual, true, negated);
|
|
123
|
+
},
|
|
124
|
+
get resolves() {
|
|
125
|
+
return makeAsync(actual, false, negated);
|
|
126
|
+
},
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
function makeAsync(subject, expectRejection, negated) {
|
|
130
|
+
const settle = async () => {
|
|
131
|
+
let value;
|
|
132
|
+
let reason;
|
|
133
|
+
let threw = false;
|
|
134
|
+
try {
|
|
135
|
+
value = await subject;
|
|
136
|
+
}
|
|
137
|
+
catch (e) {
|
|
138
|
+
threw = true;
|
|
139
|
+
reason = e;
|
|
140
|
+
}
|
|
141
|
+
if (expectRejection && !threw) {
|
|
142
|
+
throw new AssertionError(`expected promise to reject, but it resolved with ${fmt(value)}`);
|
|
143
|
+
}
|
|
144
|
+
if (!expectRejection && threw) {
|
|
145
|
+
throw new AssertionError(`expected promise to resolve, but it rejected with ${fmt(reason)}`);
|
|
146
|
+
}
|
|
147
|
+
return expectRejection ? reason : value;
|
|
148
|
+
};
|
|
149
|
+
const settled = async () => makeMatchers(await settle(), negated);
|
|
150
|
+
return {
|
|
151
|
+
toBe: async (expected) => (await settled()).toBe(expected),
|
|
152
|
+
toEqual: async (expected) => (await settled()).toEqual(expected),
|
|
153
|
+
toBeTruthy: async () => (await settled()).toBeTruthy(),
|
|
154
|
+
toBeFalsy: async () => (await settled()).toBeFalsy(),
|
|
155
|
+
toBeNull: async () => (await settled()).toBeNull(),
|
|
156
|
+
toBeUndefined: async () => (await settled()).toBeUndefined(),
|
|
157
|
+
toBeDefined: async () => (await settled()).toBeDefined(),
|
|
158
|
+
toBeNaN: async () => (await settled()).toBeNaN(),
|
|
159
|
+
toBeGreaterThan: async (n) => (await settled()).toBeGreaterThan(n),
|
|
160
|
+
toBeGreaterThanOrEqual: async (n) => (await settled()).toBeGreaterThanOrEqual(n),
|
|
161
|
+
toBeLessThan: async (n) => (await settled()).toBeLessThan(n),
|
|
162
|
+
toBeLessThanOrEqual: async (n) => (await settled()).toBeLessThanOrEqual(n),
|
|
163
|
+
toBeCloseTo: async (n, numDigits) => (await settled()).toBeCloseTo(n, numDigits),
|
|
164
|
+
toContain: async (item) => (await settled()).toContain(item),
|
|
165
|
+
toMatch: async (expected) => (await settled()).toMatch(expected),
|
|
166
|
+
toHaveLength: async (length) => (await settled()).toHaveLength(length),
|
|
167
|
+
toThrow: async (expected) => {
|
|
168
|
+
const reason = await settle();
|
|
169
|
+
if (expected === undefined)
|
|
170
|
+
return;
|
|
171
|
+
const pass = errorMatches(reason, expected);
|
|
172
|
+
if (pass === negated) {
|
|
173
|
+
const verb = negated ? "not to match" : "to match";
|
|
174
|
+
throw new AssertionError(`expected rejection ${verb} ${describeThrow(expected)}, got ${fmt(reason)}`);
|
|
175
|
+
}
|
|
176
|
+
},
|
|
177
|
+
get not() {
|
|
178
|
+
return makeAsync(subject, expectRejection, !negated);
|
|
179
|
+
},
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
function checkThrow(subject, threw, thrown, expected, negated) {
|
|
183
|
+
const pass = threw && errorMatches(thrown, expected);
|
|
184
|
+
if (pass !== negated)
|
|
185
|
+
return;
|
|
186
|
+
const what = expected !== undefined ? ` ${describeThrow(expected)}` : "";
|
|
187
|
+
const verb = negated ? `not to throw${what}` : `to throw${what}`;
|
|
188
|
+
const got = threw && expected !== undefined ? `, threw ${fmt(thrown)}` : "";
|
|
189
|
+
throw new AssertionError(`expected ${subject} ${verb}${got}`);
|
|
190
|
+
}
|
|
191
|
+
function errorMatches(thrown, expected) {
|
|
192
|
+
if (expected === undefined)
|
|
193
|
+
return true;
|
|
194
|
+
const message = thrown instanceof Error ? thrown.message : String(thrown);
|
|
195
|
+
if (typeof expected === "string")
|
|
196
|
+
return message.includes(expected);
|
|
197
|
+
if (expected instanceof RegExp)
|
|
198
|
+
return expected.test(message);
|
|
199
|
+
if (typeof expected === "function")
|
|
200
|
+
return thrown instanceof expected;
|
|
201
|
+
if (expected instanceof Error)
|
|
202
|
+
return message === expected.message;
|
|
203
|
+
return false;
|
|
204
|
+
}
|
|
205
|
+
function describeThrow(expected) {
|
|
206
|
+
if (typeof expected === "string")
|
|
207
|
+
return JSON.stringify(expected);
|
|
208
|
+
if (expected instanceof RegExp)
|
|
209
|
+
return String(expected);
|
|
210
|
+
if (typeof expected === "function")
|
|
211
|
+
return expected.name || "Error";
|
|
212
|
+
if (expected instanceof Error)
|
|
213
|
+
return JSON.stringify(expected.message);
|
|
214
|
+
return String(expected);
|
|
215
|
+
}
|
|
216
|
+
function describeMatch(expected) {
|
|
217
|
+
return expected instanceof RegExp ? String(expected) : fmt(expected);
|
|
218
|
+
}
|
|
219
|
+
function fmt(value) {
|
|
220
|
+
try {
|
|
221
|
+
return JSON.stringify(value) ?? String(value);
|
|
222
|
+
}
|
|
223
|
+
catch {
|
|
224
|
+
return String(value);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
function fmtDiff(value) {
|
|
228
|
+
try {
|
|
229
|
+
return JSON.stringify(value, null, 2) ?? String(value);
|
|
230
|
+
}
|
|
231
|
+
catch {
|
|
232
|
+
return String(value);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
//# sourceMappingURL=expect.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"expect.js","sourceRoot":"","sources":["../../src/agent/expect.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export { expect } from "./expect.js";
|
|
2
|
+
export interface TestContext {
|
|
3
|
+
skip: (reason?: string) => never;
|
|
4
|
+
}
|
|
5
|
+
export type TestFn = (ctx: TestContext) => void | Promise<void>;
|
|
6
|
+
export interface SuspendedContext extends TestContext {
|
|
7
|
+
resume: () => Promise<void>;
|
|
8
|
+
}
|
|
9
|
+
export type SuspendedFn = (ctx: SuspendedContext) => void | Promise<void>;
|
|
10
|
+
export type Launch = "shared" | "isolated" | "suspended";
|
|
11
|
+
export interface TestOptions {
|
|
12
|
+
launch?: Launch;
|
|
13
|
+
timeout?: number;
|
|
14
|
+
}
|
|
15
|
+
type Thunk = () => void | Promise<void>;
|
|
16
|
+
export interface RunOptions {
|
|
17
|
+
grep?: string;
|
|
18
|
+
only?: number[];
|
|
19
|
+
}
|
|
20
|
+
export declare function describe(label: string, fn: () => void): void;
|
|
21
|
+
export declare function beforeEach(fn: Thunk): void;
|
|
22
|
+
export declare function afterEach(fn: Thunk): void;
|
|
23
|
+
export declare const test: ((name: string, fn: TestFn, opts?: TestOptions) => void) & {
|
|
24
|
+
skip: (name: string, fn: TestFn, opts?: TestOptions) => void;
|
|
25
|
+
isolated: (name: string, fn: TestFn, opts?: TestOptions) => void;
|
|
26
|
+
suspended: (name: string, fn: SuspendedFn, opts?: TestOptions) => void;
|
|
27
|
+
};
|
|
28
|
+
export declare function run(options?: RunOptions): Promise<void>;
|
|
29
|
+
//# sourceMappingURL=runtime.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../src/agent/runtime.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,CAAC,MAAM,CAAC,EAAE,MAAM,KAAK,KAAK,CAAC;CAClC;AAED,MAAM,MAAM,MAAM,GAAG,CAAC,GAAG,EAAE,WAAW,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AAEhE,MAAM,WAAW,gBAAiB,SAAQ,WAAW;IACnD,MAAM,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC7B;AAED,MAAM,MAAM,WAAW,GAAG,CAAC,GAAG,EAAE,gBAAgB,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AAU1E,MAAM,MAAM,MAAM,GAAG,QAAQ,GAAG,UAAU,GAAG,WAAW,CAAC;AAIzD,MAAM,WAAW,WAAW;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,KAAK,KAAK,GAAG,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AAyBxC,MAAM,WAAW,UAAU;IACzB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;CACjB;AAmBD,wBAAgB,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,IAAI,GAAG,IAAI,CAU5D;AAED,wBAAgB,UAAU,CAAC,EAAE,EAAE,KAAK,GAAG,IAAI,CAE1C;AAED,wBAAgB,SAAS,CAAC,EAAE,EAAE,KAAK,GAAG,IAAI,CAEzC;AAeD,eAAO,MAAM,IAAI,UACR,MAAM,MAAM,MAAM,SAAS,WAAW;iBAE9B,MAAM,MAAM,MAAM,SAAS,WAAW;qBAElC,MAAM,MAAM,MAAM,SAAS,WAAW;sBAErC,MAAM,MAAM,WAAW,SAAS,WAAW;CAGhE,CAAC;AASF,wBAAsB,GAAG,CAAC,OAAO,GAAE,UAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CA+EjE"}
|