Skip to content

Commit ed2181f

Browse files
committed
replicate mocha-coderoad with jest config
1 parent 3cd1c96 commit ed2181f

27 files changed

+3196
-7
lines changed

Diff for: .DS_Store

6 KB
Binary file not shown.

Diff for: .gitignore

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
.DS_STORE
2+
.vscode
3+
4+
node_modules

Diff for: .npmignore

+3
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
.DS_Store
2+
.vscode
3+
14
node_modules
25
src/*.js
36
test/**/*.ts

Diff for: .vscode/cSpell.json

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// cSpell Settings
2+
{
3+
4+
// Version of the setting file. Always 0.1
5+
"version": "0.1",
6+
7+
// language - current active spelling language
8+
"language": "en",
9+
10+
// words - list of words to be always considered correct
11+
"words": [
12+
"coderoad"
13+
],
14+
15+
// flagWords - list of words to be always considered incorrect
16+
// This is useful for offensive words and common spelling errors.
17+
// For example "hte" should be "the"
18+
"flagWords": [
19+
"hte"
20+
]
21+
}

Diff for: package.json

+7-1
Original file line numberDiff line numberDiff line change
@@ -19,5 +19,11 @@
1919
"bugs": {
2020
"url": "https://github.com/coderoad/jest-coderoad/issues"
2121
},
22-
"homepage": "https://github.com/coderoad/jest-coderoad#readme"
22+
"homepage": "https://github.com/coderoad/jest-coderoad#readme",
23+
"dependencies": {
24+
"babel-jest": "^15.0.0",
25+
"jest": "^15.1.1",
26+
"js-coderoad": "^0.2.1",
27+
"node-file-exists": "1.1.0"
28+
}
2329
}

Diff for: src/constants.ts

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// test results are taken after this signal
2+
// this helps to avoid parsing console.logs before the output
3+
export const signal = '@@@CodeRoad Results@@@';
4+
5+
// path to test runner executable from "node_modules"
6+
export const runnerPath = ['jest', 'bin', 'jest'];
7+
8+
// options passed in the runner command process
9+
export const runnerOptions = [
10+
'--bail', // quit on first fail
11+
'--notify'
12+
];

Diff for: src/elements.md

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
- runner name
2+
- runner path
3+
- capture output
4+
5+
- js-coderoad
6+
- jest
7+
8+
9+
npm install -g jest-cli

Diff for: src/index.ts

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import writeTests from './writeTests';
2+
import runner from './runner';
3+
import getTestPath from './testPath';
4+
5+
export function load({ dir, testFile, tests }) {
6+
writeTests({
7+
dir,
8+
tests,
9+
testPath: getTestPath(testFile),
10+
});
11+
};
12+
13+
export function run({ dir, taskPosition, handleResult, testFile }) {
14+
runner({
15+
dir,
16+
taskPosition,
17+
handleResult,
18+
testPath: getTestPath(testFile),
19+
});
20+
}

Diff for: src/reporter/index.ts

+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import { signal } from '../constants';
2+
3+
exports = module.exports = reporter;
4+
function reporter(runner) {
5+
let result = {
6+
passes: [],
7+
failures: [],
8+
pass: true,
9+
};
10+
11+
runner.on('pass', (test) => {
12+
const {index} = getIndexAndTitle(test.fullTitle());
13+
// add pass
14+
result.passes.push({
15+
msg: `Task ${index} Complete`,
16+
taskPosition: index,
17+
});
18+
});
19+
20+
runner.on('fail', (test, err: Error) => {
21+
const {msg, index} = getIndexAndTitle(test.fullTitle());
22+
// add fail
23+
result.failures.push({
24+
msg,
25+
taskPosition: index - 1,
26+
// body: test.body,
27+
timedOut: test.timedOut,
28+
// duration: test.duration
29+
});
30+
result.pass = false;
31+
});
32+
33+
runner.on('end', function() {
34+
// anything before the signal will be captured as log
35+
process.stdout.write(signal + JSON.stringify(result, null, 2));
36+
});
37+
}
38+
39+
interface IndexTitle {
40+
index: number;
41+
msg: string;
42+
}
43+
44+
function getIndexAndTitle(title: string): IndexTitle {
45+
// tests prefixed with task number: "01 title"
46+
const indexString = title.match(/^[0-9]+/);
47+
if (!indexString) {
48+
throw 'Tests should begin with a number, indicating the task number';
49+
}
50+
return {
51+
index: parseInt(indexString[0], 10),
52+
msg: title.slice(indexString[0].length + 1),
53+
};
54+
}

Diff for: src/runner/index.ts

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import startRunner from './start-runner';
2+
import spawnRunnerProcess from './runner-process';
3+
4+
const isWindows = window.navigator.appVersion.indexOf('Win') > -1;
5+
6+
export default function runner({dir, taskPosition, handleResult, testPath}) {
7+
8+
if (isWindows) {
9+
testPath = testPath.split('\\').join('\\\\');
10+
testPath = testPath.split('/').join('\\\\');
11+
}
12+
13+
const runner = spawnRunnerProcess({dir, taskPosition, testPath});
14+
return startRunner({runner, handleResult, taskPosition});
15+
}

Diff for: src/runner/paths/node.ts

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import { join } from 'path';
2+
3+
export default function getNode(): string {
4+
if (process.platform === 'darwin' && process.resourcesPath) {
5+
return join(process.resourcesPath, '..', 'Frameworks', 'Atom Helper.app', 'Contents', 'MacOS', 'Atom Helper');
6+
} else if (process.platform.match(/win/)) {
7+
return 'node';
8+
}
9+
return process.execPath;
10+
}

Diff for: src/runner/paths/runner.ts

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import fileExists from 'node-file-exists';
2+
import { join } from 'path';
3+
import { runnerPath } from '../../constants';
4+
5+
6+
const nestedPath = [__dirname, '..', '..', '..', '..'].concat(runnerPath);
7+
const flattenedPath = [__dirname, '..', '..', '..', 'node_modules'].concat(runnerPath);
8+
9+
export default function getRunner(): string {
10+
// runner, location may differ based on NPM version
11+
if (fileExists(join(...nestedPath))) {
12+
return join(...nestedPath);
13+
} else if (fileExists(join(...flattenedPath))) {
14+
return join(...flattenedPath);
15+
}
16+
throw new Error('Error finding test runner.');
17+
}

Diff for: src/runner/runner-process.ts

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import { join } from 'path';
2+
import { spawn } from 'child_process';
3+
4+
import getRunner from './paths/runner';
5+
import getNode from './paths/node';
6+
import { runnerOptions } from '../constants';
7+
8+
const reporterPath = join(__dirname, '..', 'reporter', 'index.js');
9+
const node = getNode();
10+
const runner = getRunner();
11+
12+
export default function spawnRunnerProcess({dir, taskPosition, testPath}) {
13+
// node electron setup
14+
let options: any = {
15+
cwd: dir
16+
};
17+
if (options.env == null) {
18+
options.env = Object.create(process.env);
19+
}
20+
21+
Object.assign(options.env, {
22+
ATOM_SHELL_INTERNAL_RUN_AS_NODE: 1,
23+
DIR: dir, // user project directory
24+
TASK_POSITION: taskPosition,
25+
NODE_PATH: join(dir, 'node_modules'),
26+
});
27+
28+
// spawn child process calling jest test runner
29+
return spawn(node, [
30+
// into shared node_modules directory
31+
runner,
32+
`--reporter=${reporterPath}` // test feedback
33+
]
34+
.concat(runnerOptions)
35+
.concat(testPath), // unit tests
36+
options);
37+
}

Diff for: src/runner/start-runner.ts

+68
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
import { parseLog } from 'process-console-log';
2+
import { signal } from '../constants';
3+
4+
// take code after the signal to avoid confusing console.log statements
5+
// with test output
6+
const signalMatch = new RegExp(signal);
7+
8+
export default function startRunner({runner, handleResult, taskPosition}) {
9+
10+
var final = null;
11+
12+
new Promise(function run(resolve, reject) {
13+
14+
runner.stdout.on('data', function onData(data): void {
15+
data = data.toString();
16+
// parse only final output data
17+
let match = signalMatch.exec(data); // 0
18+
19+
if (!match) {
20+
try {
21+
parseLog(data);
22+
} catch (e) {
23+
parseLog(data);
24+
}
25+
return;
26+
}
27+
28+
/* Result */
29+
// transform string result into object
30+
let resultString = data.substring(match.index + signal.length);
31+
let result = JSON.parse(JSON.stringify(resultString));
32+
// why parse twice? it works
33+
if (typeof result === 'string') {
34+
result = JSON.parse(result);
35+
}
36+
37+
switch (result.pass) {
38+
case true:
39+
final = result.passes[result.passes.length - 1];
40+
break;
41+
case false:
42+
final = result.failures[0];
43+
break;
44+
default:
45+
console.log('error processing result: ', result);
46+
}
47+
48+
final.change = final.taskPosition - taskPosition;
49+
final.pass = final.change > 0;
50+
final.completed = result.pass;
51+
52+
// return result to atom-coderoad
53+
handleResult(final);
54+
});
55+
56+
runner.stderr.on('data', function onError(data) {
57+
console.log('test error', data.toString());
58+
});
59+
60+
runner.on('close', function onClose(code: number) {
61+
// if (code === 0) {
62+
// resolve(final);
63+
// } else {
64+
resolve(final);
65+
// }
66+
});
67+
});
68+
}

Diff for: src/testPath.ts

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import { join } from 'path';
2+
3+
const isWindows = window.navigator.appVersion.includes('Win') || false;
4+
5+
export default function tmpTestName(testFile: string): string {
6+
let testPath = join(__dirname, '..', '.tmp', testFile + '.js');
7+
if (isWindows) {
8+
testPath = testPath.split('/').join('\\');
9+
}
10+
return testPath;
11+
}

0 commit comments

Comments
 (0)