Skip to content

Commit 4392fee

Browse files
committed
Add files
1 parent a3d5412 commit 4392fee

25 files changed

+1771
-0
lines changed
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
name: Publish Package
2+
on:
3+
release:
4+
types: [published]
5+
jobs:
6+
publish:
7+
runs-on: ubuntu-18.04
8+
steps:
9+
- uses: actions/checkout@v2
10+
- uses: actions/setup-node@v1
11+
with:
12+
node-version: "12.x"
13+
registry-url: https://registry.npmjs.org
14+
- run: yarn
15+
- run: yarn publish --access public
16+
env:
17+
NODE_AUTH_TOKEN: ${{secrets.NODE_AUTH_TOKEN}}
18+
- uses: actions/setup-node@v1
19+
with:
20+
node-version: "12.x"
21+
registry-url: https://npm.pkg.github.com
22+
- run: yarn publish --access public
23+
env:
24+
NODE_AUTH_TOKEN: ${{secrets.GITHUB_TOKEN}}

.github/workflows/test.yml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
name: Test
2+
on: [push, pull_request]
3+
4+
jobs:
5+
test:
6+
runs-on: ubuntu-18.04
7+
steps:
8+
- uses: actions/checkout@v2
9+
- uses: actions/setup-node@v1
10+
with:
11+
node-version: "12.x"
12+
registry-url: https://registry.npmjs.org/
13+
- uses: actions/cache@v1
14+
with:
15+
path: node_modules
16+
key: yarn-${{ hashFiles('yarn.lock') }}
17+
restore-keys: |
18+
yarn-
19+
- run: yarn install --frozen-lockfile
20+
- run: yarn test

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
node_modules/
2+
lib/

LICENSE.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2020 Qualified, Inc
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.

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# @codewars/mocha-reporter
2+
3+
Codewars reporter for Mocha

gen-fixture.sh

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#!/bin/bash
2+
# ./gen-fixture.sh tests/fixtures/example.js
3+
# ./gen-fixture.sh tests/fixtures/example.js expected
4+
# ./gen-fixture.sh tests/fixtures/example.js sample
5+
6+
./node_modules/.bin/mocha --reporter lib/codewars-reporter $1 > "${1%.js}.${2:-expected}.txt"

package.json

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
{
2+
"name": "@codewars/mocha-reporter",
3+
"version": "1.0.0",
4+
"description": "Codewars reporter for Mocha",
5+
"license": "MIT",
6+
"homepage": "https://github.com/codewars/mocha-reporter#readme",
7+
"repository": "https://github.com/codewars/mocha-reporter",
8+
"bugs": {
9+
"url": "https://github.com/codewars/mocha-reporter/issues"
10+
},
11+
"main": "lib/codewars-reporter.js",
12+
"files": [
13+
"lib/"
14+
],
15+
"scripts": {
16+
"test": "ts-mocha tests/codewars-reporter.spec.ts",
17+
"prepare": "tsc",
18+
"watch": "tsc --watch"
19+
},
20+
"peerDependencies": {
21+
"mocha": ">=8.x"
22+
},
23+
"devDependencies": {
24+
"@types/chai": "^4.2.11",
25+
"@types/mocha": "^7.0.2",
26+
"chai": "^4.2.0",
27+
"execa": "^4.0.3",
28+
"husky": "^4.2.5",
29+
"mocha": "^8.0.1",
30+
"prettier": "^2.0.5",
31+
"pretty-quick": "^2.0.1",
32+
"ts-mocha": "^7.0.0",
33+
"typescript": "^3.9.6"
34+
},
35+
"husky": {
36+
"hooks": {
37+
"pre-commit": "pretty-quick --staged"
38+
}
39+
}
40+
}

src/codewars-reporter.ts

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
import { reporters, Runner, Suite, MochaOptions } from "mocha";
2+
3+
const EVENT_SUITE_BEGIN = Runner.constants.EVENT_SUITE_BEGIN;
4+
const EVENT_SUITE_END = Runner.constants.EVENT_SUITE_END;
5+
const EVENT_TEST_BEGIN = Runner.constants.EVENT_TEST_BEGIN;
6+
const EVENT_TEST_END = Runner.constants.EVENT_TEST_END;
7+
const EVENT_TEST_PASS = Runner.constants.EVENT_TEST_PASS;
8+
const EVENT_TEST_FAIL = Runner.constants.EVENT_TEST_FAIL;
9+
const EVENT_TEST_PENDING = Runner.constants.EVENT_TEST_PENDING;
10+
11+
class CodewarsReporter extends reporters.Base {
12+
// To allow default import
13+
static default = CodewarsReporter;
14+
constructor(runner: Runner, options?: MochaOptions) {
15+
super(runner, options);
16+
17+
runner.on(EVENT_SUITE_BEGIN, (suite) => {
18+
if (suite.title) groupStart(suite.title);
19+
});
20+
21+
runner.on(EVENT_SUITE_END, (suite) => {
22+
if (suite.title) completedIn(getSuiteDuration(suite));
23+
});
24+
25+
runner.on(EVENT_TEST_BEGIN, (test) => {
26+
testStart(test.title);
27+
});
28+
29+
runner.on(EVENT_TEST_END, (test) => {
30+
completedIn(test.duration);
31+
});
32+
33+
runner.on(EVENT_TEST_PASS, (_) => {
34+
passed();
35+
});
36+
37+
runner.on(EVENT_TEST_PENDING, (_) => {
38+
skipped();
39+
});
40+
41+
runner.on(EVENT_TEST_FAIL, (test, err) => {
42+
if (test.timedOut) return failed("Timed Out");
43+
44+
// From fast-check
45+
// TODO Improve the output by providing custom reporter.
46+
// https://github.com/dubzzz/fast-check/blob/master/documentation/1-Guides/Tips.md#customize-the-reported-error
47+
if (
48+
err instanceof Error &&
49+
/^Property failed after \d+ tests/.test(err.message)
50+
) {
51+
failed(err.message);
52+
return;
53+
}
54+
55+
if (err instanceof Error && !/^AssertionError/.test(err.name)) {
56+
errored(err.stack || err.toString());
57+
return;
58+
}
59+
60+
failed(err.message);
61+
});
62+
}
63+
}
64+
65+
const getSuiteDuration = ({ tests, suites }: Suite): number =>
66+
tests.reduce((a, t) => a + (t.duration || 0), 0) +
67+
suites.reduce((a, s) => a + getSuiteDuration(s), 0);
68+
69+
const escapeLF = (text: string) => text.replace(/\n/g, "<:LF:>");
70+
71+
const groupStart = (s: string) => console.log(`\n<DESCRIBE::>${escapeLF(s)}`);
72+
const testStart = (s: string) => console.log(`\n<IT::>${escapeLF(s)}`);
73+
const failed = (s: string) => console.log(`\n<FAILED::>${escapeLF(s)}`);
74+
const errored = (s: string) => console.log(`\n<ERROR::>${escapeLF(s)}`);
75+
const passed = () => console.log("\n<PASSED::>Test Passed");
76+
const skipped = () => console.log("\n<LOG::>Test Skipped");
77+
const completedIn = (d?: number) =>
78+
console.log(`\n<COMPLETEDIN::>${typeof d === "undefined" ? "" : d}`);
79+
80+
export = CodewarsReporter;

tests/codewars-reporter.spec.ts

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
import fs from "fs";
2+
import path from "path";
3+
import { promisify } from "util";
4+
5+
import chai from "chai";
6+
import execa from "execa";
7+
8+
const assert = chai.assert;
9+
const readFile = promisify(fs.readFile);
10+
const access = promisify(fs.access);
11+
const exists = async (path: string) => {
12+
try {
13+
await access(path);
14+
return true;
15+
} catch {
16+
return false;
17+
}
18+
};
19+
20+
const structureMatches = (a: string, b: string) =>
21+
assert.strictEqual(
22+
a.match(/<(?:DESCRIBE|IT|PASSED|FAILED|ERROR|COMPLETEDIN)::>/g).join(""),
23+
b.match(/<(?:DESCRIBE|IT|PASSED|FAILED|ERROR|COMPLETEDIN)::>/g).join("")
24+
);
25+
26+
describe("CodewarsReporter", function () {
27+
const cwd = path.join(__dirname, "..");
28+
const fixturesDir = path.join(__dirname, "fixtures");
29+
for (const file of fs.readdirSync(fixturesDir)) {
30+
if (!file.endsWith(".js")) continue;
31+
32+
it(file.replace(/\.js$/, ""), async () => {
33+
const { stdout } = await execa(
34+
"mocha",
35+
["--reporter", "lib/codewars-reporter", path.join(fixturesDir, file)],
36+
{
37+
cwd,
38+
preferLocal: true,
39+
stripFinalNewline: false,
40+
reject: false,
41+
}
42+
);
43+
const expectedFile = path.join(
44+
fixturesDir,
45+
file.replace(/\.js$/, ".expected.txt")
46+
);
47+
48+
if (await exists(expectedFile)) {
49+
const expected = await readFile(expectedFile, {
50+
encoding: "utf-8",
51+
});
52+
// Allow duration to change
53+
const expectedPattern = new RegExp(
54+
expected.replace(/(?<=<COMPLETEDIN::>)\d+/g, "\\d+")
55+
);
56+
assert.match(stdout, expectedPattern);
57+
} else {
58+
const samplePath = path.join(
59+
fixturesDir,
60+
file.replace(/\.js$/, ".sample.txt")
61+
);
62+
const sample = await readFile(samplePath, {
63+
encoding: "utf-8",
64+
});
65+
structureMatches(stdout, sample);
66+
}
67+
});
68+
}
69+
});
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
describe("group 1", () => {
2+
it("test 1", () => {
3+
throw new Error("error");
4+
});
5+
});

0 commit comments

Comments
 (0)