@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
@@ -0,0 +1,129 @@
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 ws_1 = __importDefault(require("ws"));
7
+ const uuid_1 = require("uuid");
8
+ function connectSocket(url) {
9
+ const socket = new ws_1.default(url);
10
+ let passthroughListener;
11
+ const listeners = new Map();
12
+ const queue = new Set();
13
+ let isReady = false;
14
+ attach();
15
+ function attach() {
16
+ if (socket.readyState === ws_1.default.CONNECTING)
17
+ socket.on('open', () => attach());
18
+ else if (socket.readyState === ws_1.default.OPEN) {
19
+ isReady = true;
20
+ queue.forEach((command) => command());
21
+ queue.clear();
22
+ socket.on('message', message => {
23
+ const { name, key, payload } = deserialize(message);
24
+ const fns = listeners.get(name);
25
+ const keyListeners = key && listeners.get(`${name}/${key}`);
26
+ if (fns)
27
+ fns.forEach(fn => fn(payload, key));
28
+ if (keyListeners)
29
+ keyListeners.forEach(fn => fn(payload, key));
30
+ if (!fns && !keyListeners && passthroughListener) {
31
+ passthroughListener(message);
32
+ }
33
+ });
34
+ }
35
+ }
36
+ function disconnect() {
37
+ if (!socket)
38
+ return;
39
+ socket.terminate();
40
+ isReady = false;
41
+ passthroughListener = null;
42
+ queue.clear();
43
+ }
44
+ function setPassthroughListener(fn) {
45
+ passthroughListener = fn;
46
+ }
47
+ function send(message) {
48
+ const command = () => socket.send(message);
49
+ if (isReady)
50
+ command();
51
+ else
52
+ queue.add(command);
53
+ return () => queue.delete(command);
54
+ }
55
+ function on(type, fn) {
56
+ const name = typeof type === 'string' ? type : `${type.name}/${type.key}`;
57
+ let fns = listeners.get(name);
58
+ if (!fns) {
59
+ fns = new Set();
60
+ listeners.set(name, fns);
61
+ }
62
+ fns.add(fn);
63
+ return () => off(name, fn);
64
+ }
65
+ function once(type, fn) {
66
+ const off = on(type, (...args) => (fn(...args), off()));
67
+ return off;
68
+ }
69
+ function off(name, fn) {
70
+ if (!fn)
71
+ return listeners.delete(name);
72
+ const fns = listeners.get(name);
73
+ if (!fns)
74
+ return false;
75
+ const existed = fns.delete(fn);
76
+ if (!fns.size)
77
+ listeners.delete(name);
78
+ return existed;
79
+ }
80
+ function emit(type, payload) {
81
+ return send(serialize(type, payload));
82
+ }
83
+ function request(name, payload) {
84
+ return new Promise((resolve, reject) => {
85
+ const key = (0, uuid_1.v4)();
86
+ emit({ name, key }, payload);
87
+ once({ name, key }, (response) => {
88
+ if (response.error)
89
+ return reject(response.error);
90
+ return resolve(response.result);
91
+ });
92
+ });
93
+ }
94
+ function ref() {
95
+ const command = () => socket._socket.ref();
96
+ if (isReady)
97
+ command();
98
+ else
99
+ queue.add(command);
100
+ return () => queue.delete(command);
101
+ }
102
+ function unref() {
103
+ const command = () => socket._socket.unref();
104
+ if (isReady)
105
+ command();
106
+ else
107
+ queue.add(command);
108
+ return () => queue.delete(command);
109
+ }
110
+ return {
111
+ setPassthroughListener,
112
+ send,
113
+ on,
114
+ once,
115
+ off,
116
+ request,
117
+ disconnect,
118
+ ref,
119
+ unref,
120
+ };
121
+ }
122
+ exports.default = connectSocket;
123
+ function serialize(type, payload) {
124
+ const message = typeof type === 'string' ? { name: type, payload } : { name: type.name, key: type.key, payload };
125
+ return JSON.stringify(message);
126
+ }
127
+ function deserialize(message) {
128
+ return JSON.parse(message);
129
+ }
package/index.js CHANGED
@@ -1,2 +1,3 @@
1
- 'use strict'
2
- module.exports = require('./src/plugin/startPlugin')
1
+ const expose = require('./dist/expose')
2
+ module.exports = expose.default
3
+ Object.defineProperty(module.exports, 'default', {value: expose.default})
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@applitools/eyes-cypress",
3
- "version": "3.28.3",
3
+ "version": "3.29.0",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git://github.com/applitools/eyes.sdk.javascript1.git",
@@ -11,8 +11,8 @@
11
11
  "cypress",
12
12
  "cy"
13
13
  ],
14
- "main": "index.js",
15
- "types": "./index.d.ts",
14
+ "main": "./index.js",
15
+ "types": "./types/index.d.ts",
16
16
  "bin": {
17
17
  "eyes-setup": "./bin/eyes-setup.js"
18
18
  },
@@ -25,8 +25,8 @@
25
25
  "index.d.ts"
26
26
  ],
27
27
  "scripts": {
28
- "lint": "eslint \"**/*.js\"",
29
- "build": "tsc",
28
+ "lint": "eslint \"**/*.{js,ts}\"",
29
+ "build": "ttsc",
30
30
  "generate:tests": "coverage-tests generate",
31
31
  "test": "yarn test:unit && yarn test:it && yarn test:e2e && yarn test:ts && yarn test:components && yarn test:coverage",
32
32
  "test:sanity": "yarn test:unit && yarn test:it && yarn test:ts",
@@ -34,7 +34,16 @@
34
34
  "test:it": "yarn build && mocha --no-timeouts 'test/it/**/*.test.js'",
35
35
  "test:ts": "yarn test:ts:compile && yarn test:ts:run",
36
36
  "test:ts:compile": "tsc --project test/e2e/ts/cypress",
37
- "test:ts:run": "cypress run --config-file test/e2e/ts/cypress-ts.json",
37
+ "test:ts:run:legacy": "yarn cypress9 run --config-file ./test/e2e/ts/cypress-ts-legacy.json",
38
+ "cypress9": "./node_modules/cypress9/bin/cypress",
39
+ "test:ts:run:9": "yarn cypress9 run --project ./test/e2e/ts --config-file ./cypress-9.config.ts",
40
+ "cypress10": "./node_modules/cypress10/bin/cypress",
41
+ "test:ts:run:10": "yarn cypress10 run --project ./test/e2e/ts --config-file ./cypress-10.config.ts",
42
+ "cypress11": "./node_modules/cypress11/bin/cypress",
43
+ "test:ts:run:11": "yarn cypress11 run --project ./test/e2e/ts --config-file ./cypress-11.config.ts",
44
+ "cypress12": "./node_modules/cypress12/bin/cypress",
45
+ "test:ts:run:12": "yarn cypress12 run --project ./test/e2e/ts --config-file ./cypress-12.config.ts",
46
+ "test:ts:run": "yarn test:ts:run:legacy && yarn test:ts:run:9",
38
47
  "test:coverage": "yarn generate:tests && cd test/coverage/generic && yarn && unset APPLITOOLS_API_KEY && APPLITOOLS_BATCH_NAME='JS Coverage Tests: eyes-cypress' APPLITOOLS_BATCH_ID=$(uuidgen) npx cypress run",
39
48
  "test:e2e": "mkdir -p test/fixtures/testAppCopies && mocha --no-timeouts 'test/e2e/**/*.test.js'",
40
49
  "test:components": "cd test/components && yarn && npx cypress run --component",
@@ -56,11 +65,13 @@
56
65
  }
57
66
  },
58
67
  "dependencies": {
59
- "@applitools/core": "1.4.2",
60
- "@applitools/eyes-api": "1.12.2",
68
+ "@applitools/core": "1.4.6",
69
+ "@applitools/eyes-api": "1.13.1",
61
70
  "@applitools/eyes-universal": "2.18.0",
62
71
  "@applitools/functional-commons": "1.6.0",
63
- "@applitools/logger": "1.1.40",
72
+ "@applitools/logger": "1.1.43",
73
+ "@applitools/utils": "1.3.28",
74
+ "boxen": "5.1.2",
64
75
  "chalk": "3.0.0",
65
76
  "semver": "7.3.8",
66
77
  "uuid": "8.3.2",
@@ -68,26 +79,32 @@
68
79
  "ws": "8.5.0"
69
80
  },
70
81
  "devDependencies": {
82
+ "@applitools/api-extractor": "^1.2.11",
71
83
  "@applitools/bongo": "^2.2.2",
72
84
  "@applitools/scripts": "1.2.0",
73
- "@applitools/sdk-coverage-tests": "^2.7.10",
85
+ "@applitools/sdk-coverage-tests": "^2.7.8",
74
86
  "@applitools/snaptdout": "1.0.1",
75
- "@applitools/test-server": "1.1.21",
76
- "@applitools/test-utils": "1.5.8",
77
- "@applitools/utils": "1.3.26",
87
+ "@applitools/test-server": "1.1.22",
88
+ "@applitools/test-utils": "1.5.11",
78
89
  "@types/node": "12",
90
+ "@types/semver": "^7.3.13",
91
+ "@types/uuid": "^9.0.0",
79
92
  "@types/which": "^2.0.1",
80
93
  "@types/ws": "^8.2.2",
81
- "@typescript-eslint/eslint-plugin": "^5.10.2",
82
- "@typescript-eslint/parser": "^5.10.2",
94
+ "@typescript-eslint/eslint-plugin": "^5.47.1",
95
+ "@typescript-eslint/parser": "^5.47.1",
83
96
  "chai": "4.2.0",
84
97
  "chai-spies": "1.0.0",
85
98
  "cookie-parser": "1.4.4",
86
99
  "cypress": "9.7.0",
100
+ "cypress10": "npm:cypress@^10.0.0",
101
+ "cypress11": "npm:cypress@^11.0.0",
102
+ "cypress12": "npm:cypress@^12.0.0",
103
+ "cypress9": "npm:cypress@^9.0.0",
87
104
  "eslint": "8.10.0",
88
105
  "eslint-config-prettier": "^8.5.0",
89
106
  "eslint-plugin-mocha-no-only": "1.1.0",
90
- "eslint-plugin-no-only-tests": "^3.0.0",
107
+ "eslint-plugin-no-only-tests": "^3.1.0",
91
108
  "eslint-plugin-node": "^11.1.0",
92
109
  "eslint-plugin-prettier": "^4.0.0",
93
110
  "husky": "4.3.8",
@@ -97,9 +114,11 @@
97
114
  "ncp": "2.0.0",
98
115
  "node-fetch": "2.6.0",
99
116
  "prettier": "^2.6.2",
100
- "typescript": "4.8.4"
117
+ "ttypescript": "^1.5.13",
118
+ "typescript": "^4.7.2"
101
119
  },
102
120
  "engines": {
103
121
  "node": ">=12.13.0"
104
- }
122
+ },
123
+ "xvfb": true
105
124
  }
@@ -37,7 +37,7 @@ export function childContext(_context: Context, element: HTMLIFrameElement): Con
37
37
  }
38
38
  }
39
39
 
40
- export function getViewportSize(): Object {
40
+ export function getViewportSize(): {width: number; height: number} {
41
41
  //@ts-ignore
42
42
  const currWindow = cy.state('window')
43
43
  const viewportSize = {
package/src/expose.ts ADDED
@@ -0,0 +1,71 @@
1
+ /*
2
+ * The types here are compiled via `ttsc` and `api-extractor`, and are used to describe the inputs to
3
+ * Eyes-Cypress custom commands. The reason they are not written in the `index.d.ts` file next to the
4
+ * `declare global { namespace Cypress {...}}` statement is that `api-extractor` has a limitation (at
5
+ * the time of writing this) that drops the `declare global` statement. So it's important to not pass
6
+ * `index.d.ts` through `api-extractor`,but keep the types in this file go through it, to produce the
7
+ * correct types for the SDK just like all other conventional SDK's.
8
+ **/
9
+ /// <reference types="cypress" />
10
+ import type * as api from '@applitools/eyes-api'
11
+ import {type EyesSelector, type TestResultsStatus} from '@applitools/eyes-api'
12
+
13
+ export type {EyesSelector, TestResultsStatus}
14
+
15
+ type MaybeArray<T> = T | T[]
16
+
17
+ type LegacyRegion = {left: number; top: number; width: number; height: number}
18
+ type Selector = {selector: string; type?: 'css' | 'xpath'; nodeType?: 'element' | 'shadow-root'} | 'string'
19
+ type Element = HTMLElement | JQuery<HTMLElement>
20
+ type ElementWithOptions = {element: Element; regionId?: string; padding?: any}
21
+
22
+ export type CypressCheckSettings = api.CheckSettingsAutomationPlain<Element, Selector> & {
23
+ tag?: CypressCheckSettings['name']
24
+
25
+ target?: 'window' | 'region'
26
+ selector?: Selector
27
+ element?: Element
28
+
29
+ ignore?: MaybeArray<NonNullable<CypressCheckSettings['ignoreRegions']>[number] | LegacyRegion | ElementWithOptions>
30
+ layout?: MaybeArray<NonNullable<CypressCheckSettings['layoutRegions']>[number] | LegacyRegion | ElementWithOptions>
31
+ content?: MaybeArray<NonNullable<CypressCheckSettings['contentRegions']>[number] | LegacyRegion | ElementWithOptions>
32
+ strict?: MaybeArray<NonNullable<CypressCheckSettings['strictRegions']>[number] | LegacyRegion | ElementWithOptions>
33
+ floating?: MaybeArray<
34
+ | NonNullable<CypressCheckSettings['floatingRegions']>[number]
35
+ | ((ElementWithOptions | Selector | LegacyRegion) & {
36
+ maxUpOffset?: number
37
+ maxDownOffset?: number
38
+ maxLeftOffset?: number
39
+ maxRightOffset?: number
40
+ })
41
+ >
42
+ accessibility?: MaybeArray<
43
+ | NonNullable<CypressCheckSettings['accessibilityRegions']>[number]
44
+ | ((ElementWithOptions | Selector | LegacyRegion) & {accessibilityType?: api.AccessibilityRegionTypePlain})
45
+ >
46
+ scriptHooks?: CypressCheckSettings['hooks']
47
+ ignoreCaret?: boolean
48
+ ignoreDisplacements?: boolean
49
+ }
50
+ export type CypressEyesConfig = api.ConfigurationPlain<Element, Selector> & {
51
+ browser?: MaybeArray<
52
+ | NonNullable<CypressEyesConfig['browsersInfo']>[number]
53
+ | {deviceName: string; screenOrientation?: api.ScreenOrientationPlain; name?: string}
54
+ >
55
+
56
+ batchId?: NonNullable<CypressEyesConfig['batch']>['id']
57
+ batchName?: NonNullable<CypressEyesConfig['batch']>['name']
58
+ batchSequence?: NonNullable<CypressEyesConfig['batch']>['sequenceName']
59
+ notifyOnCompletion?: NonNullable<CypressEyesConfig['batch']>['notifyOnCompletion']
60
+
61
+ envName?: CypressEyesConfig['environmentName']
62
+
63
+ accessibilitySettings?: NonNullable<CypressEyesConfig['defaultMatchSettings']>['accessibilitySettings']
64
+ }
65
+
66
+ export type CypressTestResultsSummary = api.TestResultsSummary
67
+
68
+ export {type EyesPluginConfig} from './plugin'
69
+
70
+ import plugin from './plugin'
71
+ export default plugin
@@ -5,4 +5,4 @@ Important notice: Your Applitools visual tests are currently running with a test
5
5
  This means that only up to 5 visual tests can run in parallel, and therefore the execution might be slower.
6
6
  If your Applitools license supports a higher concurrency level, learn how to configure it here: https://www.npmjs.com/package/@applitools/eyes-cypress#concurrency.
7
7
  Need a higher concurrency in your account? Email us @ sdr@applitools.com with your required concurrency level.`
8
- module.exports = {concurrencyMsg: chalk.yellow(MSG), msgText: MSG}
8
+ export default {concurrencyMsg: chalk.yellow(MSG), msgText: MSG}
@@ -1,19 +1,12 @@
1
- 'use strict'
2
- const utils = require('@applitools/utils')
3
- const {configParams} = require('./configParams')
1
+ import * as utils from '@applitools/utils'
2
+ import configParams from './configParams'
4
3
  const DEFAULT_TEST_CONCURRENCY = 5
5
- const uuid = require('uuid')
4
+ import * as uuid from 'uuid'
5
+ import {type EyesPluginConfig} from './'
6
6
 
7
- function makeConfig() {
7
+ export default function makeConfig(): {config: any; eyesConfig: EyesPluginConfig} {
8
8
  const config = utils.config.getConfig({
9
- params: [
10
- ...configParams,
11
- 'failCypressOnDiff',
12
- 'tapDirPath',
13
- 'tapFileName',
14
- 'disableBrowserFetching',
15
- 'testConcurrency',
16
- ],
9
+ params: [...configParams, 'failCypressOnDiff', 'tapDirPath', 'tapFileName', 'disableBrowserFetching', 'testConcurrency'],
17
10
  })
18
11
 
19
12
  if ((!config.batch || !config.batch.id) && !config.batchId) {
@@ -51,5 +44,3 @@ function makeConfig() {
51
44
 
52
45
  return {config, eyesConfig}
53
46
  }
54
-
55
- module.exports = makeConfig
@@ -1,5 +1,3 @@
1
- 'use strict'
2
-
3
1
  const configParams = [
4
2
  'appName',
5
3
  'testName',
@@ -45,4 +43,4 @@ const configParams = [
45
43
  'dontCloseBatches',
46
44
  ]
47
45
 
48
- module.exports = {configParams}
46
+ export default configParams
@@ -1,5 +1,4 @@
1
- 'use strict'
2
-
1
+ type Color = 'reset' | 'green' | 'red' | 'teal' | 'orange'
3
2
  const colors = {
4
3
  green: '\x1b[32m',
5
4
  red: '\x1b[31m',
@@ -7,26 +6,48 @@ const colors = {
7
6
  orange: '\x1b[38;5;214m',
8
7
  reset: '\x1b[0m',
9
8
  }
10
-
11
- const formatByStatus = {
9
+ const formatByStatus: Record<string, {color: Color; symbol: string; title: (tests: number) => string}> = {
12
10
  Passed: {
13
11
  color: 'green',
14
12
  symbol: '\u2713',
15
- title: tests => `Passed - ${tests} tests`,
13
+ title: (tests: number) => `Passed - ${tests} tests`,
16
14
  },
17
15
  Failed: {
18
16
  color: 'red',
19
17
  symbol: '\u2716',
20
- title: tests => `Errors - ${tests} tests`,
18
+ title: (tests: number) => `Errors - ${tests} tests`,
21
19
  },
22
20
  Unresolved: {
23
21
  color: 'orange',
24
22
  symbol: '\u26A0',
25
- title: tests => `Diffs detected - ${tests} tests`,
23
+ title: (tests: number) => `Diffs detected - ${tests} tests`,
26
24
  },
27
25
  }
28
26
 
29
- function errorDigest({passed, failed, diffs, logger, isInteractive}) {
27
+ function stringifyTestResults(testResults: any) {
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
+
34
+ function testResultsSection(title: string, results: any) {
35
+ return results.length ? `${indent()}${title}${indent(3)}${results.join(indent(3))}` : ''
36
+ }
37
+
38
+ function stringifyError(testResults: any) {
39
+ return testResults.error ? stringifyTestResults(testResults) : `[Eyes test not started] : ${testResults}`
40
+ }
41
+
42
+ function indent(spaces = 2) {
43
+ return `\n ${' '.repeat(spaces)}`
44
+ }
45
+
46
+ function hasError(testResult: any) {
47
+ return testResult.error || testResult instanceof Error
48
+ }
49
+
50
+ export default function errorDigest({passed, failed, diffs, logger, isInteractive}: any) {
30
51
  logger.log('errorDigest: diff errors', diffs)
31
52
  logger.log('errorDigest: test errors', failed)
32
53
 
@@ -43,9 +64,9 @@ function errorDigest({passed, failed, diffs, logger, isInteractive}) {
43
64
  '\n\n'
44
65
  )
45
66
 
46
- function testResultsToString(testResultsArr, category) {
47
- const {color, title, symbol, chalkFunction} = formatByStatus[category]
48
- const results = testResultsArr.reduce((acc, testResults) => {
67
+ function testResultsToString(testResultsArr: any, category: 'Passed' | 'Failed' | 'Unresolved') {
68
+ const {color, title, symbol} = formatByStatus[category]
69
+ const results = testResultsArr.reduce((acc: any, testResults: any) => {
49
70
  if (!testResults.isEmpty) {
50
71
  const error = hasError(testResults) ? stringifyError(testResults) : undefined
51
72
  acc.push(`${colorify(symbol, color)} ${colorify(error || stringifyTestResults(testResults))}`)
@@ -53,36 +74,11 @@ function errorDigest({passed, failed, diffs, logger, isInteractive}) {
53
74
  return acc
54
75
  }, [])
55
76
 
56
- const coloredTitle = results.length ? colorify(title(results.length), color, chalkFunction) : ''
77
+ const coloredTitle = results.length ? colorify(title(results.length), color) : ''
57
78
  return testResultsSection(coloredTitle, results)
58
79
  }
59
80
 
60
- function colorify(msg, color = 'reset') {
81
+ function colorify(msg: any, color: Color = 'reset') {
61
82
  return isInteractive ? msg : `${colors[color]}${msg}${colors.reset}`
62
83
  }
63
84
  }
64
-
65
- function stringifyTestResults(testResults) {
66
- const hostDisplaySize = testResults.hostDisplaySize
67
- const viewport = hostDisplaySize ? `[${hostDisplaySize.width}x${hostDisplaySize.height}]` : ''
68
- const testName = `${testResults.name} ${viewport}`
69
- return testName + (testResults.error ? ` : ${testResults.error}` : '')
70
- }
71
-
72
- function testResultsSection(title, results) {
73
- return results.length ? `${indent()}${title}${indent(3)}${results.join(indent(3))}` : ''
74
- }
75
-
76
- function stringifyError(testResults) {
77
- return testResults.error ? stringifyTestResults(testResults) : `[Eyes test not started] : ${testResults}`
78
- }
79
-
80
- function indent(spaces = 2) {
81
- return `\n ${' '.repeat(spaces)}`
82
- }
83
-
84
- function hasError(testResult) {
85
- return testResult.error || testResult instanceof Error
86
- }
87
-
88
- module.exports = errorDigest
@@ -1,7 +1,6 @@
1
- 'use strict'
2
- function getErrorsAndDiffs(testResultsArr) {
1
+ export default function getErrorsAndDiffs(testResultsArr: any) {
3
2
  return testResultsArr.reduce(
4
- ({failed, diffs, passed}, testResults) => {
3
+ ({failed, diffs, passed}: any, testResults: any) => {
5
4
  if (testResults instanceof Error || testResults.error) {
6
5
  failed.push(testResults)
7
6
  } else {
@@ -11,9 +10,7 @@ function getErrorsAndDiffs(testResultsArr) {
11
10
  } else {
12
11
  if (testStatus === 'Unresolved') {
13
12
  if (testResults.isNew) {
14
- testResults.error = new Error(
15
- `${testResults.name}. Please approve the new baseline at ${testResults.url}`,
16
- )
13
+ testResults.error = new Error(`${testResults.name}. Please approve the new baseline at ${testResults.url}`)
17
14
  failed.push(testResults)
18
15
  } else {
19
16
  diffs.push(testResults)
@@ -29,5 +26,3 @@ function getErrorsAndDiffs(testResultsArr) {
29
26
  {failed: [], diffs: [], passed: []},
30
27
  )
31
28
  }
32
-
33
- module.exports = getErrorsAndDiffs
@@ -1,13 +1,11 @@
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 {formatters} = require('@applitools/core')
8
- const {resolve} = require('path')
1
+ import errorDigest from './errorDigest'
2
+ import {makeLogger} from '@applitools/logger'
3
+ import getErrorsAndDiffs from './getErrorsAndDiffs'
4
+ import fs from 'fs'
5
+ import {formatters} from '@applitools/core'
6
+ import {resolve} from 'path'
9
7
 
10
- function printTestResults(testResultsArr) {
8
+ function printTestResults(testResultsArr: any) {
11
9
  const logger = makeLogger({
12
10
  level: testResultsArr.resultConfig.showLogs ? 'info' : 'silent',
13
11
  label: 'eyes',
@@ -26,10 +24,17 @@ function printTestResults(testResultsArr) {
26
24
  )
27
25
  }
28
26
  }
29
- function handleBatchResultsFile(results, tapFileConfig) {
27
+ function handleBatchResultsFile(results: any, tapFileConfig: any) {
30
28
  const fileName = tapFileConfig.tapFileName || `${new Date().toISOString()}-eyes.tap`
31
29
  const tapFile = resolve(tapFileConfig.tapDirPath, fileName)
32
- return writeFile(tapFile, formatters.toHierarchicTAPString(results, {includeSubTests: false, markNewAsPassed: true}))
30
+ return fs.writeFile(
31
+ tapFile,
32
+ formatters.toHierarchicTAPString(results, {includeSubTests: false, markNewAsPassed: true}),
33
+ {},
34
+ (err: any) => {
35
+ if (err) throw err
36
+ },
37
+ )
33
38
  }
34
39
 
35
- module.exports = {printTestResults, handleBatchResultsFile}
40
+ export default {printTestResults, handleBatchResultsFile}
@@ -0,0 +1,60 @@
1
+ import handleTestResults from './handleTestResults'
2
+ export type EyesCypressAction = 'before:run' | 'after:run'
3
+
4
+ declare global {
5
+ // eslint-disable-next-line @typescript-eslint/no-namespace
6
+ namespace Cypress {
7
+ interface ResolvedConfigOptions {
8
+ appliConfFile: {
9
+ dontCloseBatches: boolean
10
+ batch: any
11
+ serverUrl: string
12
+ proxy: string
13
+ apiKey: string
14
+ batchId: string
15
+ tapDirPath: string
16
+ tapFileName: string
17
+ }
18
+ }
19
+ }
20
+ }
21
+
22
+ export default function makeGlobalRunHooks({closeManager, closeBatches, closeUniversalServer}: any): {
23
+ 'after:run': (results: CypressCommandLine.CypressRunResult) => void | Promise<void>
24
+ 'before:run': (runDetails: Cypress.BeforeRunDetails) => void | Promise<void>
25
+ } {
26
+ return {
27
+ 'before:run': ({config}: Cypress.BeforeRunDetails): void => {
28
+ if (!(config as Cypress.Config).isTextTerminal) return
29
+ },
30
+
31
+ 'after:run': async ({config}: CypressCommandLine.CypressRunResult) => {
32
+ try {
33
+ if (!(config as Cypress.Config).isTextTerminal) return
34
+ const summaries = await closeManager()
35
+
36
+ let testResults
37
+ for (const summary of summaries) {
38
+ testResults = summary.results.map(({testResults}: any) => testResults)
39
+ }
40
+ if (!config.appliConfFile.dontCloseBatches) {
41
+ await closeBatches({
42
+ batchIds: [config.appliConfFile.batchId || config.appliConfFile.batch.id],
43
+ serverUrl: config.appliConfFile.serverUrl,
44
+ proxy: config.appliConfFile.proxy,
45
+ apiKey: config.appliConfFile.apiKey,
46
+ })
47
+ }
48
+
49
+ if (config.appliConfFile.tapDirPath) {
50
+ await handleTestResults.handleBatchResultsFile(testResults, {
51
+ tapDirPath: config.appliConfFile.tapDirPath,
52
+ tapFileName: config.appliConfFile.tapFileName,
53
+ })
54
+ }
55
+ } finally {
56
+ await closeUniversalServer()
57
+ }
58
+ },
59
+ }
60
+ }
@@ -0,0 +1,37 @@
1
+ 'use strict'
2
+ import makePluginExport from './pluginExport'
3
+ import makeConfig from './config'
4
+ import makeStartServer from './server'
5
+ import {makeLogger} from '@applitools/logger'
6
+
7
+ // DON'T REMOVE
8
+ //
9
+ // if remove the `ttsc` will compile the absolute path
10
+ //
11
+ // the absolute path is added because api-extractor goes over the `eyesPlugin`
12
+ // declaration before it goes over the `EyesConfig` definition, and this is why
13
+ // it's important to reverse the order
14
+ export type EyesPluginConfig = {
15
+ tapDirPath: string
16
+ tapFileName: string
17
+ eyesIsDisabled: boolean
18
+ eyesBrowser: any
19
+ eyesLayoutBreakpoints: any
20
+ eyesFailCypressOnDiff: boolean
21
+ eyesDisableBrowserFetching: boolean
22
+ eyesTestConcurrency: number
23
+ eyesWaitBeforeCapture: number
24
+ eyesPort?: number
25
+ }
26
+
27
+ const {config, eyesConfig} = makeConfig()
28
+ const logger = makeLogger({level: config.showLogs ? 'info' : 'silent', label: 'eyes'})
29
+
30
+ const startServer = makeStartServer({logger})
31
+
32
+ const pluginExport = makePluginExport({
33
+ startServer,
34
+ eyesConfig: Object.assign({}, eyesConfig, {appliConfFile: config}),
35
+ })
36
+
37
+ export default pluginExport