@testomatio/reporter 0.4.6 → 0.5.0-beta.1
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/.eslintrc.js +18 -22
- package/.github/workflows/node.js.yml +2 -1
- package/.prettierrc.js +12 -0
- package/Changelog.md +18 -18
- package/README.md +122 -93
- package/example/codecept/codecept.conf.js +7 -7
- package/example/codecept/index_test.js +8 -8
- package/example/codecept/sample_test.js +4 -4
- package/example/codecept/steps.d.ts +1 -1
- package/example/codecept/steps_file.js +4 -2
- package/example/core/index.js +6 -6
- package/example/jest/index.test.js +3 -3
- package/example/jest/jest.config.js +1 -1
- package/example/jest/sample.test.js +4 -4
- package/example/mocha/test/index.test.js +5 -5
- package/lib/adapter/codecept.js +62 -67
- package/lib/adapter/cucumber.js +35 -52
- package/lib/adapter/cypress-plugin/index.js +42 -0
- package/lib/adapter/jasmine.js +15 -6
- package/lib/adapter/jest.js +9 -10
- package/lib/adapter/mocha.js +17 -14
- package/lib/adapter/playwright.js +25 -25
- package/lib/adapter/webdriver.js +3 -3
- package/lib/bin/startTest.js +56 -60
- package/lib/client.js +58 -110
- package/lib/constants.js +6 -6
- package/lib/fileUploader.js +17 -16
- package/lib/output.js +6 -8
- package/lib/reporter.js +2 -2
- package/lib/util.js +18 -5
- package/package.json +27 -15
- package/testcafe/index.js +11 -14
- package/tests/adapter/config/index.js +10 -0
- package/tests/adapter/examples/codecept/codecept.conf.js +33 -0
- package/tests/adapter/examples/codecept/index_test.js +11 -0
- package/tests/adapter/examples/codecept/jsconfig.json +5 -0
- package/tests/adapter/examples/codecept/output/Test_for_suite_2_@Tc2171bd2.failed.png +0 -0
- package/tests/adapter/examples/codecept/output/Test_issue_for_suite_1_@Tca70c8c4.failed.png +0 -0
- package/tests/adapter/examples/codecept/sample_test.js +7 -0
- package/tests/adapter/examples/codecept/steps_file.js +10 -0
- package/tests/adapter/examples/jasmine/index.test.js +11 -0
- package/tests/adapter/examples/jasmine/passReporterOpts.sh +8 -0
- package/tests/adapter/examples/jest/index.test.js +11 -0
- package/tests/adapter/examples/jest/jest.config.js +4 -0
- package/tests/adapter/examples/mocha/index.test.js +13 -0
- package/tests/adapter/examples/mocha/mocha.config.js +4 -0
- package/tests/adapter/index.test.js +136 -0
- package/tests/adapter/utils/index.js +40 -0
- package/.prettierrc.json +0 -1
package/lib/util.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
|
+
const { URL } = require('url');
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
* @param {String} testTitle - Test title
|
|
3
5
|
*
|
|
4
6
|
* @returns {String} testId
|
|
5
7
|
*/
|
|
6
|
-
const parseTest =
|
|
8
|
+
const parseTest = testTitle => {
|
|
7
9
|
const captures = testTitle.match(/@T([\w\d]+)/);
|
|
8
10
|
if (captures) {
|
|
9
11
|
return captures[1];
|
|
@@ -14,14 +16,25 @@ const parseTest = (testTitle) => {
|
|
|
14
16
|
|
|
15
17
|
const ansiRegExp = () => {
|
|
16
18
|
const pattern = [
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
].join(
|
|
19
|
+
'[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:[a-zA-Z\\d]*(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?\\u0007)',
|
|
20
|
+
'(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-ntqry=><~]))',
|
|
21
|
+
].join('|');
|
|
22
|
+
|
|
23
|
+
return new RegExp(pattern, 'g');
|
|
24
|
+
};
|
|
20
25
|
|
|
21
|
-
|
|
26
|
+
const isValidUrl = s => {
|
|
27
|
+
try {
|
|
28
|
+
// eslint-disable-next-line no-new
|
|
29
|
+
new URL(s);
|
|
30
|
+
return true;
|
|
31
|
+
} catch (err) {
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
22
34
|
};
|
|
23
35
|
|
|
24
36
|
module.exports = {
|
|
25
37
|
parseTest,
|
|
26
38
|
ansiRegExp,
|
|
39
|
+
isValidUrl,
|
|
27
40
|
};
|
package/package.json
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@testomatio/reporter",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0-beta.1",
|
|
4
4
|
"description": "Testomatio Reporter Client",
|
|
5
5
|
"main": "./lib/reporter.js",
|
|
6
6
|
"repository": "git@github.com:testomatio/reporter.git",
|
|
7
7
|
"author": "Koushik Mohan <koushikmohan1996@gmail.com>",
|
|
8
8
|
"license": "MIT",
|
|
9
9
|
"dependencies": {
|
|
10
|
-
"aws-sdk": "^2.
|
|
11
|
-
"axios": "^0.
|
|
12
|
-
"callsite-record": "^4.1.
|
|
10
|
+
"aws-sdk": "^2.1064.0",
|
|
11
|
+
"axios": "^0.25.0",
|
|
12
|
+
"callsite-record": "^4.1.4",
|
|
13
13
|
"chalk": "^4.1.0",
|
|
14
14
|
"commander": "^4.1.1",
|
|
15
15
|
"has-flag": "^5.0.1",
|
|
@@ -17,23 +17,35 @@
|
|
|
17
17
|
},
|
|
18
18
|
"scripts": {
|
|
19
19
|
"pretty": "prettier --write .",
|
|
20
|
-
"lint": "eslint lib
|
|
20
|
+
"lint": "eslint lib",
|
|
21
|
+
"lint:fix": "eslint lib --fix",
|
|
22
|
+
"test": "npm run test:adapter",
|
|
23
|
+
"test:adapter": "mocha './tests/adapter/index.test.js'",
|
|
24
|
+
"test:adapter:jest:example": "jest './tests/adapter/examples/jest/index.test.js' --config='./tests/adapter/examples/jest/jest.config.js'",
|
|
25
|
+
"test:adapter:mocha:example": "mocha './tests/adapter/examples/mocha/index.test.js' --config='./tests/adapter/examples/mocha/mocha.config.js'",
|
|
26
|
+
"test:adapter:jasmine:example": "./tests/adapter/examples/jasmine/passReporterOpts.sh && jasmine './tests/adapter/examples/jasmine/index.test.js' --reporter=./../../../lib/adapter/jasmine.js",
|
|
27
|
+
"test:adapter:codecept:example": "codeceptjs run --config='./tests/adapter/examples/codecept/codecept.conf.js'"
|
|
21
28
|
},
|
|
22
29
|
"peerDependencies": {
|
|
30
|
+
"@wdio/reporter": "*",
|
|
23
31
|
"codeceptjs": "*",
|
|
24
32
|
"cucumber": "*",
|
|
25
|
-
"mocha": "*"
|
|
26
|
-
"@wdio/reporter": "*"
|
|
33
|
+
"mocha": "*"
|
|
27
34
|
},
|
|
28
35
|
"devDependencies": {
|
|
29
|
-
"@wdio/reporter": "^7.
|
|
30
|
-
"
|
|
31
|
-
"
|
|
32
|
-
"eslint
|
|
33
|
-
"eslint-
|
|
34
|
-
"
|
|
35
|
-
"
|
|
36
|
-
"
|
|
36
|
+
"@wdio/reporter": "^7.16.13",
|
|
37
|
+
"chai": "^4.3.6",
|
|
38
|
+
"codeceptjs": "^3.2.3",
|
|
39
|
+
"eslint": "^8.7.0",
|
|
40
|
+
"eslint-config-airbnb-base": "^15.0.0",
|
|
41
|
+
"eslint-config-prettier": "^8.3.0",
|
|
42
|
+
"eslint-plugin-import": "^2.25.4",
|
|
43
|
+
"jasmine": "^3.10.0",
|
|
44
|
+
"jest": "^27.4.7",
|
|
45
|
+
"mocha": "^9.2.0",
|
|
46
|
+
"mock-http-server": "^1.4.5",
|
|
47
|
+
"prettier": "2.5.1",
|
|
48
|
+
"puppeteer": "^13.1.2"
|
|
37
49
|
},
|
|
38
50
|
"bin": {
|
|
39
51
|
"start-test-run": "./lib/bin/startTest.js"
|
package/testcafe/index.js
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
const TestomatClient = require(
|
|
2
|
-
const TRConstants = require(
|
|
3
|
-
const util = require(
|
|
1
|
+
const TestomatClient = require('@testomatio/reporter/lib/client');
|
|
2
|
+
const TRConstants = require('@testomatio/reporter/lib/constants');
|
|
3
|
+
const util = require('@testomatio/reporter/lib/util');
|
|
4
4
|
|
|
5
|
-
module.exports =
|
|
5
|
+
module.exports = () => {
|
|
6
6
|
const apiKey = process.env.TESTOMATIO;
|
|
7
7
|
let failed = false;
|
|
8
8
|
|
|
9
|
-
if (apiKey ===
|
|
10
|
-
throw new Error(
|
|
9
|
+
if (apiKey === '' || apiKey === undefined) {
|
|
10
|
+
throw new Error('Testomat.io API key cannot be empty');
|
|
11
11
|
}
|
|
12
12
|
const client = new TestomatClient({ apiKey });
|
|
13
13
|
|
|
14
14
|
return {
|
|
15
15
|
reportTaskStart(startTime, userAgents) {
|
|
16
|
-
console.log(
|
|
16
|
+
console.log('TestCafe started with: ', userAgents);
|
|
17
17
|
client.createRun();
|
|
18
18
|
},
|
|
19
19
|
|
|
@@ -23,7 +23,7 @@ module.exports = function () {
|
|
|
23
23
|
|
|
24
24
|
reportTestDone(name, testRunInfo) {
|
|
25
25
|
let status = TRConstants.PASSED;
|
|
26
|
-
let message =
|
|
26
|
+
let message = '';
|
|
27
27
|
|
|
28
28
|
if (testRunInfo.skipped) {
|
|
29
29
|
status = TRConstants.SKIPPED;
|
|
@@ -43,16 +43,13 @@ module.exports = function () {
|
|
|
43
43
|
},
|
|
44
44
|
|
|
45
45
|
renderErrors(errors) {
|
|
46
|
-
let errorMessage =
|
|
46
|
+
let errorMessage = '';
|
|
47
47
|
errors.forEach((error, id) => {
|
|
48
|
-
errorMessage = `${errorMessage}${this.formatError(
|
|
49
|
-
error,
|
|
50
|
-
`${id + 1} `
|
|
51
|
-
)}\n`;
|
|
48
|
+
errorMessage = `${errorMessage}${this.formatError(error, `${id + 1} `)}\n`;
|
|
52
49
|
});
|
|
53
50
|
|
|
54
51
|
console.log(errorMessage);
|
|
55
|
-
return errorMessage.replace(util.ansiRegExp(),
|
|
52
|
+
return errorMessage.replace(util.ansiRegExp(), '');
|
|
56
53
|
},
|
|
57
54
|
|
|
58
55
|
reportTaskDone() {
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
exports.config = {
|
|
2
|
+
tests: './*_test.js',
|
|
3
|
+
output: './output',
|
|
4
|
+
helpers: {
|
|
5
|
+
Puppeteer: {
|
|
6
|
+
url: 'http://localhost',
|
|
7
|
+
show: false,
|
|
8
|
+
},
|
|
9
|
+
},
|
|
10
|
+
include: {
|
|
11
|
+
I: './steps_file.js',
|
|
12
|
+
},
|
|
13
|
+
bootstrap: null,
|
|
14
|
+
mocha: {},
|
|
15
|
+
name: 'codecept',
|
|
16
|
+
plugins: {
|
|
17
|
+
pauseOnFail: {},
|
|
18
|
+
retryFailedStep: {
|
|
19
|
+
enabled: true,
|
|
20
|
+
},
|
|
21
|
+
tryTo: {
|
|
22
|
+
enabled: true,
|
|
23
|
+
},
|
|
24
|
+
screenshotOnFail: {
|
|
25
|
+
enabled: true,
|
|
26
|
+
},
|
|
27
|
+
testomat: {
|
|
28
|
+
enabled: true,
|
|
29
|
+
require: '../../../../lib/adapter/codecept',
|
|
30
|
+
apiKey: 'lz8ea4948ud5',
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/* eslint-disable no-undef */
|
|
2
|
+
Feature('Suite 1 @S25e19ba9');
|
|
3
|
+
|
|
4
|
+
Scenario('Test issue for suite 1 @Tca70c8c4', ({ I }) => {
|
|
5
|
+
I.amOnPage('https://github.com/login');
|
|
6
|
+
I.see('GitHub');
|
|
7
|
+
I.fillField('login', 'randomuser_kmk');
|
|
8
|
+
I.fillField('password', 'randomuser_kmk');
|
|
9
|
+
I.click('Sign in');
|
|
10
|
+
I.see('Repositories');
|
|
11
|
+
});
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// in this file you can append custom step methods to 'I' object
|
|
2
|
+
|
|
3
|
+
module.exports = function () {
|
|
4
|
+
return actor({
|
|
5
|
+
|
|
6
|
+
// Define custom steps here, use 'this' to access default methods of I.
|
|
7
|
+
// It is recommended to place a general 'login' function here.
|
|
8
|
+
|
|
9
|
+
});
|
|
10
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
const assert = require('assert');
|
|
2
|
+
|
|
3
|
+
describe('Sample mocha suite', () => {
|
|
4
|
+
it('Sample mocha test', () => {
|
|
5
|
+
assert.equal([1, 2, 3].indexOf(4), 0);
|
|
6
|
+
});
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
describe('Sample mocha suite 2', () => {
|
|
10
|
+
it('Sample mocha test 2', () => {
|
|
11
|
+
assert.equal(1, 1);
|
|
12
|
+
});
|
|
13
|
+
});
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
const { assert } = require('chai');
|
|
2
|
+
const { exec } = require('child_process');
|
|
3
|
+
const ServerMock = require('mock-http-server');
|
|
4
|
+
const JestReporter = require('../../lib/adapter/jest');
|
|
5
|
+
const MochaReporter = require('../../lib/adapter/mocha');
|
|
6
|
+
const JasmineReporter = require('../../lib/adapter/jasmine');
|
|
7
|
+
const CodeceptReporter = require('../../lib/adapter/codecept');
|
|
8
|
+
const { registerHandlers } = require('./utils');
|
|
9
|
+
const { host, port, TESTOMATIO_URL, TESTOMATIO, RUN_ID } = require('./config');
|
|
10
|
+
|
|
11
|
+
const params = [
|
|
12
|
+
{
|
|
13
|
+
adapterName: JestReporter.name,
|
|
14
|
+
positiveCmd: `TESTOMATIO_URL=${TESTOMATIO_URL} TESTOMATIO=${TESTOMATIO} npm run test:adapter:jest:example`,
|
|
15
|
+
negativeCmd: `TESTOMATIO_URL=${TESTOMATIO_URL} npm run test:adapter:jest:example`,
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
adapterName: MochaReporter.name,
|
|
19
|
+
positiveCmd: `TESTOMATIO_URL=${TESTOMATIO_URL} TESTOMATIO=${TESTOMATIO} npm run test:adapter:mocha:example`,
|
|
20
|
+
negativeCmd: `TESTOMATIO_URL=${TESTOMATIO_URL} npm run test:adapter:mocha:example`,
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
adapterName: JasmineReporter.name,
|
|
24
|
+
positiveCmd: `TESTOMATIO_URL=${TESTOMATIO_URL} TESTOMATIO=${TESTOMATIO} npm run test:adapter:jasmine:example`,
|
|
25
|
+
negativeCmd: `TESTOMATIO_URL=${TESTOMATIO_URL} npm run test:adapter:jasmine:example`,
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
adapterName: CodeceptReporter.name,
|
|
29
|
+
positiveCmd: `TESTOMATIO_URL=${TESTOMATIO_URL} TESTOMATIO=${TESTOMATIO} npm run test:adapter:jasmine:example`,
|
|
30
|
+
negativeCmd: `TESTOMATIO_URL=${TESTOMATIO_URL} npm run test:adapter:jasmine:example`,
|
|
31
|
+
},
|
|
32
|
+
];
|
|
33
|
+
|
|
34
|
+
describe('Adapters', () => {
|
|
35
|
+
const server = new ServerMock({ host, port });
|
|
36
|
+
|
|
37
|
+
before(done => {
|
|
38
|
+
server.start(() => {
|
|
39
|
+
console.log(`[mock-http-server]: Server started at ${TESTOMATIO_URL}`);
|
|
40
|
+
|
|
41
|
+
done();
|
|
42
|
+
});
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
after(done => {
|
|
46
|
+
server.stop(() => {
|
|
47
|
+
console.log('[mock-http-server]: Server stopped');
|
|
48
|
+
|
|
49
|
+
done();
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
for (const { adapterName, positiveCmd, negativeCmd } of params) {
|
|
54
|
+
describe(adapterName, () => {
|
|
55
|
+
describe('positive tests', () => {
|
|
56
|
+
before(function (done) {
|
|
57
|
+
this.timeout(5000);
|
|
58
|
+
|
|
59
|
+
registerHandlers(server, RUN_ID);
|
|
60
|
+
|
|
61
|
+
exec(positiveCmd, () => done());
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
after(() => {
|
|
65
|
+
server.reset();
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
it('POST :: /api/reporter :: should create a report if api_key has been provided', () => {
|
|
69
|
+
const [req] = server.requests({ method: 'POST', path: '/api/reporter' });
|
|
70
|
+
|
|
71
|
+
const expectedResult = { api_key: TESTOMATIO };
|
|
72
|
+
|
|
73
|
+
assert.isObject(req.body);
|
|
74
|
+
assert.deepEqual(req.body, expectedResult);
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
it('PUT :: /api/reporter/:runId :: should update run status', () => {
|
|
78
|
+
const [req] = server.requests({ method: 'PUT', path: `/api/reporter/${RUN_ID}` });
|
|
79
|
+
|
|
80
|
+
const expectedResult = { api_key: TESTOMATIO, status_event: 'fail', status: 'failed' };
|
|
81
|
+
|
|
82
|
+
assert.isObject(req.body);
|
|
83
|
+
assert.deepEqual(req.body, expectedResult);
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
it('POST :: /api/reporter/:runId/testrun :: should add a new test to run instance', () => {
|
|
87
|
+
const reqs = server.requests({ method: 'POST', path: `/api/reporter/${RUN_ID}/testrun` });
|
|
88
|
+
|
|
89
|
+
const expectedRequiredBodyKeys = [
|
|
90
|
+
'api_key',
|
|
91
|
+
'files',
|
|
92
|
+
// 'steps',
|
|
93
|
+
'status',
|
|
94
|
+
'stack',
|
|
95
|
+
'example',
|
|
96
|
+
'title',
|
|
97
|
+
'message',
|
|
98
|
+
'run_time',
|
|
99
|
+
'artifacts',
|
|
100
|
+
];
|
|
101
|
+
|
|
102
|
+
for (const req of reqs) {
|
|
103
|
+
assert.isObject(req.body);
|
|
104
|
+
assert.includeMembers(Object.keys(req.body), expectedRequiredBodyKeys);
|
|
105
|
+
|
|
106
|
+
assert.strictEqual(req.body.api_key, TESTOMATIO);
|
|
107
|
+
assert.isString(req.body.status);
|
|
108
|
+
assert.isString(req.body.title);
|
|
109
|
+
assert.isNumber(req.body.run_time);
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
describe('negative tests', () => {
|
|
115
|
+
before(function (done) {
|
|
116
|
+
this.timeout(5000);
|
|
117
|
+
|
|
118
|
+
registerHandlers(server, RUN_ID);
|
|
119
|
+
|
|
120
|
+
exec(negativeCmd, () => done());
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
after(() => {
|
|
124
|
+
server.reset();
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
it('should ignore reporter if api_key has not been provided', () => {
|
|
128
|
+
const requests = server.requests();
|
|
129
|
+
|
|
130
|
+
assert.isArray(requests);
|
|
131
|
+
assert.isEmpty(requests);
|
|
132
|
+
});
|
|
133
|
+
});
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
});
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
const registerHandlers = (server, RUN_ID) => {
|
|
2
|
+
// client.createRun()
|
|
3
|
+
server.on({
|
|
4
|
+
method: 'POST',
|
|
5
|
+
path: '/api/reporter',
|
|
6
|
+
reply: {
|
|
7
|
+
status: 200,
|
|
8
|
+
headers: { 'content-type': 'application/json' },
|
|
9
|
+
body: JSON.stringify({
|
|
10
|
+
uid: RUN_ID,
|
|
11
|
+
url: `http://127.0.0.1:3000/projects/test-project/runs/${RUN_ID}/report`,
|
|
12
|
+
}),
|
|
13
|
+
},
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
// client.updateRunStatus()
|
|
17
|
+
server.on({
|
|
18
|
+
method: 'PUT',
|
|
19
|
+
path: `/api/reporter/${RUN_ID}`,
|
|
20
|
+
reply: {
|
|
21
|
+
status: 200,
|
|
22
|
+
headers: { 'content-type': 'application/json' },
|
|
23
|
+
},
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
// client.addTestRun()
|
|
27
|
+
server.on({
|
|
28
|
+
method: 'POST',
|
|
29
|
+
path: `/api/reporter/${RUN_ID}/testrun`,
|
|
30
|
+
reply: {
|
|
31
|
+
status: 400,
|
|
32
|
+
headers: { 'content-type': 'application/json' },
|
|
33
|
+
body: JSON.stringify({ message: 'Test could not be matched' }),
|
|
34
|
+
},
|
|
35
|
+
});
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
module.exports = {
|
|
39
|
+
registerHandlers,
|
|
40
|
+
};
|
package/.prettierrc.json
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{}
|