@applitools/eyes-cypress 3.23.9 → 3.24.0-beta.2
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/CHANGELOG.md +2195 -2186
- package/LICENSE +25 -25
- package/README.md +778 -769
- package/bin/eyes-setup.js +21 -21
- package/commands.js +2 -2
- package/dist/browser/spec-driver.js +104 -0
- package/dist/plugin/handler.js +55 -0
- package/eyes-index.d.ts +34 -34
- package/index.js +2 -2
- package/package.json +97 -81
- package/src/browser/commands.js +167 -147
- package/src/browser/eyesCheckMapping.js +71 -0
- package/src/browser/eyesOpenMapping.js +34 -0
- package/src/browser/makeSend.js +18 -22
- package/src/browser/refer.js +57 -0
- package/src/browser/sendRequest.js +16 -16
- package/src/browser/socket.js +143 -0
- package/src/browser/socketCommands.js +81 -0
- package/src/browser/spec-driver.ts +109 -0
- package/src/pem/server.cert +22 -22
- package/src/pem/server.key +27 -27
- package/src/plugin/concurrencyMsg.js +8 -8
- package/src/plugin/config.js +54 -53
- package/src/plugin/defaultPort.js +1 -1
- package/src/plugin/errorDigest.js +96 -96
- package/src/plugin/getErrorsAndDiffs.js +34 -34
- package/src/plugin/handleTestResults.js +39 -0
- package/src/plugin/handler.ts +58 -0
- package/src/plugin/hooks.js +49 -42
- package/src/plugin/isGlobalHooksSupported.js +13 -13
- package/src/plugin/pluginExport.js +60 -57
- package/src/plugin/server.js +98 -46
- package/src/plugin/startPlugin.js +13 -34
- package/src/plugin/webSocket.js +130 -0
- package/src/setup/addEyesCommands.js +24 -24
- package/src/setup/addEyesCypressPlugin.js +15 -15
- package/src/setup/getCypressConfig.js +16 -16
- package/src/setup/getFilePath.js +22 -22
- package/src/setup/handleCommands.js +23 -23
- package/src/setup/handlePlugin.js +23 -23
- package/src/setup/handleTypeScript.js +21 -21
- package/src/setup/isCommandsDefined.js +7 -7
- package/src/setup/isPluginDefined.js +7 -7
- package/test/fixtures/testAppCopies/.gitignore +1 -1
- package/src/browser/eyesCheckWindow.js +0 -132
- package/src/browser/getAllBlobs.js +0 -14
- package/src/browser/getBrowserInfo.js +0 -39
- package/src/browser/makeHandleCypressViewport.js +0 -22
- package/src/browser/poll.js +0 -25
- package/src/plugin/app.js +0 -42
- package/src/plugin/handlers.js +0 -205
- package/src/plugin/makeHandleBatchResultsFile.js +0 -17
- package/src/plugin/pollingHandler.js +0 -46
- package/src/plugin/processCloseAndAbort.js +0 -33
- package/src/plugin/runningTests.js +0 -27
- package/src/plugin/waitForBatch.js +0 -33
|
@@ -1,96 +1,96 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const colors = {
|
|
4
|
-
green: '\x1b[32m',
|
|
5
|
-
red: '\x1b[31m',
|
|
6
|
-
teal: '\x1b[38;5;86m',
|
|
7
|
-
orange: '\x1b[38;5;214m',
|
|
8
|
-
reset: '\x1b[0m',
|
|
9
|
-
};
|
|
10
|
-
|
|
11
|
-
const formatByStatus = {
|
|
12
|
-
Passed: {
|
|
13
|
-
color: 'green',
|
|
14
|
-
symbol: '\u2713',
|
|
15
|
-
title: tests => `Passed - ${tests} tests`,
|
|
16
|
-
},
|
|
17
|
-
Failed: {
|
|
18
|
-
color: 'red',
|
|
19
|
-
symbol: '\u2716',
|
|
20
|
-
title: tests => `Errors - ${tests} tests`,
|
|
21
|
-
},
|
|
22
|
-
Unresolved: {
|
|
23
|
-
color: 'orange',
|
|
24
|
-
symbol: '\u26A0',
|
|
25
|
-
title: tests => `Diffs detected - ${tests} tests`,
|
|
26
|
-
},
|
|
27
|
-
};
|
|
28
|
-
|
|
29
|
-
function errorDigest({passed, failed, diffs, logger, isInteractive}) {
|
|
30
|
-
logger.log('errorDigest: diff errors', diffs);
|
|
31
|
-
logger.log('errorDigest: test errors', failed);
|
|
32
|
-
|
|
33
|
-
const testResultsUrl = diffs.length ? colorify(diffs[0].getUrl(), 'teal') : '';
|
|
34
|
-
const testResultsPrefix = testResultsUrl ? 'See details at:' : '';
|
|
35
|
-
const footer = testResultsUrl
|
|
36
|
-
? `\n${indent()}${colorify(testResultsPrefix)} ${testResultsUrl}`
|
|
37
|
-
: '';
|
|
38
|
-
return (
|
|
39
|
-
colorify('Eyes-Cypress detected diffs or errors during execution of visual tests.') +
|
|
40
|
-
colorify(` ${testResultsPrefix} ${testResultsUrl}`) +
|
|
41
|
-
testResultsToString(passed, 'Passed') +
|
|
42
|
-
testResultsToString(diffs, 'Unresolved') +
|
|
43
|
-
testResultsToString(failed, 'Failed') +
|
|
44
|
-
footer +
|
|
45
|
-
'\n\n'
|
|
46
|
-
);
|
|
47
|
-
|
|
48
|
-
function testResultsToString(testResultsArr, category) {
|
|
49
|
-
const {color, title, symbol, chalkFunction} = formatByStatus[category];
|
|
50
|
-
const results = testResultsArr.reduce((acc, testResults) => {
|
|
51
|
-
if (!testResults.isEmpty) {
|
|
52
|
-
const error = hasError(testResults) ? stringifyError(testResults) : undefined;
|
|
53
|
-
acc.push(
|
|
54
|
-
`${colorify(symbol, color)} ${colorify(error || stringifyTestResults(testResults))}`,
|
|
55
|
-
);
|
|
56
|
-
}
|
|
57
|
-
return acc;
|
|
58
|
-
}, []);
|
|
59
|
-
|
|
60
|
-
const coloredTitle = results.length
|
|
61
|
-
? colorify(title(results.length), color, chalkFunction)
|
|
62
|
-
: '';
|
|
63
|
-
return testResultsSection(coloredTitle, results);
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
function colorify(msg, color = 'reset') {
|
|
67
|
-
return isInteractive ? msg : `${colors[color]}${msg}${colors.reset}`;
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
function stringifyTestResults(testResults) {
|
|
72
|
-
const hostDisplaySize = testResults.getHostDisplaySize();
|
|
73
|
-
const viewport = hostDisplaySize ? `[${hostDisplaySize}]` : '';
|
|
74
|
-
const testName = `${testResults.getName()} ${viewport}`;
|
|
75
|
-
return testName + (testResults.error ? ` : ${testResults.error}` : '');
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
function testResultsSection(title, results) {
|
|
79
|
-
return results.length ? `${indent()}${title}${indent(3)}${results.join(indent(3))}` : '';
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
function stringifyError(testResults) {
|
|
83
|
-
return testResults.error
|
|
84
|
-
? stringifyTestResults(testResults)
|
|
85
|
-
: `[Eyes test not started] : ${testResults}`;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
function indent(spaces = 2) {
|
|
89
|
-
return `\n ${' '.repeat(spaces)}`;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
function hasError(testResult) {
|
|
93
|
-
return testResult.error || testResult instanceof Error;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
module.exports = errorDigest;
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const colors = {
|
|
4
|
+
green: '\x1b[32m',
|
|
5
|
+
red: '\x1b[31m',
|
|
6
|
+
teal: '\x1b[38;5;86m',
|
|
7
|
+
orange: '\x1b[38;5;214m',
|
|
8
|
+
reset: '\x1b[0m',
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
const formatByStatus = {
|
|
12
|
+
Passed: {
|
|
13
|
+
color: 'green',
|
|
14
|
+
symbol: '\u2713',
|
|
15
|
+
title: tests => `Passed - ${tests} tests`,
|
|
16
|
+
},
|
|
17
|
+
Failed: {
|
|
18
|
+
color: 'red',
|
|
19
|
+
symbol: '\u2716',
|
|
20
|
+
title: tests => `Errors - ${tests} tests`,
|
|
21
|
+
},
|
|
22
|
+
Unresolved: {
|
|
23
|
+
color: 'orange',
|
|
24
|
+
symbol: '\u26A0',
|
|
25
|
+
title: tests => `Diffs detected - ${tests} tests`,
|
|
26
|
+
},
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
function errorDigest({passed, failed, diffs, logger, isInteractive}) {
|
|
30
|
+
logger.log('errorDigest: diff errors', diffs);
|
|
31
|
+
logger.log('errorDigest: test errors', failed);
|
|
32
|
+
|
|
33
|
+
const testResultsUrl = diffs.length ? colorify(diffs[0].getUrl(), 'teal') : '';
|
|
34
|
+
const testResultsPrefix = testResultsUrl ? 'See details at:' : '';
|
|
35
|
+
const footer = testResultsUrl
|
|
36
|
+
? `\n${indent()}${colorify(testResultsPrefix)} ${testResultsUrl}`
|
|
37
|
+
: '';
|
|
38
|
+
return (
|
|
39
|
+
colorify('Eyes-Cypress detected diffs or errors during execution of visual tests.') +
|
|
40
|
+
colorify(` ${testResultsPrefix} ${testResultsUrl}`) +
|
|
41
|
+
testResultsToString(passed, 'Passed') +
|
|
42
|
+
testResultsToString(diffs, 'Unresolved') +
|
|
43
|
+
testResultsToString(failed, 'Failed') +
|
|
44
|
+
footer +
|
|
45
|
+
'\n\n'
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
function testResultsToString(testResultsArr, category) {
|
|
49
|
+
const {color, title, symbol, chalkFunction} = formatByStatus[category];
|
|
50
|
+
const results = testResultsArr.reduce((acc, testResults) => {
|
|
51
|
+
if (!testResults.isEmpty) {
|
|
52
|
+
const error = hasError(testResults) ? stringifyError(testResults) : undefined;
|
|
53
|
+
acc.push(
|
|
54
|
+
`${colorify(symbol, color)} ${colorify(error || stringifyTestResults(testResults))}`,
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
return acc;
|
|
58
|
+
}, []);
|
|
59
|
+
|
|
60
|
+
const coloredTitle = results.length
|
|
61
|
+
? colorify(title(results.length), color, chalkFunction)
|
|
62
|
+
: '';
|
|
63
|
+
return testResultsSection(coloredTitle, results);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function colorify(msg, color = 'reset') {
|
|
67
|
+
return isInteractive ? msg : `${colors[color]}${msg}${colors.reset}`;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function stringifyTestResults(testResults) {
|
|
72
|
+
const hostDisplaySize = testResults.getHostDisplaySize();
|
|
73
|
+
const viewport = hostDisplaySize ? `[${hostDisplaySize}]` : '';
|
|
74
|
+
const testName = `${testResults.getName()} ${viewport}`;
|
|
75
|
+
return testName + (testResults.error ? ` : ${testResults.error}` : '');
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function testResultsSection(title, results) {
|
|
79
|
+
return results.length ? `${indent()}${title}${indent(3)}${results.join(indent(3))}` : '';
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function stringifyError(testResults) {
|
|
83
|
+
return testResults.error
|
|
84
|
+
? stringifyTestResults(testResults)
|
|
85
|
+
: `[Eyes test not started] : ${testResults}`;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function indent(spaces = 2) {
|
|
89
|
+
return `\n ${' '.repeat(spaces)}`;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function hasError(testResult) {
|
|
93
|
+
return testResult.error || testResult instanceof Error;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
module.exports = errorDigest;
|
|
@@ -1,34 +1,34 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
function getErrorsAndDiffs(testResultsArr) {
|
|
4
|
-
return testResultsArr.reduce(
|
|
5
|
-
({failed, diffs, passed}, testResults) => {
|
|
6
|
-
if (testResults instanceof Error || testResults.error) {
|
|
7
|
-
failed.push(testResults);
|
|
8
|
-
} else {
|
|
9
|
-
const testStatus = testResults.getStatus();
|
|
10
|
-
if (testStatus === 'Passed') {
|
|
11
|
-
passed.push(testResults);
|
|
12
|
-
} else {
|
|
13
|
-
if (testStatus === 'Unresolved') {
|
|
14
|
-
if (testResults.getIsNew()) {
|
|
15
|
-
testResults.error = new Error(
|
|
16
|
-
`${testResults.getName()}. Please approve the new baseline at ${testResults.getUrl()}`,
|
|
17
|
-
);
|
|
18
|
-
failed.push(testResults);
|
|
19
|
-
} else {
|
|
20
|
-
diffs.push(testResults);
|
|
21
|
-
}
|
|
22
|
-
} else if (testStatus === 'Failed') {
|
|
23
|
-
failed.push(testResults);
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
return {failed, diffs, passed};
|
|
29
|
-
},
|
|
30
|
-
{failed: [], diffs: [], passed: []},
|
|
31
|
-
);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
module.exports = getErrorsAndDiffs;
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
function getErrorsAndDiffs(testResultsArr) {
|
|
4
|
+
return testResultsArr.reduce(
|
|
5
|
+
({failed, diffs, passed}, testResults) => {
|
|
6
|
+
if (testResults instanceof Error || testResults.error) {
|
|
7
|
+
failed.push(testResults);
|
|
8
|
+
} else {
|
|
9
|
+
const testStatus = testResults.getStatus();
|
|
10
|
+
if (testStatus === 'Passed') {
|
|
11
|
+
passed.push(testResults);
|
|
12
|
+
} else {
|
|
13
|
+
if (testStatus === 'Unresolved') {
|
|
14
|
+
if (testResults.getIsNew()) {
|
|
15
|
+
testResults.error = new Error(
|
|
16
|
+
`${testResults.getName()}. Please approve the new baseline at ${testResults.getUrl()}`,
|
|
17
|
+
);
|
|
18
|
+
failed.push(testResults);
|
|
19
|
+
} else {
|
|
20
|
+
diffs.push(testResults);
|
|
21
|
+
}
|
|
22
|
+
} else if (testStatus === 'Failed') {
|
|
23
|
+
failed.push(testResults);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
return {failed, diffs, passed};
|
|
29
|
+
},
|
|
30
|
+
{failed: [], diffs: [], passed: []},
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
module.exports = getErrorsAndDiffs;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
const errorDigest = require('./errorDigest');
|
|
2
|
+
const {makeLogger} = require('@applitools/logger');
|
|
3
|
+
const getErrorsAndDiffs = require('./getErrorsAndDiffs');
|
|
4
|
+
const {promisify} = require('util');
|
|
5
|
+
const fs = require('fs');
|
|
6
|
+
const writeFile = promisify(fs.writeFile);
|
|
7
|
+
const {TestResultsFormatter} = require('@applitools/visual-grid-client');
|
|
8
|
+
const {resolve} = require('path');
|
|
9
|
+
|
|
10
|
+
function printTestResults(testResultsArr) {
|
|
11
|
+
const logger = makeLogger({
|
|
12
|
+
level: testResultsArr.resultConfig.showLogs ? 'info' : 'silent',
|
|
13
|
+
label: 'eyes',
|
|
14
|
+
});
|
|
15
|
+
const {passed, failed, diffs} = getErrorsAndDiffs(testResultsArr.testResults);
|
|
16
|
+
if ((failed.length || diffs.length) && !!testResultsArr.resultConfig.eyesFailCypressOnDiff) {
|
|
17
|
+
throw new Error(
|
|
18
|
+
errorDigest({
|
|
19
|
+
passed,
|
|
20
|
+
failed,
|
|
21
|
+
diffs,
|
|
22
|
+
logger,
|
|
23
|
+
isInteractive: !testResultsArr.resultConfig.isTextTerminal,
|
|
24
|
+
}),
|
|
25
|
+
);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
function handleBatchResultsFile(results, tapFileConfig) {
|
|
29
|
+
try {
|
|
30
|
+
const formatter = new TestResultsFormatter(results);
|
|
31
|
+
const fileName = tapFileConfig.tapFileName || `${new Date().toISOString()}-eyes.tap`;
|
|
32
|
+
const tapFile = resolve(tapFileConfig.tapDirPath, fileName);
|
|
33
|
+
return writeFile(tapFile, formatter.asHierarchicTAPString(false, true));
|
|
34
|
+
} catch (ex) {
|
|
35
|
+
console.log(ex);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
module.exports = {printTestResults, handleBatchResultsFile};
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import {Server as HTTPServer, request} from 'http'
|
|
2
|
+
import {Server as WSServer} from 'ws'
|
|
3
|
+
|
|
4
|
+
const {name, version} = require('../../package.json') // TODO is the handshake needed at all?
|
|
5
|
+
const TOKEN_HEADER = 'x-eyes-universal-token'
|
|
6
|
+
const TOKEN = `${name}@${version}`
|
|
7
|
+
|
|
8
|
+
// TODO make default port 0 and return actual port
|
|
9
|
+
export async function makeHandler({port = 31077, singleton = true, lazy = false} = {}): Promise<{
|
|
10
|
+
server?: WSServer
|
|
11
|
+
port: number
|
|
12
|
+
}> {
|
|
13
|
+
const http = new HTTPServer()
|
|
14
|
+
http.on('request', (request, response) => {
|
|
15
|
+
if (request.url === '/handshake') {
|
|
16
|
+
if (request.headers[TOKEN_HEADER] === TOKEN) {
|
|
17
|
+
response.writeHead(200, {[TOKEN_HEADER]: TOKEN})
|
|
18
|
+
} else {
|
|
19
|
+
response.writeHead(400)
|
|
20
|
+
}
|
|
21
|
+
response.end()
|
|
22
|
+
}
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
http.listen(port, 'localhost')
|
|
26
|
+
|
|
27
|
+
return new Promise((resolve, reject) => {
|
|
28
|
+
http.on('listening', () => {
|
|
29
|
+
const ws = new WSServer({server: http, path: '/eyes'})
|
|
30
|
+
ws.on('close', () => http.close())
|
|
31
|
+
resolve({server: ws, port})
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
http.on('error', async (err: Error & {code: string}) => {
|
|
35
|
+
if (!lazy && err.code === 'EADDRINUSE') {
|
|
36
|
+
if (singleton && (await isHandshakable(port))) {
|
|
37
|
+
return resolve({port})
|
|
38
|
+
} else {
|
|
39
|
+
return resolve(await makeHandler({port: port + 1, singleton}))
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
reject(err)
|
|
43
|
+
})
|
|
44
|
+
})
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
async function isHandshakable(port: number) {
|
|
48
|
+
return new Promise(resolve => {
|
|
49
|
+
const handshake = request(`http://localhost:${port}/handshake`, {
|
|
50
|
+
headers: {[TOKEN_HEADER]: TOKEN},
|
|
51
|
+
})
|
|
52
|
+
handshake.on('response', ({statusCode, headers}) => {
|
|
53
|
+
resolve(statusCode === 200 && headers[TOKEN_HEADER] === TOKEN)
|
|
54
|
+
})
|
|
55
|
+
handshake.on('error', () => resolve(false))
|
|
56
|
+
handshake.end()
|
|
57
|
+
})
|
|
58
|
+
}
|
package/src/plugin/hooks.js
CHANGED
|
@@ -1,42 +1,49 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
const
|
|
3
|
-
const
|
|
4
|
-
const
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
if (
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
1
|
+
'use strict';
|
|
2
|
+
const flatten = require('lodash.flatten');
|
|
3
|
+
const {TestResults} = require('@applitools/visual-grid-client');
|
|
4
|
+
const handleTestResults = require('./handleTestResults');
|
|
5
|
+
|
|
6
|
+
function makeGlobalRunHooks({closeAllEyes, closeBatches, closeUniversalServer}) {
|
|
7
|
+
return {
|
|
8
|
+
'before:run': ({config}) => {
|
|
9
|
+
if (!config.isTextTerminal) return;
|
|
10
|
+
},
|
|
11
|
+
|
|
12
|
+
'after:run': async ({config}) => {
|
|
13
|
+
try {
|
|
14
|
+
if (!config.isTextTerminal) return;
|
|
15
|
+
const resultConfig = {
|
|
16
|
+
showLogs: config.showLogs,
|
|
17
|
+
eyesFailCypressOnDiff: config.eyesFailCypressOnDiff,
|
|
18
|
+
isTextTerminal: config.isTextTerminal,
|
|
19
|
+
};
|
|
20
|
+
const testResults = await closeAllEyes();
|
|
21
|
+
const testResultsArr = [];
|
|
22
|
+
for (const result of flatten(testResults)) {
|
|
23
|
+
testResultsArr.push(new TestResults(result));
|
|
24
|
+
}
|
|
25
|
+
if (!config.appliConfFile.dontCloseBatches) {
|
|
26
|
+
await closeBatches({
|
|
27
|
+
batchIds: [config.appliConfFile.batch.id],
|
|
28
|
+
serverUrl: config.appliConfFile.serverUrl,
|
|
29
|
+
proxy: config.appliConfFile.proxy,
|
|
30
|
+
apiKey: config.appliConfFile.apiKey,
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (config.appliConfFile.tapDirPath) {
|
|
35
|
+
await handleTestResults.handleBatchResultsFile(testResultsArr, {
|
|
36
|
+
tapDirPath: config.appliConfFile.tapDirPath,
|
|
37
|
+
tapFileName: config.appliConfFile.tapFileName,
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
handleTestResults.printTestResults({testResults: testResultsArr, resultConfig});
|
|
42
|
+
} finally {
|
|
43
|
+
closeUniversalServer();
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
module.exports = makeGlobalRunHooks;
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
const CYPRESS_SUPPORTED_VERSION = '6.2.0';
|
|
2
|
-
const CYPRESS_NO_FLAG_VERSION = '6.7.0';
|
|
3
|
-
|
|
4
|
-
function isGlobalHooksSupported(config) {
|
|
5
|
-
const {version, experimentalRunEvents} = config;
|
|
6
|
-
|
|
7
|
-
return (
|
|
8
|
-
version >= CYPRESS_NO_FLAG_VERSION ||
|
|
9
|
-
(version >= CYPRESS_SUPPORTED_VERSION && !!experimentalRunEvents)
|
|
10
|
-
);
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
module.exports = isGlobalHooksSupported;
|
|
1
|
+
const CYPRESS_SUPPORTED_VERSION = '6.2.0';
|
|
2
|
+
const CYPRESS_NO_FLAG_VERSION = '6.7.0';
|
|
3
|
+
|
|
4
|
+
function isGlobalHooksSupported(config) {
|
|
5
|
+
const {version, experimentalRunEvents} = config;
|
|
6
|
+
|
|
7
|
+
return (
|
|
8
|
+
version >= CYPRESS_NO_FLAG_VERSION ||
|
|
9
|
+
(version >= CYPRESS_SUPPORTED_VERSION && !!experimentalRunEvents)
|
|
10
|
+
);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
module.exports = isGlobalHooksSupported;
|
|
@@ -1,57 +1,60 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
const isGlobalHooksSupported = require('./isGlobalHooksSupported');
|
|
3
|
-
const {presult} = require('@applitools/functional-commons');
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
pluginModule.exports
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
//
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
await
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
};
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
1
|
+
'use strict';
|
|
2
|
+
const isGlobalHooksSupported = require('./isGlobalHooksSupported');
|
|
3
|
+
const {presult} = require('@applitools/functional-commons');
|
|
4
|
+
const makeGlobalRunHooks = require('./hooks');
|
|
5
|
+
|
|
6
|
+
function makePluginExport({startServer, eyesConfig}) {
|
|
7
|
+
return function pluginExport(pluginModule) {
|
|
8
|
+
let eyesServer;
|
|
9
|
+
const pluginModuleExports = pluginModule.exports;
|
|
10
|
+
pluginModule.exports = async function(...args) {
|
|
11
|
+
const {server, port, closeAllEyes, closeBatches, closeUniversalServer} = await startServer();
|
|
12
|
+
eyesServer = server;
|
|
13
|
+
|
|
14
|
+
const globalHooks = makeGlobalRunHooks({closeAllEyes, closeBatches, closeUniversalServer});
|
|
15
|
+
|
|
16
|
+
const [origOn, config] = args;
|
|
17
|
+
const isGlobalHookCalledFromUserHandlerMap = new Map();
|
|
18
|
+
eyesConfig.eyesIsGlobalHooksSupported = isGlobalHooksSupported(config);
|
|
19
|
+
const moduleExportsResult = await pluginModuleExports(onThatCallsUserDefinedHandler, config);
|
|
20
|
+
if (eyesConfig.eyesIsGlobalHooksSupported) {
|
|
21
|
+
for (const [eventName, eventHandler] of Object.entries(globalHooks)) {
|
|
22
|
+
if (!isGlobalHookCalledFromUserHandlerMap.get(eventName)) {
|
|
23
|
+
origOn.call(this, eventName, eventHandler);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
return Object.assign({}, eyesConfig, {eyesPort: port}, moduleExportsResult);
|
|
29
|
+
|
|
30
|
+
// This piece of code exists because at the point of writing, Cypress does not support multiple event handlers:
|
|
31
|
+
// https://github.com/cypress-io/cypress/issues/5240#issuecomment-948277554
|
|
32
|
+
// So we wrap Cypress' `on` function in order to wrap the user-defined handler. This way we can call our own handler
|
|
33
|
+
// in addition to the user's handler
|
|
34
|
+
function onThatCallsUserDefinedHandler(eventName, handler) {
|
|
35
|
+
const isRunEvent = eventName === 'before:run' || eventName === 'after:run';
|
|
36
|
+
let handlerToCall = handler;
|
|
37
|
+
if (eyesConfig.eyesIsGlobalHooksSupported && isRunEvent) {
|
|
38
|
+
handlerToCall = handlerThatCallsUserDefinedHandler;
|
|
39
|
+
isGlobalHookCalledFromUserHandlerMap.set(eventName, true);
|
|
40
|
+
}
|
|
41
|
+
return origOn.call(this, eventName, handlerToCall);
|
|
42
|
+
|
|
43
|
+
async function handlerThatCallsUserDefinedHandler() {
|
|
44
|
+
const [err] = await presult(
|
|
45
|
+
Promise.resolve(globalHooks[eventName].apply(this, arguments)),
|
|
46
|
+
);
|
|
47
|
+
await handler.apply(this, arguments);
|
|
48
|
+
if (err) {
|
|
49
|
+
throw err;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
return function getCloseServer() {
|
|
55
|
+
return eyesServer.close();
|
|
56
|
+
};
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
module.exports = makePluginExport;
|