@applitools/eyes-cypress 3.28.3 → 3.29.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.
Files changed (40) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/README.md +28 -2
  3. package/dist/browser/spec-driver.js +0 -8
  4. package/dist/expose.js +7 -0
  5. package/dist/plugin/concurrencyMsg.js +9 -0
  6. package/dist/plugin/config.js +66 -0
  7. package/dist/plugin/configParams.js +47 -0
  8. package/dist/plugin/errorDigest.js +74 -0
  9. package/dist/plugin/getErrorsAndDiffs.js +31 -0
  10. package/dist/plugin/handleTestResults.js +38 -0
  11. package/dist/plugin/hooks.js +43 -0
  12. package/dist/plugin/index.js +17 -0
  13. package/dist/plugin/isGlobalHooksSupported.js +10 -0
  14. package/dist/plugin/pluginExport.js +104 -0
  15. package/dist/plugin/server.js +117 -0
  16. package/dist/plugin/webSocket.js +129 -0
  17. package/index.js +3 -2
  18. package/package.json +37 -18
  19. package/src/browser/spec-driver.ts +1 -1
  20. package/src/expose.ts +71 -0
  21. package/src/plugin/{concurrencyMsg.js → concurrencyMsg.ts} +1 -1
  22. package/src/plugin/{config.js → config.ts} +6 -15
  23. package/src/plugin/{configParams.js → configParams.ts} +1 -3
  24. package/src/plugin/{errorDigest.js → errorDigest.ts} +34 -38
  25. package/src/plugin/{getErrorsAndDiffs.js → getErrorsAndDiffs.ts} +3 -8
  26. package/src/plugin/{handleTestResults.js → handleTestResults.ts} +17 -12
  27. package/src/plugin/hooks.ts +60 -0
  28. package/src/plugin/index.ts +37 -0
  29. package/src/plugin/isGlobalHooksSupported.ts +11 -0
  30. package/src/plugin/pluginExport.ts +118 -0
  31. package/src/plugin/{server.js → server.ts} +30 -33
  32. package/src/plugin/{webSocket.js → webSocket.ts} +34 -23
  33. package/src/setup/handlePlugin.js +21 -2
  34. package/src/setup/isPluginDefinedESM.js +5 -0
  35. package/index.d.ts +0 -86
  36. package/src/plugin/defaultPort.js +0 -1
  37. package/src/plugin/hooks.js +0 -41
  38. package/src/plugin/isGlobalHooksSupported.js +0 -13
  39. package/src/plugin/pluginExport.js +0 -94
  40. package/src/plugin/startPlugin.js +0 -15
package/CHANGELOG.md CHANGED
@@ -12,6 +12,12 @@
12
12
 
13
13
 
14
14
 
15
+ ## 3.29.0 - 2023/2/1
16
+
17
+ ### Features
18
+ - Support ESM and TypeScript in Applitools' config file
19
+ ### Bug fixes
20
+
15
21
  ## 3.28.3 - 2023/1/20
16
22
 
17
23
  ### Features
package/README.md CHANGED
@@ -45,12 +45,38 @@ Normally, this is `cypress/plugins/index.js`. You can read more about it in Cypr
45
45
 
46
46
  #### Cypress version >= 10:
47
47
 
48
- Add the following code to your `cypress.config.js` file after `module.exports`:
48
+ Add the following code to your:
49
+
50
+ ##### `cypress.config.js`
49
51
 
50
52
  ```js
51
- require('@applitools/eyes-cypress')(module)
53
+ const { defineConfig } = require('cypress')
54
+ const eyesPlugin = require('@applitools/eyes-cypress')
55
+ module.exports = eyesPlugin(defineConfig({
56
+ // the e2e or component configuration
57
+ e2e: {
58
+ setupNodeEvents(on, config) {
59
+ }
60
+ }
61
+ }))
52
62
  ```
63
+
64
+ ##### `cypress.config.ts`
65
+
66
+ ```typescript
67
+ import { defineConfig } from 'cypress'
68
+ import eyesPlugin from '@applitools/eyes-cypress'
69
+ export default eyesPlugin(defineConfig({
70
+ // the e2e or component configuration
71
+ e2e: {
72
+ setupNodeEvents(on, config) {
73
+ }
74
+ }
75
+ }))
76
+ ```
77
+
53
78
  This file is normally at the root of the project
79
+
54
80
  ##### 2. Configure custom commands
55
81
 
56
82
  Eyes-Cypress exposes new commands to your tests. This means that more methods will be available on the `cy` object. To enable this, it's required to configure these custom commands.
@@ -15,12 +15,10 @@ function executeScript(context, script, arg) {
15
15
  }
16
16
  exports.executeScript = executeScript;
17
17
  function mainContext() {
18
- //@ts-ignore
19
18
  return cy.state('window').document;
20
19
  }
21
20
  exports.mainContext = mainContext;
22
21
  function parentContext(context) {
23
- // because Cypress doesn't support cross origin iframe, then childContext might return null, and then the input to parentContext might be null
24
22
  if (!context) {
25
23
  throw new Error('Context is not accessible');
26
24
  }
@@ -36,7 +34,6 @@ function childContext(_context, element) {
36
34
  }
37
35
  exports.childContext = childContext;
38
36
  function getViewportSize() {
39
- //@ts-ignore
40
37
  const currWindow = cy.state('window');
41
38
  const viewportSize = {
42
39
  width: currWindow.innerWidth || currWindow.document.documentElement.clientWidth || currWindow.document.body.clientWidth,
@@ -46,7 +43,6 @@ function getViewportSize() {
46
43
  }
47
44
  exports.getViewportSize = getViewportSize;
48
45
  function setViewportSize(vs) {
49
- //@ts-ignore
50
46
  Cypress.action('cy:viewport:changed', { viewportWidth: vs.size.width, viewportHeight: vs.size.height });
51
47
  }
52
48
  exports.setViewportSize = setViewportSize;
@@ -95,10 +91,6 @@ function getUrl(context) {
95
91
  }
96
92
  exports.getUrl = getUrl;
97
93
  function getCookies() {
98
- //@ts-ignore
99
94
  return Cypress.automation('get:cookies', {});
100
95
  }
101
96
  exports.getCookies = getCookies;
102
- // export function takeScreenshot(page: Driver): Promise<Buffer>;
103
- // export function visit(page: Driver, url: string): Promise<void>; (??)
104
- // export function isStaleElementError(err: any): boolean;
package/dist/expose.js ADDED
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const plugin_1 = __importDefault(require("./plugin"));
7
+ exports.default = plugin_1.default;
@@ -0,0 +1,9 @@
1
+ 'use strict';
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const chalk = require('chalk');
4
+ const MSG = `
5
+ Important notice: Your Applitools visual tests are currently running with a testConcurrency value of 5.
6
+ This means that only up to 5 visual tests can run in parallel, and therefore the execution might be slower.
7
+ If your Applitools license supports a higher concurrency level, learn how to configure it here: https://www.npmjs.com/package/@applitools/eyes-cypress#concurrency.
8
+ Need a higher concurrency in your account? Email us @ sdr@applitools.com with your required concurrency level.`;
9
+ exports.default = { concurrencyMsg: chalk.yellow(MSG), msgText: MSG };
@@ -0,0 +1,66 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ var __importDefault = (this && this.__importDefault) || function (mod) {
26
+ return (mod && mod.__esModule) ? mod : { "default": mod };
27
+ };
28
+ Object.defineProperty(exports, "__esModule", { value: true });
29
+ const utils = __importStar(require("@applitools/utils"));
30
+ const configParams_1 = __importDefault(require("./configParams"));
31
+ const DEFAULT_TEST_CONCURRENCY = 5;
32
+ const uuid = __importStar(require("uuid"));
33
+ function makeConfig() {
34
+ const config = utils.config.getConfig({
35
+ params: [...configParams_1.default, 'failCypressOnDiff', 'tapDirPath', 'tapFileName', 'disableBrowserFetching', 'testConcurrency'],
36
+ });
37
+ if ((!config.batch || !config.batch.id) && !config.batchId) {
38
+ config.batch = { id: uuid.v4(), ...config.batch };
39
+ }
40
+ if (config.failCypressOnDiff === '0') {
41
+ config.failCypressOnDiff = false;
42
+ }
43
+ if (utils.types.isString(config.showLogs)) {
44
+ config.showLogs = config.showLogs === 'true' || config.showLogs === '1';
45
+ }
46
+ if (utils.types.isString(config.testConcurrency)) {
47
+ config.testConcurrency = Number(config.testConcurrency);
48
+ }
49
+ if (config.accessibilityValidation) {
50
+ config.accessibilitySettings = config.accessibilityValidation;
51
+ delete config.accessiblityValidation;
52
+ }
53
+ const eyesConfig = {
54
+ tapDirPath: config.tapDirPath,
55
+ tapFileName: config.tapFileName,
56
+ eyesIsDisabled: !!config.isDisabled,
57
+ eyesBrowser: JSON.stringify(config.browser),
58
+ eyesLayoutBreakpoints: JSON.stringify(config.layoutBreakpoints),
59
+ eyesFailCypressOnDiff: config.failCypressOnDiff === undefined ? true : !!config.failCypressOnDiff,
60
+ eyesDisableBrowserFetching: !!config.disableBrowserFetching,
61
+ eyesTestConcurrency: config.testConcurrency || DEFAULT_TEST_CONCURRENCY,
62
+ eyesWaitBeforeCapture: config.waitBeforeCapture,
63
+ };
64
+ return { config, eyesConfig };
65
+ }
66
+ exports.default = makeConfig;
@@ -0,0 +1,47 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const configParams = [
4
+ 'appName',
5
+ 'testName',
6
+ 'displayName',
7
+ 'browser',
8
+ 'url',
9
+ 'apiKey',
10
+ 'showLogs',
11
+ 'batch',
12
+ 'batchId',
13
+ 'batchName',
14
+ 'batchSequenceName',
15
+ 'batchSequence',
16
+ 'properties',
17
+ 'baselineBranchName',
18
+ 'baselineBranch',
19
+ 'baselineEnvName',
20
+ 'baselineName',
21
+ 'envName',
22
+ 'ignoreCaret',
23
+ 'isDisabled',
24
+ 'matchLevel',
25
+ 'parentBranchName',
26
+ 'parentBranch',
27
+ 'branchName',
28
+ 'branch',
29
+ 'proxy',
30
+ 'autProxy',
31
+ 'saveDiffs',
32
+ 'saveFailedTests',
33
+ 'saveNewTests',
34
+ 'compareWithParentBranch',
35
+ 'ignoreBaseline',
36
+ 'serverUrl',
37
+ 'concurrency',
38
+ 'testConcurrency',
39
+ 'useDom',
40
+ 'enablePatterns',
41
+ 'ignoreDisplacements',
42
+ 'accessibilitySettings',
43
+ 'notifyOnCompletion',
44
+ 'batchNotify',
45
+ 'dontCloseBatches',
46
+ ];
47
+ exports.default = configParams;
@@ -0,0 +1,74 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
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
+ const formatByStatus = {
11
+ Passed: {
12
+ color: 'green',
13
+ symbol: '\u2713',
14
+ title: (tests) => `Passed - ${tests} tests`,
15
+ },
16
+ Failed: {
17
+ color: 'red',
18
+ symbol: '\u2716',
19
+ title: (tests) => `Errors - ${tests} tests`,
20
+ },
21
+ Unresolved: {
22
+ color: 'orange',
23
+ symbol: '\u26A0',
24
+ title: (tests) => `Diffs detected - ${tests} tests`,
25
+ },
26
+ };
27
+ function stringifyTestResults(testResults) {
28
+ const hostDisplaySize = testResults.hostDisplaySize;
29
+ const viewport = hostDisplaySize ? `[${hostDisplaySize.width}x${hostDisplaySize.height}]` : '';
30
+ const testName = `${testResults.name} ${viewport}`;
31
+ return testName + (testResults.error ? ` : ${testResults.error}` : '');
32
+ }
33
+ function testResultsSection(title, results) {
34
+ return results.length ? `${indent()}${title}${indent(3)}${results.join(indent(3))}` : '';
35
+ }
36
+ function stringifyError(testResults) {
37
+ return testResults.error ? stringifyTestResults(testResults) : `[Eyes test not started] : ${testResults}`;
38
+ }
39
+ function indent(spaces = 2) {
40
+ return `\n ${' '.repeat(spaces)}`;
41
+ }
42
+ function hasError(testResult) {
43
+ return testResult.error || testResult instanceof Error;
44
+ }
45
+ function errorDigest({ passed, failed, diffs, logger, isInteractive }) {
46
+ logger.log('errorDigest: diff errors', diffs);
47
+ logger.log('errorDigest: test errors', failed);
48
+ const testResultsUrl = diffs.length ? colorify(` ${diffs[0].url} `, 'teal') : '';
49
+ const testResultsPrefix = testResultsUrl ? 'See details at:' : '';
50
+ const footer = testResultsUrl ? `\n${indent()}${colorify(testResultsPrefix)}${testResultsUrl}` : '';
51
+ return (colorify('Eyes-Cypress detected diffs or errors during execution of visual tests.') +
52
+ colorify(` ${testResultsPrefix}${testResultsUrl}`) +
53
+ testResultsToString(passed, 'Passed') +
54
+ testResultsToString(diffs, 'Unresolved') +
55
+ testResultsToString(failed, 'Failed') +
56
+ footer +
57
+ '\n\n');
58
+ function testResultsToString(testResultsArr, category) {
59
+ const { color, title, symbol } = formatByStatus[category];
60
+ const results = testResultsArr.reduce((acc, testResults) => {
61
+ if (!testResults.isEmpty) {
62
+ const error = hasError(testResults) ? stringifyError(testResults) : undefined;
63
+ acc.push(`${colorify(symbol, color)} ${colorify(error || stringifyTestResults(testResults))}`);
64
+ }
65
+ return acc;
66
+ }, []);
67
+ const coloredTitle = results.length ? colorify(title(results.length), color) : '';
68
+ return testResultsSection(coloredTitle, results);
69
+ }
70
+ function colorify(msg, color = 'reset') {
71
+ return isInteractive ? msg : `${colors[color]}${msg}${colors.reset}`;
72
+ }
73
+ }
74
+ exports.default = errorDigest;
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ function getErrorsAndDiffs(testResultsArr) {
4
+ return testResultsArr.reduce(({ failed, diffs, passed }, testResults) => {
5
+ if (testResults instanceof Error || testResults.error) {
6
+ failed.push(testResults);
7
+ }
8
+ else {
9
+ const testStatus = testResults.status;
10
+ if (testStatus === 'Passed') {
11
+ passed.push(testResults);
12
+ }
13
+ else {
14
+ if (testStatus === 'Unresolved') {
15
+ if (testResults.isNew) {
16
+ testResults.error = new Error(`${testResults.name}. Please approve the new baseline at ${testResults.url}`);
17
+ failed.push(testResults);
18
+ }
19
+ else {
20
+ diffs.push(testResults);
21
+ }
22
+ }
23
+ else if (testStatus === 'Failed') {
24
+ failed.push(testResults);
25
+ }
26
+ }
27
+ }
28
+ return { failed, diffs, passed };
29
+ }, { failed: [], diffs: [], passed: [] });
30
+ }
31
+ exports.default = getErrorsAndDiffs;
@@ -0,0 +1,38 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const errorDigest_1 = __importDefault(require("./errorDigest"));
7
+ const logger_1 = require("@applitools/logger");
8
+ const getErrorsAndDiffs_1 = __importDefault(require("./getErrorsAndDiffs"));
9
+ const fs_1 = __importDefault(require("fs"));
10
+ const core_1 = require("@applitools/core");
11
+ const path_1 = require("path");
12
+ function printTestResults(testResultsArr) {
13
+ const logger = (0, logger_1.makeLogger)({
14
+ level: testResultsArr.resultConfig.showLogs ? 'info' : 'silent',
15
+ label: 'eyes',
16
+ });
17
+ if (!testResultsArr.testResults)
18
+ return;
19
+ const { passed, failed, diffs } = (0, getErrorsAndDiffs_1.default)(testResultsArr.testResults);
20
+ if ((failed.length || diffs.length) && !!testResultsArr.resultConfig.eyesFailCypressOnDiff) {
21
+ throw new Error((0, errorDigest_1.default)({
22
+ passed,
23
+ failed,
24
+ diffs,
25
+ logger,
26
+ isInteractive: !testResultsArr.resultConfig.isTextTerminal,
27
+ }));
28
+ }
29
+ }
30
+ function handleBatchResultsFile(results, tapFileConfig) {
31
+ const fileName = tapFileConfig.tapFileName || `${new Date().toISOString()}-eyes.tap`;
32
+ const tapFile = (0, path_1.resolve)(tapFileConfig.tapDirPath, fileName);
33
+ return fs_1.default.writeFile(tapFile, core_1.formatters.toHierarchicTAPString(results, { includeSubTests: false, markNewAsPassed: true }), {}, (err) => {
34
+ if (err)
35
+ throw err;
36
+ });
37
+ }
38
+ exports.default = { printTestResults, handleBatchResultsFile };
@@ -0,0 +1,43 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const handleTestResults_1 = __importDefault(require("./handleTestResults"));
7
+ function makeGlobalRunHooks({ closeManager, closeBatches, closeUniversalServer }) {
8
+ return {
9
+ 'before:run': ({ config }) => {
10
+ if (!config.isTextTerminal)
11
+ return;
12
+ },
13
+ 'after:run': async ({ config }) => {
14
+ try {
15
+ if (!config.isTextTerminal)
16
+ return;
17
+ const summaries = await closeManager();
18
+ let testResults;
19
+ for (const summary of summaries) {
20
+ testResults = summary.results.map(({ testResults }) => testResults);
21
+ }
22
+ if (!config.appliConfFile.dontCloseBatches) {
23
+ await closeBatches({
24
+ batchIds: [config.appliConfFile.batchId || config.appliConfFile.batch.id],
25
+ serverUrl: config.appliConfFile.serverUrl,
26
+ proxy: config.appliConfFile.proxy,
27
+ apiKey: config.appliConfFile.apiKey,
28
+ });
29
+ }
30
+ if (config.appliConfFile.tapDirPath) {
31
+ await handleTestResults_1.default.handleBatchResultsFile(testResults, {
32
+ tapDirPath: config.appliConfFile.tapDirPath,
33
+ tapFileName: config.appliConfFile.tapFileName,
34
+ });
35
+ }
36
+ }
37
+ finally {
38
+ await closeUniversalServer();
39
+ }
40
+ },
41
+ };
42
+ }
43
+ exports.default = makeGlobalRunHooks;
@@ -0,0 +1,17 @@
1
+ 'use strict';
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const pluginExport_1 = __importDefault(require("./pluginExport"));
7
+ const config_1 = __importDefault(require("./config"));
8
+ const server_1 = __importDefault(require("./server"));
9
+ const logger_1 = require("@applitools/logger");
10
+ const { config, eyesConfig } = (0, config_1.default)();
11
+ const logger = (0, logger_1.makeLogger)({ level: config.showLogs ? 'info' : 'silent', label: 'eyes' });
12
+ const startServer = (0, server_1.default)({ logger });
13
+ const pluginExport = (0, pluginExport_1.default)({
14
+ startServer,
15
+ eyesConfig: Object.assign({}, eyesConfig, { appliConfFile: config }),
16
+ });
17
+ exports.default = pluginExport;
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const CYPRESS_SUPPORTED_VERSION = '6.2.0';
4
+ const CYPRESS_NO_FLAG_VERSION = '6.7.0';
5
+ function isGlobalHooksSupported(config) {
6
+ const { version, experimentalRunEvents } = config;
7
+ return (parseFloat(version) >= parseFloat(CYPRESS_NO_FLAG_VERSION) ||
8
+ (parseFloat(version) >= parseFloat(CYPRESS_SUPPORTED_VERSION) && !!experimentalRunEvents));
9
+ }
10
+ exports.default = isGlobalHooksSupported;
@@ -0,0 +1,104 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const isGlobalHooksSupported_1 = __importDefault(require("./isGlobalHooksSupported"));
7
+ const functional_commons_1 = require("@applitools/functional-commons");
8
+ const hooks_1 = __importDefault(require("./hooks"));
9
+ function makePluginExport({ startServer, eyesConfig }) {
10
+ return function pluginExport(pluginInitArgs) {
11
+ let eyesServer, pluginModuleExports, pluginExportsE2E, pluginExportsComponent;
12
+ let pluginExports;
13
+ if (pluginInitArgs.exports) {
14
+ const pluginAsNodeJSModule = pluginInitArgs;
15
+ pluginExports =
16
+ pluginAsNodeJSModule.exports && pluginAsNodeJSModule.exports.default
17
+ ? pluginAsNodeJSModule.exports.default
18
+ : pluginAsNodeJSModule.exports;
19
+ if (pluginExports.component) {
20
+ pluginExportsComponent = pluginExports.component.setupNodeEvents;
21
+ }
22
+ if (pluginExports.e2e) {
23
+ pluginExportsE2E = pluginExports.e2e.setupNodeEvents;
24
+ }
25
+ if (!pluginExports.e2e && !pluginExports.component) {
26
+ pluginModuleExports = pluginExports;
27
+ }
28
+ if (pluginExports === null || pluginExports === void 0 ? void 0 : pluginExports.component) {
29
+ pluginExports.component.setupNodeEvents = setupNodeEvents;
30
+ }
31
+ if (pluginExports === null || pluginExports === void 0 ? void 0 : pluginExports.e2e) {
32
+ pluginExports.e2e.setupNodeEvents = setupNodeEvents;
33
+ }
34
+ if (!pluginExports.component && !pluginExports.e2e) {
35
+ if (pluginAsNodeJSModule.exports.default) {
36
+ pluginAsNodeJSModule.exports.default = setupNodeEvents;
37
+ }
38
+ else {
39
+ pluginAsNodeJSModule.exports = setupNodeEvents;
40
+ }
41
+ }
42
+ }
43
+ else {
44
+ const pluginAsCypress10PluginOptions = pluginInitArgs;
45
+ if (pluginAsCypress10PluginOptions.component) {
46
+ pluginExportsComponent = pluginAsCypress10PluginOptions.component.setupNodeEvents;
47
+ pluginAsCypress10PluginOptions.component.setupNodeEvents = setupNodeEvents;
48
+ }
49
+ if (pluginAsCypress10PluginOptions.e2e) {
50
+ pluginExportsE2E = pluginAsCypress10PluginOptions.e2e.setupNodeEvents;
51
+ pluginAsCypress10PluginOptions.e2e.setupNodeEvents = setupNodeEvents;
52
+ }
53
+ }
54
+ if (!pluginInitArgs.exports) {
55
+ return pluginInitArgs;
56
+ }
57
+ return function getCloseServer() {
58
+ return eyesServer.close();
59
+ };
60
+ async function setupNodeEvents(origOn, cypressConfig) {
61
+ const { server, port, closeManager, closeBatches, closeUniversalServer } = await startServer();
62
+ eyesServer = server;
63
+ const globalHooks = (0, hooks_1.default)({
64
+ closeManager,
65
+ closeBatches,
66
+ closeUniversalServer,
67
+ });
68
+ if (!pluginModuleExports) {
69
+ pluginModuleExports = cypressConfig.testingType === 'e2e' ? pluginExportsE2E : pluginExportsComponent;
70
+ }
71
+ const isGlobalHookCalledFromUserHandlerMap = new Map();
72
+ eyesConfig.eyesIsGlobalHooksSupported = (0, isGlobalHooksSupported_1.default)(cypressConfig);
73
+ let moduleExportsResult = {};
74
+ if (typeof pluginModuleExports === 'function') {
75
+ moduleExportsResult = await pluginModuleExports(onThatCallsUserDefinedHandler, cypressConfig);
76
+ }
77
+ if (eyesConfig.eyesIsGlobalHooksSupported) {
78
+ for (const [eventName, eventHandler] of Object.entries(globalHooks)) {
79
+ if (!isGlobalHookCalledFromUserHandlerMap.get(eventName)) {
80
+ origOn.call(this, eventName, eventHandler);
81
+ }
82
+ }
83
+ }
84
+ return Object.assign({}, eyesConfig, { eyesPort: port }, moduleExportsResult);
85
+ function onThatCallsUserDefinedHandler(eventName, handler) {
86
+ const isRunEvent = eventName === 'before:run' || eventName === 'after:run';
87
+ let handlerToCall = handler;
88
+ if (eyesConfig.eyesIsGlobalHooksSupported && isRunEvent) {
89
+ handlerToCall = handlerThatCallsUserDefinedHandler;
90
+ isGlobalHookCalledFromUserHandlerMap.set(eventName, true);
91
+ }
92
+ return origOn.call(this, eventName, handlerToCall);
93
+ async function handlerThatCallsUserDefinedHandler(...args) {
94
+ const [err] = await (0, functional_commons_1.presult)(Promise.resolve(globalHooks[eventName].apply(this, args)));
95
+ await handler.apply(this, args);
96
+ if (err) {
97
+ throw err;
98
+ }
99
+ }
100
+ }
101
+ }
102
+ };
103
+ }
104
+ exports.default = makePluginExport;
@@ -0,0 +1,117 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const webSocket_1 = __importDefault(require("./webSocket"));
7
+ const eyes_universal_1 = require("@applitools/eyes-universal");
8
+ const handleTestResults_1 = __importDefault(require("./handleTestResults"));
9
+ const path_1 = __importDefault(require("path"));
10
+ const fs_1 = __importDefault(require("fs"));
11
+ const semver_1 = require("semver");
12
+ const https_1 = require("https");
13
+ const ws_1 = require("ws");
14
+ const which_1 = __importDefault(require("which"));
15
+ const util_1 = require("util");
16
+ function makeStartServer({ logger }) {
17
+ return async function startServer() {
18
+ const key = fs_1.default.readFileSync(path_1.default.resolve(__dirname, '../../src/pem/server.key'));
19
+ const cert = fs_1.default.readFileSync(path_1.default.resolve(__dirname, '../../src/pem/server.cert'));
20
+ const https = new https_1.Server({
21
+ key,
22
+ cert,
23
+ });
24
+ await (0, util_1.promisify)(https.listen.bind(https))();
25
+ const port = https.address().port;
26
+ const wss = new ws_1.Server({ server: https, path: '/eyes', maxPayload: 254 * 1024 * 1024 });
27
+ wss.on('close', () => https.close());
28
+ const forkOptions = {
29
+ detached: true,
30
+ };
31
+ const cypressVersion = require('cypress/package.json').version;
32
+ if ((0, semver_1.lt)(cypressVersion, '7.0.0')) {
33
+ forkOptions.execPath = await (0, which_1.default)('node');
34
+ }
35
+ const { port: universalPort, close: closeUniversalServer } = await (0, eyes_universal_1.makeServerProcess)({
36
+ idleTimeout: 0,
37
+ shutdownMode: 'stdin',
38
+ forkOptions,
39
+ singleton: false,
40
+ portResolutionMode: 'random',
41
+ });
42
+ const managers = [];
43
+ let socketWithUniversal;
44
+ wss.on('connection', socketWithClient => {
45
+ socketWithUniversal = (0, webSocket_1.default)(`ws://localhost:${universalPort}/eyes`);
46
+ socketWithUniversal.setPassthroughListener((message) => {
47
+ logger.log('<== ', message.toString().slice(0, 1000));
48
+ const { name, payload } = JSON.parse(message);
49
+ if (name === 'Core.makeManager') {
50
+ managers.push({ manager: payload.result, socketWithUniversal });
51
+ }
52
+ socketWithClient.send(message.toString());
53
+ });
54
+ socketWithClient.on('message', (message) => {
55
+ const msg = JSON.parse(message);
56
+ logger.log('==> ', message.toString().slice(0, 1000));
57
+ if (msg.name === 'Core.makeSDK') {
58
+ const newMessage = Buffer.from(JSON.stringify({
59
+ name: msg.name,
60
+ key: msg.key,
61
+ payload: Object.assign(msg.payload, { cwd: process.cwd() }),
62
+ }), 'utf-8');
63
+ socketWithUniversal.send(newMessage);
64
+ }
65
+ else if (msg.name === 'Test.printTestResults') {
66
+ try {
67
+ if (msg.payload.resultConfig.tapDirPath && msg.payload.resultConfig.shouldCreateTapFile) {
68
+ handleTestResults_1.default.handleBatchResultsFile(msg.payload.testResults, {
69
+ tapFileName: msg.payload.resultConfig.tapFileName,
70
+ tapDirPath: msg.payload.resultConfig.tapDirPath,
71
+ });
72
+ }
73
+ handleTestResults_1.default.printTestResults({
74
+ testResults: msg.payload.testResults,
75
+ resultConfig: msg.payload.resultConfig,
76
+ });
77
+ socketWithClient.send(JSON.stringify({
78
+ name: 'Test.printTestResults',
79
+ key: msg.key,
80
+ payload: { result: 'success' },
81
+ }));
82
+ }
83
+ catch (ex) {
84
+ socketWithClient.send(JSON.stringify({
85
+ name: 'Test.printTestResults',
86
+ key: msg.key,
87
+ payload: { result: ex.message.toString() },
88
+ }));
89
+ }
90
+ }
91
+ else {
92
+ socketWithUniversal.send(message);
93
+ }
94
+ });
95
+ });
96
+ return {
97
+ server: wss,
98
+ port,
99
+ closeManager,
100
+ closeBatches,
101
+ closeUniversalServer,
102
+ };
103
+ function closeManager() {
104
+ return Promise.all(managers.map(({ manager, socketWithUniversal }) => socketWithUniversal.request('EyesManager.closeManager', {
105
+ manager,
106
+ throwErr: false,
107
+ })));
108
+ }
109
+ function closeBatches(settings) {
110
+ if (socketWithUniversal)
111
+ return socketWithUniversal.request('Core.closeBatches', { settings }).catch((err) => {
112
+ logger.log('@@@', err);
113
+ });
114
+ }
115
+ };
116
+ }
117
+ exports.default = makeStartServer;