@applitools/eyes-cypress 3.24.0-beta.5 → 3.25.0
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 +2191 -2195
- package/LICENSE +25 -25
- package/README.md +803 -782
- package/bin/eyes-setup.js +21 -21
- package/commands.js +2 -2
- package/dist/browser/spec-driver.js +110 -106
- package/dist/plugin/handler.js +55 -55
- package/eyes-index.d.ts +34 -34
- package/index.js +2 -2
- package/package.json +98 -97
- package/src/browser/commands.js +188 -188
- package/src/browser/eyesCheckMapping.js +104 -103
- package/src/browser/eyesOpenMapping.js +60 -60
- package/src/browser/makeSend.js +18 -18
- package/src/browser/refer.js +57 -57
- package/src/browser/sendRequest.js +16 -16
- package/src/browser/socket.js +144 -143
- package/src/browser/socketCommands.js +81 -81
- package/src/browser/spec-driver.ts +117 -111
- 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 -54
- 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 +35 -39
- package/src/plugin/handler.ts +58 -58
- package/src/plugin/hooks.js +51 -50
- package/src/plugin/isGlobalHooksSupported.js +13 -13
- package/src/plugin/pluginExport.js +60 -60
- package/src/plugin/server.js +98 -98
- package/src/plugin/startPlugin.js +15 -13
- package/src/plugin/webSocket.js +130 -130
- 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
|
@@ -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;
|
|
@@ -1,39 +1,35 @@
|
|
|
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
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
module.exports = {printTestResults, handleBatchResultsFile};
|
|
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
|
+
const formatter = new TestResultsFormatter(results);
|
|
30
|
+
const fileName = tapFileConfig.tapFileName || `${new Date().toISOString()}-eyes.tap`;
|
|
31
|
+
const tapFile = resolve(tapFileConfig.tapDirPath, fileName);
|
|
32
|
+
return writeFile(tapFile, formatter.asHierarchicTAPString(false, true));
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
module.exports = {printTestResults, handleBatchResultsFile};
|
package/src/plugin/handler.ts
CHANGED
|
@@ -1,58 +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
|
-
}
|
|
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,50 +1,51 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
const
|
|
3
|
-
const
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
const
|
|
21
|
-
const
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
|
|
1
|
+
'use strict';
|
|
2
|
+
const {TestResults} = require('@applitools/visual-grid-client');
|
|
3
|
+
const handleTestResults = require('./handleTestResults');
|
|
4
|
+
|
|
5
|
+
function makeGlobalRunHooks({closeManager, closeBatches, closeUniversalServer}) {
|
|
6
|
+
return {
|
|
7
|
+
'before:run': ({config}) => {
|
|
8
|
+
if (!config.isTextTerminal) return;
|
|
9
|
+
},
|
|
10
|
+
|
|
11
|
+
'after:run': async ({config}) => {
|
|
12
|
+
try {
|
|
13
|
+
if (!config.isTextTerminal) return;
|
|
14
|
+
const resultConfig = {
|
|
15
|
+
showLogs: config.showLogs,
|
|
16
|
+
eyesFailCypressOnDiff: config.eyesFailCypressOnDiff,
|
|
17
|
+
isTextTerminal: config.isTextTerminal,
|
|
18
|
+
};
|
|
19
|
+
const summaries = await closeManager();
|
|
20
|
+
const testResultsArr = [];
|
|
21
|
+
for (const summary of summaries) {
|
|
22
|
+
const testResults = summary.results.map(({testResults}) => testResults);
|
|
23
|
+
for (const result of testResults) {
|
|
24
|
+
testResultsArr.push(new TestResults(result));
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
if (!config.appliConfFile.dontCloseBatches) {
|
|
28
|
+
await closeBatches({
|
|
29
|
+
batchIds: [config.appliConfFile.batch.id],
|
|
30
|
+
serverUrl: config.appliConfFile.serverUrl,
|
|
31
|
+
proxy: config.appliConfFile.proxy,
|
|
32
|
+
apiKey: config.appliConfFile.apiKey,
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if (config.appliConfFile.tapDirPath) {
|
|
37
|
+
await handleTestResults.handleBatchResultsFile(testResultsArr, {
|
|
38
|
+
tapDirPath: config.appliConfFile.tapDirPath,
|
|
39
|
+
tapFileName: config.appliConfFile.tapFileName,
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
handleTestResults.printTestResults({testResults: testResultsArr, resultConfig});
|
|
44
|
+
} finally {
|
|
45
|
+
await closeUniversalServer();
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
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,60 +1,60 @@
|
|
|
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,
|
|
12
|
-
eyesServer = server;
|
|
13
|
-
|
|
14
|
-
const globalHooks = makeGlobalRunHooks({
|
|
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;
|
|
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, closeManager, closeBatches, closeUniversalServer} = await startServer();
|
|
12
|
+
eyesServer = server;
|
|
13
|
+
|
|
14
|
+
const globalHooks = makeGlobalRunHooks({closeManager, 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;
|