Skip to content

Commit 58a92fc

Browse files
committed
First working example of create-jest-runner
1 parent 6c782c7 commit 58a92fc

File tree

19 files changed

+318
-118
lines changed

19 files changed

+318
-118
lines changed

README.md

Lines changed: 40 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# create-jest-runner
22

3+
A highly opinionated way for creating Jest Runners
4+
35
## Install
46

57
```bash
@@ -13,65 +15,71 @@ create-jest-runner takes care of handling the appropriate parallelization and cr
1315

1416
You simply need two files:
1517
* Entry file: Used by Jest as an entrypoint to your runner.
16-
* Run file: Contains the domain logic of your runner.
18+
* Run file: Runs once per test file, and it encapsulates the logic of your runner
1719

1820
### 1) Create your entry file
1921

2022
```js
2123
// index.js
22-
const createRunner = require('create-jest-runner');
23-
module.exports = createRunner('/path/to/run.js')
24+
const { createJestRunner } = require('create-jest-runner');
25+
module.exports = createJestRunner(require.resolve('./run'));
2426
```
2527

2628
### 2) Create your run file
2729

28-
2930
```js
30-
// run.js
31-
module.exports = (options, workerCallback) => {
32-
// ...
33-
}
31+
module.exports = (options) => {
32+
};
3433
```
3534

36-
## Run File API
35+
### Run File API
3736

38-
This file should export a function that receives two parameters `(options, workerCallback)`
37+
This file should export a function that receives one parameter with the options
3938

40-
### `options: { testPath, config, globalConfig }`
39+
#### `options: { testPath, config, globalConfig }`
4140
- `testPath`: Path of the file that is going to be tests
4241
- `config`: Jest Project config used by this file
4342
- `globalConfig`: Jest global config
4443

45-
### `workerCallback: (error, testResult) => void`
46-
_Use this callback function to report back the results (needs to be called exactly one time)._
47-
- `error`: Any Javascript error or a string.
48-
- `testResult`: Needs to be an object of type https://github.com/facebook/jest/blob/master/types/TestResult.js#L131-L157
44+
You can return one of the following values:
45+
- `testResult`: Needs to be an object of type https://github.com/facebook/jest/blob/master/types/TestResult.js#L131-L157
46+
- `Promise<testResult|Error>`: needs to be of above type.
47+
- `Error`: good for reporting system error, not failed tests.
48+
49+
50+
51+
## Example of a runner
52+
53+
This runner "blade-runner" makes sure that these two emojis `⚔️ 🏃` are present in every file
4954

50-
### Reporting test results
5155

52-
#### Passing test suite
5356
```js
54-
// run.js
55-
module.exports = (options, workerCallback) => {
56-
if (/* something */) {
57-
workerCallback(new Error('my message'));
58-
}
59-
}
57+
// index.js
58+
const { createJestRunner } = require('create-jest-runner');
59+
module.exports = createJestRunner(require.resolve('./run'));
6060
```
61-
#### Failing test suite
6261

63-
### Reporting an error
64-
You can report other errors by calling the `workerCallback` with the appropriate error.
6562
```js
6663
// run.js
67-
module.exports = (options, workerCallback) => {
68-
if (/* something */) {
69-
workerCallback(new Error('my message'));
70-
}
71-
}
72-
```
64+
const fs = require('fs');
65+
const { pass, fail } = require('create-jest-runner');
7366

67+
module.exports = ({ testPath }) => {
68+
const start = +new Date();
69+
const contents = fs.readFileSync(testPath, 'utf8');
70+
const end = +new Date();
7471

72+
if (contents.includes('⚔️🏃')) {
73+
return pass({ start, end, test: { path: testPath } });
74+
}
75+
const errorMessage = 'Company policies require ⚔️ 🏃 in every file';
76+
return fail({
77+
start,
78+
end,
79+
test: { path: testPath, errorMessage, title: 'Check for ⚔️ 🏃' },
80+
});
81+
};
82+
```
7583

7684

7785
## Add your runner to Jest config
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
console.log();
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
module.exports = {
2+
runner: require.resolve('../../runner'),
3+
testMatch: ['**/__src__/**/*.js'],
4+
};
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
// ⚔️🏃
2+
console.log();
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
module.exports = {
2+
runner: require.resolve('../../runner'),
3+
testMatch: ['**/__src__/**/*.js'],
4+
};
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// Jest Snapshot v1, https://goo.gl/fbAQLP
2+
3+
exports[`Works when it has failing tests 1`] = `
4+
"FAIL integrationTests/__fixtures__/failing/__src__/file1.js
5+
Company policies require ⚔️ 🏃 in every file
6+
✕ Check for ⚔️ 🏃
7+
Test Suites: 1 failed, 1 total
8+
Tests: 1 failed, 1 total
9+
Snapshots: 0 total
10+
Time:
11+
Ran all test suites.
12+
13+
"
14+
`;
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// Jest Snapshot v1, https://goo.gl/fbAQLP
2+
3+
exports[`Works when it has only passing tests 1`] = `
4+
"PASS integrationTests/__fixtures__/passing/__src__/file1.js
5+
6+
Test Suites: 1 passed, 1 total
7+
Tests: 1 passed, 1 total
8+
Snapshots: 0 total
9+
Time:
10+
Ran all test suites.
11+
"
12+
`;

integrationTests/failing.test.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
const runJest = require('./runJest');
2+
3+
it('Works when it has failing tests', () => {
4+
return expect(runJest('failing')).resolves.toMatchSnapshot();
5+
});

integrationTests/passing.test.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
const runJest = require('./runJest');
2+
3+
it('Works when it has only passing tests', () => {
4+
return expect(runJest('passing')).resolves.toMatchSnapshot();
5+
});

integrationTests/runJest.js

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// eslint-disable-next-line import/no-extraneous-dependencies
2+
const execa = require('execa');
3+
const path = require('path');
4+
5+
const rootDir = path.join(__dirname, '..');
6+
7+
const normalize = output =>
8+
output
9+
.replace(/\(?\d*\.?\d+m?s\)?/g, '')
10+
.replace(/, estimated/g, '')
11+
.replace(new RegExp(rootDir, 'g'), '/mocked-path-to-jest-runner-mocha')
12+
.replace(new RegExp('.*at .*\\n', 'g'), 'mocked-stack-trace')
13+
.replace(/.*at .*\\n/g, 'mocked-stack-trace')
14+
.replace(/(mocked-stack-trace)+/, ' at mocked-stack-trace')
15+
.replace(/\s+\n/g, '\n');
16+
17+
const runJest = (project, options = []) => {
18+
// eslint-disable-next-line
19+
jasmine.DEFAULT_TIMEOUT_INTERVAL = 15000;
20+
return execa(
21+
'jest',
22+
[
23+
'--useStderr',
24+
'--no-watchman',
25+
'--no-cache',
26+
'--projects',
27+
path.join(__dirname, '__fixtures__', project),
28+
].concat(options),
29+
{
30+
env: process.env,
31+
},
32+
)
33+
.catch(t => t)
34+
.then(({ stdout, stderr }) => `${normalize(stderr)}\n${normalize(stdout)}`);
35+
};
36+
37+
module.exports = runJest;

0 commit comments

Comments
 (0)