proby 0.12.0 → 0.13.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/README.md +60 -1
- package/lib/Schema.d.ts +8 -0
- package/lib/Schema.js +9 -0
- package/lib/bin.js +34 -26
- package/lib/config.d.ts +9 -0
- package/lib/config.js +2 -0
- package/lib/fixtures/static-mock/math.d.ts +2 -0
- package/lib/fixtures/static-mock/math.js +4 -0
- package/lib/fixtures/static-mock/math.mock.d.ts +2 -0
- package/lib/fixtures/static-mock/math.mock.js +5 -0
- package/lib/run.d.ts +1 -1
- package/lib/run.js +31 -22
- package/package.json +17 -7
package/README.md
CHANGED
|
@@ -42,6 +42,64 @@ Run proby from your project root:
|
|
|
42
42
|
npx proby
|
|
43
43
|
```
|
|
44
44
|
|
|
45
|
+
Run a single file:
|
|
46
|
+
```bash
|
|
47
|
+
npx proby math.spec.ts
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Run a single group within a file:
|
|
51
|
+
```bash
|
|
52
|
+
npx proby math.spec.ts addition
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### Grouping tests
|
|
56
|
+
|
|
57
|
+
Use `test.group` in your spec files to cluster related cases. Groups can then
|
|
58
|
+
be targeted individually when running proby:
|
|
59
|
+
```js
|
|
60
|
+
// src/math.spec.ts
|
|
61
|
+
import test from "@rcompat/test";
|
|
62
|
+
|
|
63
|
+
test.group("addition", () => {
|
|
64
|
+
test.case("integers", assert => {
|
|
65
|
+
assert(1 + 1).equals(2);
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
test.group("multiplication", () => {
|
|
70
|
+
test.case("integers", assert => {
|
|
71
|
+
assert(2 * 3).equals(6);
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
```
|
|
75
|
+
```bash
|
|
76
|
+
npx proby math.spec.ts addition # runs only the addition group
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Grouping tests
|
|
80
|
+
|
|
81
|
+
Use `test.group` in your spec files to cluster related cases. Groups can then
|
|
82
|
+
be targeted individually when running proby:
|
|
83
|
+
```js
|
|
84
|
+
// src/math.spec.ts
|
|
85
|
+
import test from "@rcompat/test";
|
|
86
|
+
|
|
87
|
+
test.group("addition", () => {
|
|
88
|
+
test.case("integers", assert => {
|
|
89
|
+
assert(1 + 1).equals(2);
|
|
90
|
+
});
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
test.group("multiplication", () => {
|
|
94
|
+
test.case("integers", assert => {
|
|
95
|
+
assert(2 * 3).equals(6);
|
|
96
|
+
});
|
|
97
|
+
});
|
|
98
|
+
```
|
|
99
|
+
```bash
|
|
100
|
+
npx proby math.spec.ts addition # runs only the addition group
|
|
101
|
+
```
|
|
102
|
+
|
|
45
103
|
### Writing tests
|
|
46
104
|
|
|
47
105
|
Create test files with `.spec.ts` or `.spec.js` extension in your `src`
|
|
@@ -128,7 +186,8 @@ npm test
|
|
|
128
186
|
- Files must end with `.spec.ts` or `.spec.js`
|
|
129
187
|
- Files must be in the `src` directory (or `packages/*/src` for monorepos)
|
|
130
188
|
- Use `@rcompat/test` to write tests
|
|
131
|
-
|
|
189
|
+
- Use `test.group` to organize cases into named groups targetable by proby
|
|
190
|
+

|
|
132
191
|
## Examples
|
|
133
192
|
|
|
134
193
|
### Basic assertions
|
package/lib/Schema.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
declare const Schema: import("pema").ObjectType<{
|
|
2
|
+
monorepo: import("pema").DefaultType<import("pema").BooleanType, false>;
|
|
3
|
+
packages: import("pema").DefaultType<import("pema").StringType, "packages">;
|
|
4
|
+
include: import("pema").DefaultType<import("pema").ArrayType<import("pema").StringType>, string[]>;
|
|
5
|
+
conditions: import("pema").DefaultType<import("pema").ArrayType<import("pema").StringType>, string[]>;
|
|
6
|
+
}>;
|
|
7
|
+
export default Schema;
|
|
8
|
+
//# sourceMappingURL=Schema.d.ts.map
|
package/lib/Schema.js
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import p from "pema";
|
|
2
|
+
const Schema = p({
|
|
3
|
+
monorepo: p.boolean.default(false),
|
|
4
|
+
packages: p.string.default("packages"),
|
|
5
|
+
include: p.array(p.string).default(["src"]),
|
|
6
|
+
conditions: p.array(p.string).default(["source"]),
|
|
7
|
+
});
|
|
8
|
+
export default Schema;
|
|
9
|
+
//# sourceMappingURL=Schema.js.map
|
package/lib/bin.js
CHANGED
|
@@ -1,37 +1,45 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
import print from "@rcompat/cli/print";
|
|
2
|
+
import Schema from "#Schema";
|
|
3
|
+
import env from "@rcompat/env";
|
|
5
4
|
import fs from "@rcompat/fs";
|
|
6
|
-
import
|
|
5
|
+
import io from "@rcompat/io";
|
|
6
|
+
import is from "@rcompat/is";
|
|
7
|
+
import runtime from "@rcompat/runtime";
|
|
7
8
|
const root = await fs.project.root();
|
|
8
|
-
const
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
const ts_config_file = root.join("proby.config.ts");
|
|
10
|
+
const js_config_file = root.join("proby.config.js");
|
|
11
|
+
const user_config = await ts_config_file.exists()
|
|
12
|
+
? (await ts_config_file.import("default"))
|
|
13
|
+
: await js_config_file.exists()
|
|
14
|
+
? (await js_config_file.import("default"))
|
|
15
|
+
: {};
|
|
16
|
+
const { include, packages, conditions, monorepo } = Schema.parse(user_config);
|
|
17
|
+
const conditions_flag = conditions.length > 0
|
|
18
|
+
? ` --conditions=${conditions.join(",")}`
|
|
19
|
+
: "";
|
|
20
|
+
const script = runtime.script;
|
|
21
|
+
const args = runtime.args.join(" ");
|
|
22
|
+
if (!is.defined(env.try("PROBY_RELAUNCHED"))) {
|
|
23
|
+
await io.spawn(`${runtime.bin} ${conditions_flag} ${script} ${args}`, {
|
|
24
|
+
inherit: true,
|
|
25
|
+
env: { ...process.env, PROBY_RELAUNCHED: "1" },
|
|
26
|
+
});
|
|
27
|
+
runtime.exit(0);
|
|
11
28
|
}
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
const
|
|
16
|
-
const type = await (async (base) => {
|
|
17
|
-
if (await base.join("packages").exists()) {
|
|
18
|
-
return "monorepo";
|
|
19
|
-
}
|
|
20
|
-
if (await base.join("src").exists()) {
|
|
21
|
-
return "repo";
|
|
22
|
-
}
|
|
23
|
-
})(root);
|
|
24
|
-
if (type === "monorepo") {
|
|
25
|
-
for (const repo of await root.join("packages").list({
|
|
29
|
+
import run from "#run";
|
|
30
|
+
const [file, group] = runtime.args;
|
|
31
|
+
if (monorepo) {
|
|
32
|
+
for (const repo of await root.join(packages).list({
|
|
26
33
|
filter: info => info.kind === "directory",
|
|
27
34
|
})) {
|
|
28
|
-
|
|
35
|
+
for (const dir of include) {
|
|
36
|
+
await run(repo.join(dir), repo.name, file, group);
|
|
37
|
+
}
|
|
29
38
|
}
|
|
30
39
|
}
|
|
31
|
-
else if (type === "repo") {
|
|
32
|
-
await run(root.join("src"), undefined, file);
|
|
33
|
-
}
|
|
34
40
|
else {
|
|
35
|
-
|
|
41
|
+
for (const dir of include) {
|
|
42
|
+
await run(root.join(dir), undefined, file, group);
|
|
43
|
+
}
|
|
36
44
|
}
|
|
37
45
|
//# sourceMappingURL=bin.js.map
|
package/lib/config.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type Schema from "#Schema";
|
|
2
|
+
declare const _default: (input: typeof Schema.input) => {
|
|
3
|
+
monorepo?: boolean | undefined;
|
|
4
|
+
packages?: string | undefined;
|
|
5
|
+
include?: string[] | undefined;
|
|
6
|
+
conditions?: string[] | undefined;
|
|
7
|
+
} | undefined;
|
|
8
|
+
export default _default;
|
|
9
|
+
//# sourceMappingURL=config.d.ts.map
|
package/lib/config.js
ADDED
package/lib/run.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import type { FileRef } from "@rcompat/fs";
|
|
2
|
-
declare const _default: (root: FileRef, subrepo?: string, target?: string) => Promise<void>;
|
|
2
|
+
declare const _default: (root: FileRef, subrepo?: string, target?: string, group?: string) => Promise<void>;
|
|
3
3
|
export default _default;
|
|
4
4
|
//# sourceMappingURL=run.d.ts.map
|
package/lib/run.js
CHANGED
|
@@ -44,7 +44,8 @@ async function run_in_worker(spec, env) {
|
|
|
44
44
|
});
|
|
45
45
|
const context = await env_module.setup?.();
|
|
46
46
|
return new Promise((resolve, reject) => {
|
|
47
|
-
const
|
|
47
|
+
const worker_url = new URL(import.meta.url.endsWith(".ts") ? "./worker.ts" : "./worker.js", import.meta.url);
|
|
48
|
+
const worker = new Worker(worker_url, {
|
|
48
49
|
workerData: {
|
|
49
50
|
spec: spec.path,
|
|
50
51
|
env: env.path,
|
|
@@ -72,7 +73,7 @@ async function run_in_worker(spec, env) {
|
|
|
72
73
|
});
|
|
73
74
|
});
|
|
74
75
|
}
|
|
75
|
-
export default async (root, subrepo, target) => {
|
|
76
|
+
export default async (root, subrepo, target, group) => {
|
|
76
77
|
const files = await root.list({
|
|
77
78
|
recursive: true,
|
|
78
79
|
filter: info => extensions.some(extension => info.path.endsWith(extension)),
|
|
@@ -89,33 +90,41 @@ export default async (root, subrepo, target) => {
|
|
|
89
90
|
await run_in_worker(file, env_file);
|
|
90
91
|
continue;
|
|
91
92
|
}
|
|
93
|
+
const mock_file = await file.sibling(file.name.replace(/\.spec\.(ts|js)$/, ".mock.$1")).or(() => null);
|
|
92
94
|
repository.suite(file);
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
95
|
+
const suite = repository.next().next().value;
|
|
96
|
+
try {
|
|
97
|
+
if (mock_file !== null)
|
|
98
|
+
await mock_file.import();
|
|
99
|
+
await file.import();
|
|
100
|
+
const failed = [];
|
|
101
|
+
for await (const test of suite.run()) {
|
|
102
|
+
if (group !== undefined && test.group !== group)
|
|
103
|
+
continue;
|
|
104
|
+
for (const result of test.results) {
|
|
105
|
+
if (result.passed) {
|
|
106
|
+
print(color.green("o"));
|
|
107
|
+
}
|
|
108
|
+
else {
|
|
109
|
+
failed.push([test, result]);
|
|
110
|
+
print(color.red("x"));
|
|
111
|
+
}
|
|
101
112
|
}
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
113
|
+
}
|
|
114
|
+
await suite.end();
|
|
115
|
+
if (failed.length > 0) {
|
|
116
|
+
print("\n");
|
|
117
|
+
for (const [test, result] of failed) {
|
|
118
|
+
print(`${suite.file.debase(root)} ${color.red(test.name)} \n`);
|
|
119
|
+
print(` expected ${stringify(result.expected)}\n`);
|
|
120
|
+
print(` actual ${stringify(result.actual)}\n`);
|
|
105
121
|
}
|
|
106
122
|
}
|
|
107
123
|
}
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
print("\n");
|
|
111
|
-
for (const [test, result] of failed) {
|
|
112
|
-
print(`${suite.file.debase(root)} ${color.red(test.name)} \n`);
|
|
113
|
-
print(` expected ${stringify(result.expected)}\n`);
|
|
114
|
-
print(` actual ${stringify(result.actual)}\n`);
|
|
115
|
-
}
|
|
124
|
+
finally {
|
|
125
|
+
repository.reset();
|
|
116
126
|
}
|
|
117
127
|
}
|
|
118
128
|
print("\n");
|
|
119
|
-
repository.reset();
|
|
120
129
|
};
|
|
121
130
|
//# sourceMappingURL=run.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "proby",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.13.0",
|
|
4
4
|
"description": "Standard library test runner",
|
|
5
5
|
"bugs": "https://github.com/rcompat/rcompat/issues",
|
|
6
6
|
"license": "MIT",
|
|
@@ -16,13 +16,17 @@
|
|
|
16
16
|
"directory": "packages/proby"
|
|
17
17
|
},
|
|
18
18
|
"dependencies": {
|
|
19
|
-
"
|
|
20
|
-
"@rcompat/
|
|
21
|
-
"@rcompat/
|
|
22
|
-
"@rcompat/
|
|
19
|
+
"pema": "^0.5.0",
|
|
20
|
+
"@rcompat/assert": "^0.8.0",
|
|
21
|
+
"@rcompat/cli": "^0.18.0",
|
|
22
|
+
"@rcompat/env": "^0.17.0",
|
|
23
|
+
"@rcompat/io": "^0.5.0",
|
|
24
|
+
"@rcompat/fs": "^0.28.0",
|
|
25
|
+
"@rcompat/is": "^0.6.0",
|
|
26
|
+
"@rcompat/runtime": "^0.11.0"
|
|
23
27
|
},
|
|
24
28
|
"peerDependencies": {
|
|
25
|
-
"@rcompat/test": "^0.
|
|
29
|
+
"@rcompat/test": "^0.12.0"
|
|
26
30
|
},
|
|
27
31
|
"peerDependenciesMeta": {
|
|
28
32
|
"@rcompat/test": {
|
|
@@ -32,10 +36,16 @@
|
|
|
32
36
|
"type": "module",
|
|
33
37
|
"imports": {
|
|
34
38
|
"#*": {
|
|
35
|
-
"
|
|
39
|
+
"source": "./src/*.ts",
|
|
36
40
|
"default": "./lib/*.js"
|
|
37
41
|
}
|
|
38
42
|
},
|
|
43
|
+
"exports": {
|
|
44
|
+
"./config": {
|
|
45
|
+
"source": "./src/config.ts",
|
|
46
|
+
"default": "./lib/config.js"
|
|
47
|
+
}
|
|
48
|
+
},
|
|
39
49
|
"scripts": {
|
|
40
50
|
"build": "npm run clean && tsc",
|
|
41
51
|
"clean": "rm -rf ./lib",
|