proby 0.4.1 → 0.6.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 +203 -0
- package/lib/bin.js +2 -2
- package/lib/run.js +16 -17
- package/package.json +4 -4
package/README.md
ADDED
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
# proby
|
|
2
|
+
|
|
3
|
+
Test runner for JavaScript runtimes.
|
|
4
|
+
|
|
5
|
+
## What is proby?
|
|
6
|
+
|
|
7
|
+
A cross-runtime test runner that automatically discovers and runs test files.
|
|
8
|
+
Works with both single repositories and monorepos. Uses `@rcompat/test` for
|
|
9
|
+
writing tests. Works consistently across Node, Deno, and Bun.
|
|
10
|
+
|
|
11
|
+
## Installation
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npm install proby
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
pnpm add proby
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
yarn add proby
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
bun add proby
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
You also need to install `@rcompat/test` as a peer dependency:
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
npm install @rcompat/test
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Usage
|
|
36
|
+
|
|
37
|
+
### Running tests
|
|
38
|
+
|
|
39
|
+
Run proby from your project root:
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
npx proby
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### Writing tests
|
|
46
|
+
|
|
47
|
+
Create test files with `.spec.ts` or `.spec.js` extension in your `src`
|
|
48
|
+
directory:
|
|
49
|
+
|
|
50
|
+
```js
|
|
51
|
+
// src/math.spec.ts
|
|
52
|
+
import test from "@rcompat/test";
|
|
53
|
+
|
|
54
|
+
test.case("addition", assert => {
|
|
55
|
+
assert(1 + 1).equals(2);
|
|
56
|
+
assert(2 + 2).equals(4);
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
test.case("multiplication", assert => {
|
|
60
|
+
assert(2 * 3).equals(6);
|
|
61
|
+
assert(4 * 5).equals(20);
|
|
62
|
+
});
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### Test output
|
|
66
|
+
|
|
67
|
+
Proby displays colored output:
|
|
68
|
+
- Green `o` for passing tests
|
|
69
|
+
- Red `x` for failing tests
|
|
70
|
+
|
|
71
|
+
```
|
|
72
|
+
oooooxoo
|
|
73
|
+
src/math.spec.ts division
|
|
74
|
+
expected 5
|
|
75
|
+
actual 4
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### Project structure
|
|
79
|
+
|
|
80
|
+
Proby automatically detects your project structure:
|
|
81
|
+
|
|
82
|
+
**Single repository:**
|
|
83
|
+
```
|
|
84
|
+
my-project/
|
|
85
|
+
├── src/
|
|
86
|
+
│ ├── utils.ts
|
|
87
|
+
│ ├── utils.spec.ts # ← Test file
|
|
88
|
+
│ ├── math.ts
|
|
89
|
+
│ └── math.spec.ts # ← Test file
|
|
90
|
+
└── package.json
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
**Monorepo:**
|
|
94
|
+
```
|
|
95
|
+
my-monorepo/
|
|
96
|
+
├── packages/
|
|
97
|
+
│ ├── core/
|
|
98
|
+
│ │ └── src/
|
|
99
|
+
│ │ ├── index.ts
|
|
100
|
+
│ │ └── index.spec.ts # ← Test file
|
|
101
|
+
│ └── utils/
|
|
102
|
+
│ └── src/
|
|
103
|
+
│ ├── helpers.ts
|
|
104
|
+
│ └── helpers.spec.ts # ← Test file
|
|
105
|
+
└── package.json
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### npm scripts
|
|
109
|
+
|
|
110
|
+
Add proby to your `package.json`:
|
|
111
|
+
|
|
112
|
+
```json
|
|
113
|
+
{
|
|
114
|
+
"scripts": {
|
|
115
|
+
"test": "npx proby"
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
Then run:
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
npm test
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
## Test file conventions
|
|
127
|
+
|
|
128
|
+
- Files must end with `.spec.ts` or `.spec.js`
|
|
129
|
+
- Files must be in the `src` directory (or `packages/*/src` for monorepos)
|
|
130
|
+
- Use `@rcompat/test` to write tests
|
|
131
|
+
|
|
132
|
+
## Examples
|
|
133
|
+
|
|
134
|
+
### Basic assertions
|
|
135
|
+
|
|
136
|
+
```js
|
|
137
|
+
import test from "@rcompat/test";
|
|
138
|
+
|
|
139
|
+
test.case("basic assertions", assert => {
|
|
140
|
+
// equality
|
|
141
|
+
assert(value).equals(expected);
|
|
142
|
+
|
|
143
|
+
// truthiness
|
|
144
|
+
assert(condition).true();
|
|
145
|
+
assert(condition).false();
|
|
146
|
+
|
|
147
|
+
// type checking
|
|
148
|
+
assert(value).type<string>();
|
|
149
|
+
|
|
150
|
+
// throws
|
|
151
|
+
assert(() => throwingFunction()).throws();
|
|
152
|
+
assert(() => safeFunction()).tries();
|
|
153
|
+
});
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
### Async tests
|
|
157
|
+
|
|
158
|
+
```js
|
|
159
|
+
import test from "@rcompat/test";
|
|
160
|
+
|
|
161
|
+
test.case("async operations", async assert => {
|
|
162
|
+
const result = await fetchData();
|
|
163
|
+
assert(result.status).equals(200);
|
|
164
|
+
});
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
### Testing modules
|
|
168
|
+
|
|
169
|
+
```js
|
|
170
|
+
// src/calculator.ts
|
|
171
|
+
export function add(a: number, b: number) {
|
|
172
|
+
return a + b;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// src/calculator.spec.ts
|
|
176
|
+
import test from "@rcompat/test";
|
|
177
|
+
import { add } from "./calculator.js";
|
|
178
|
+
|
|
179
|
+
test.case("add function", assert => {
|
|
180
|
+
assert(add(1, 2)).equals(3);
|
|
181
|
+
assert(add(-1, 1)).equals(0);
|
|
182
|
+
assert(add(0, 0)).equals(0);
|
|
183
|
+
});
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
## Cross-Runtime Compatibility
|
|
187
|
+
|
|
188
|
+
| Runtime | Supported |
|
|
189
|
+
|---------|-----------|
|
|
190
|
+
| Node.js | ✓ |
|
|
191
|
+
| Deno | ✓ |
|
|
192
|
+
| Bun | ✓ |
|
|
193
|
+
|
|
194
|
+
No configuration required — just run `npx proby`.
|
|
195
|
+
|
|
196
|
+
## License
|
|
197
|
+
|
|
198
|
+
MIT
|
|
199
|
+
|
|
200
|
+
## Contributing
|
|
201
|
+
|
|
202
|
+
See [CONTRIBUTING.md](../../CONTRIBUTING.md) in the repository root.
|
|
203
|
+
|
package/lib/bin.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import
|
|
2
|
+
import color from "@rcompat/cli/color";
|
|
3
3
|
import print from "@rcompat/cli/print";
|
|
4
4
|
import root from "@rcompat/fs/project/root";
|
|
5
5
|
import run from "./run.js";
|
|
@@ -28,6 +28,6 @@ else if (type === "repo") {
|
|
|
28
28
|
await run($root.join("src"));
|
|
29
29
|
}
|
|
30
30
|
else {
|
|
31
|
-
print(`${red("src")} or ${red("packages")} not found\n`);
|
|
31
|
+
print(`${color.red("src")} or ${color.red("packages")} not found\n`);
|
|
32
32
|
}
|
|
33
33
|
//# sourceMappingURL=bin.js.map
|
package/lib/run.js
CHANGED
|
@@ -1,29 +1,26 @@
|
|
|
1
|
-
import
|
|
2
|
-
import green from "@rcompat/cli/color/green";
|
|
3
|
-
import red from "@rcompat/cli/color/red";
|
|
1
|
+
import color from "@rcompat/cli/color";
|
|
4
2
|
import print from "@rcompat/cli/print";
|
|
5
3
|
import repository from "@rcompat/test/repository";
|
|
6
|
-
const
|
|
4
|
+
const extensions = [".spec.ts", ".spec.js"];
|
|
5
|
+
const base_scalars = ["boolean", "number", "string", "symbol"];
|
|
7
6
|
function stringify_scalar(value) {
|
|
8
7
|
if (value === null)
|
|
9
8
|
return "null";
|
|
10
9
|
if (value === undefined)
|
|
11
10
|
return "undefined";
|
|
12
|
-
|
|
11
|
+
const type = typeof value;
|
|
12
|
+
if (base_scalars.includes(type))
|
|
13
13
|
return value.toString();
|
|
14
|
-
|
|
15
|
-
if (typeof value === "bigint") {
|
|
14
|
+
if (typeof value === "bigint")
|
|
16
15
|
return value.toString() + "n";
|
|
17
|
-
}
|
|
18
16
|
if (typeof value === "function") {
|
|
19
17
|
return `[Function${value.name ? `: ${value.name}` : ""}]`;
|
|
20
18
|
}
|
|
21
19
|
}
|
|
22
20
|
function stringify(value) {
|
|
23
21
|
const scalar = stringify_scalar(value);
|
|
24
|
-
if (scalar !== undefined)
|
|
22
|
+
if (scalar !== undefined)
|
|
25
23
|
return scalar;
|
|
26
|
-
}
|
|
27
24
|
if (typeof value === "object") {
|
|
28
25
|
try {
|
|
29
26
|
return JSON.stringify(value, (_, sub) => {
|
|
@@ -38,27 +35,29 @@ function stringify(value) {
|
|
|
38
35
|
return String(value);
|
|
39
36
|
}
|
|
40
37
|
export default async (root, subrepo) => {
|
|
41
|
-
const files = await root.list(
|
|
42
|
-
|
|
38
|
+
const files = await root.list({
|
|
39
|
+
recursive: true,
|
|
40
|
+
filter: file => extensions.some(extension => file.path.endsWith(extension)),
|
|
41
|
+
});
|
|
42
|
+
if (files.length === 0)
|
|
43
43
|
return;
|
|
44
|
-
}
|
|
45
44
|
for (const file of files) {
|
|
46
45
|
repository.suite(file);
|
|
47
46
|
await file.import();
|
|
48
47
|
}
|
|
49
48
|
if (subrepo !== undefined) {
|
|
50
|
-
print(`${blue(subrepo)}\n`);
|
|
49
|
+
print(`${color.blue(subrepo)}\n`);
|
|
51
50
|
}
|
|
52
51
|
for (const suite of repository.next()) {
|
|
53
52
|
const failed = [];
|
|
54
53
|
for await (const test of suite.run()) {
|
|
55
54
|
for (const result of test.results) {
|
|
56
55
|
if (result.passed) {
|
|
57
|
-
print(green("o"));
|
|
56
|
+
print(color.green("o"));
|
|
58
57
|
}
|
|
59
58
|
else {
|
|
60
59
|
failed.push([test, result]);
|
|
61
|
-
print(red("x"));
|
|
60
|
+
print(color.red("x"));
|
|
62
61
|
}
|
|
63
62
|
}
|
|
64
63
|
}
|
|
@@ -66,7 +65,7 @@ export default async (root, subrepo) => {
|
|
|
66
65
|
if (failed.length > 0) {
|
|
67
66
|
print("\n");
|
|
68
67
|
for (const [test, result] of failed) {
|
|
69
|
-
print(`${suite.file.debase(root)} ${red(test.name)} \n`);
|
|
68
|
+
print(`${suite.file.debase(root)} ${color.red(test.name)} \n`);
|
|
70
69
|
print(` expected ${stringify(result.expected)}\n`);
|
|
71
70
|
print(` actual ${stringify(result.actual)}\n`);
|
|
72
71
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "proby",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "Standard library test runner",
|
|
5
5
|
"bugs": "https://github.com/rcompat/rcompat/issues",
|
|
6
6
|
"license": "MIT",
|
|
@@ -16,11 +16,11 @@
|
|
|
16
16
|
"directory": "packages/proby"
|
|
17
17
|
},
|
|
18
18
|
"dependencies": {
|
|
19
|
-
"@rcompat/cli": "^0.
|
|
20
|
-
"@rcompat/fs": "^0.
|
|
19
|
+
"@rcompat/cli": "^0.13.0",
|
|
20
|
+
"@rcompat/fs": "^0.24.0"
|
|
21
21
|
},
|
|
22
22
|
"peerDependencies": {
|
|
23
|
-
"@rcompat/test": "^0.
|
|
23
|
+
"@rcompat/test": "^0.7.0"
|
|
24
24
|
},
|
|
25
25
|
"peerDependenciesMeta": {
|
|
26
26
|
"@rcompat/test": {
|