@applitools/eyes-cypress 3.27.5 → 3.27.7
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 +18 -0
- package/README.md +39 -5
- package/index.d.ts +1 -1
- package/package.json +13 -10
- package/src/browser/eyesCheckMapping.js +10 -0
- package/src/plugin/pluginExport.js +41 -9
- package/src/plugin/server.js +19 -4
- package/src/setup/getCypressPaths.js +10 -3
package/CHANGELOG.md
CHANGED
|
@@ -10,6 +10,24 @@
|
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
|
|
13
|
+
|
|
14
|
+
## 3.27.7 - 2022/11/17
|
|
15
|
+
|
|
16
|
+
### Features
|
|
17
|
+
- Added new selector extensions `child` and `fallback`
|
|
18
|
+
- Use user agent metadata to improve browser environment detection logic
|
|
19
|
+
- Use APPLITOOLS_CONCURRENCY env variable to specify concurrency
|
|
20
|
+
### Bug fixes
|
|
21
|
+
- Support parallel run of multiple `Cypress` instances
|
|
22
|
+
- Add support for regionId and padding for accessibility and floating regions
|
|
23
|
+
|
|
24
|
+
## 3.27.6 - 2022/10/28
|
|
25
|
+
|
|
26
|
+
### Features
|
|
27
|
+
- Add support for componenet testing and cypress config ts file
|
|
28
|
+
### Bug fixes
|
|
29
|
+
- Fixed issue with universal not working in cypress@6
|
|
30
|
+
|
|
13
31
|
## 3.27.5 - 2022/10/20
|
|
14
32
|
|
|
15
33
|
### Features
|
package/README.md
CHANGED
|
@@ -70,13 +70,13 @@ Add this file to your project with either:
|
|
|
70
70
|
1. Adding the path to your [tsconfig](https://www.typescriptlang.org/docs/handbook/tsconfig-json.html) file:
|
|
71
71
|
```
|
|
72
72
|
{
|
|
73
|
-
"files": ["./node_modules/@applitools/eyes-cypress/
|
|
73
|
+
"files": ["./node_modules/@applitools/eyes-cypress/index.d.ts"],
|
|
74
74
|
...
|
|
75
75
|
}
|
|
76
76
|
```
|
|
77
77
|
2. Copying the file to to your [cypress/support/](https://docs.cypress.io/guides/core-concepts/writing-and-organizing-tests.html#Folder-Structure) dir:
|
|
78
78
|
```
|
|
79
|
-
cp node_modules/@applitools/eyes-cypress/
|
|
79
|
+
cp node_modules/@applitools/eyes-cypress/index.d.ts ./cypress/support/
|
|
80
80
|
```
|
|
81
81
|
### Applitools API key
|
|
82
82
|
|
|
@@ -505,7 +505,24 @@ cy.get('some-region').then(el => {
|
|
|
505
505
|
// will add padding of 20px to all JQuery elements at the top, button, right and left of the region
|
|
506
506
|
ignore: {element: el, padding: 20},
|
|
507
507
|
// will add padding for a DOM element on the top of the region
|
|
508
|
-
content: {element: el[0], padding: {top:10}}
|
|
508
|
+
content: {element: el[0], padding: {top:10}},
|
|
509
|
+
accessibility: {
|
|
510
|
+
region: {
|
|
511
|
+
accessibilityType: 'LargeText',
|
|
512
|
+
selector: 'accessibilityRegion',
|
|
513
|
+
},
|
|
514
|
+
padding: {left: 5},
|
|
515
|
+
},
|
|
516
|
+
floating:{
|
|
517
|
+
region: {
|
|
518
|
+
selector: 'floatingRegion',
|
|
519
|
+
},
|
|
520
|
+
maxDownOffset: 3,
|
|
521
|
+
maxLeftOffset: 20,
|
|
522
|
+
maxRightOffset: 30,
|
|
523
|
+
maxUpOffset: 3,
|
|
524
|
+
padding: {top: 20},
|
|
525
|
+
},
|
|
509
526
|
})
|
|
510
527
|
|
|
511
528
|
})
|
|
@@ -662,10 +679,27 @@ cy.get('.region.two:nth-child(2)').then(el => {
|
|
|
662
679
|
cy.eyesCheckWindow({
|
|
663
680
|
fully: false,
|
|
664
681
|
ignore: [
|
|
665
|
-
{region: {type: 'css', selector: '
|
|
666
|
-
{type: 'xpath', selector: '
|
|
682
|
+
{region: {type: 'css', selector: 'ignore1'}, regionId: 'region3'},
|
|
683
|
+
{type: 'xpath', selector: 'ignore2'},
|
|
667
684
|
{element: el, regionId: 'my-region-id'},
|
|
668
685
|
],
|
|
686
|
+
accessibility: [{
|
|
687
|
+
region: {
|
|
688
|
+
accessibilityType: 'LargeText',
|
|
689
|
+
selector: 'accessibilityRegion',
|
|
690
|
+
},
|
|
691
|
+
regionId: 'accesibility-regionId',
|
|
692
|
+
},],
|
|
693
|
+
floating: [{
|
|
694
|
+
region: {
|
|
695
|
+
selector: 'floatingRegion',
|
|
696
|
+
},
|
|
697
|
+
maxDownOffset: 3,
|
|
698
|
+
maxLeftOffset: 20,
|
|
699
|
+
maxRightOffset: 30,
|
|
700
|
+
maxUpOffset: 3,
|
|
701
|
+
regionId: 'floating-regionId',
|
|
702
|
+
}]
|
|
669
703
|
});
|
|
670
704
|
})
|
|
671
705
|
```
|
package/index.d.ts
CHANGED
|
@@ -7,7 +7,7 @@ type LegacyRegion = {left: number; top: number; width: number; height: number}
|
|
|
7
7
|
type Selector = {selector: string; type?: 'css' | 'xpath', nodeType?: 'element' | 'shadow-root'} | 'string'
|
|
8
8
|
type Element = HTMLElement | JQuery<HTMLElement>
|
|
9
9
|
|
|
10
|
-
interface CypressCheckSettings extends api.
|
|
10
|
+
interface CypressCheckSettings extends api.CheckSettingsAutomationPlain<Element, Selector>{
|
|
11
11
|
tag?: CypressCheckSettings['name']
|
|
12
12
|
|
|
13
13
|
target?: 'window' | 'region'
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@applitools/eyes-cypress",
|
|
3
|
-
"version": "3.27.
|
|
3
|
+
"version": "3.27.7",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "git://github.com/applitools/eyes.sdk.javascript1.git",
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
"lint": "eslint \"**/*.js\"",
|
|
29
29
|
"build": "tsc",
|
|
30
30
|
"generate:tests": "coverage-tests generate",
|
|
31
|
-
"test": "yarn test:unit && yarn test:it && yarn test:e2e && yarn test:ts && yarn test:coverage",
|
|
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",
|
|
33
33
|
"test:unit": "mocha --no-timeouts 'test/unit/**/*.test.js'",
|
|
34
34
|
"test:it": "yarn build && mocha --no-timeouts 'test/it/**/*.test.js'",
|
|
@@ -37,6 +37,7 @@
|
|
|
37
37
|
"test:ts:run": "cypress run --config-file test/e2e/ts/cypress-ts.json",
|
|
38
38
|
"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
39
|
"test:e2e": "mkdir -p test/fixtures/testAppCopies && mocha --no-timeouts 'test/e2e/**/*.test.js'",
|
|
40
|
+
"test:components": "cd test/components && yarn && npx cypress run --component",
|
|
40
41
|
"cypress": "cypress open --config-file test/fixtures/cypress-play.json",
|
|
41
42
|
"cypress:new": "cd test/play && yarn && npx cypress open",
|
|
42
43
|
"cypress:run": "cypress run --config-file test/fixtures/cypress-play.json --spec=test/fixtures/testApp/cypress/integration-play/play.js",
|
|
@@ -55,25 +56,27 @@
|
|
|
55
56
|
}
|
|
56
57
|
},
|
|
57
58
|
"dependencies": {
|
|
58
|
-
"@applitools/core": "1.2.
|
|
59
|
-
"@applitools/eyes-api": "1.
|
|
60
|
-
"@applitools/eyes-universal": "2.
|
|
59
|
+
"@applitools/core": "1.2.12",
|
|
60
|
+
"@applitools/eyes-api": "1.10.4",
|
|
61
|
+
"@applitools/eyes-universal": "2.17.2",
|
|
61
62
|
"@applitools/functional-commons": "1.6.0",
|
|
62
|
-
"@applitools/logger": "1.1.
|
|
63
|
+
"@applitools/logger": "1.1.30",
|
|
63
64
|
"chalk": "3.0.0",
|
|
64
|
-
"semver": "7.3.
|
|
65
|
+
"semver": "7.3.8",
|
|
65
66
|
"uuid": "8.3.2",
|
|
67
|
+
"which": "2.0.2",
|
|
66
68
|
"ws": "8.5.0"
|
|
67
69
|
},
|
|
68
70
|
"devDependencies": {
|
|
69
71
|
"@applitools/bongo": "^2.2.0",
|
|
70
72
|
"@applitools/scripts": "1.2.0",
|
|
71
|
-
"@applitools/sdk-coverage-tests": "^2.
|
|
73
|
+
"@applitools/sdk-coverage-tests": "^2.7.8",
|
|
72
74
|
"@applitools/snaptdout": "1.0.1",
|
|
73
|
-
"@applitools/test-server": "1.1.
|
|
75
|
+
"@applitools/test-server": "1.1.10",
|
|
74
76
|
"@applitools/test-utils": "1.5.2",
|
|
75
|
-
"@applitools/utils": "1.3.
|
|
77
|
+
"@applitools/utils": "1.3.16",
|
|
76
78
|
"@types/node": "12",
|
|
79
|
+
"@types/which": "^2.0.1",
|
|
77
80
|
"@types/ws": "^8.2.2",
|
|
78
81
|
"@typescript-eslint/eslint-plugin": "^5.10.2",
|
|
79
82
|
"@typescript-eslint/parser": "^5.10.2",
|
|
@@ -119,6 +119,10 @@ function eyesCheckMapValues({args, refer}) {
|
|
|
119
119
|
resRegions = [...resRegions, ...refElements(region)];
|
|
120
120
|
}
|
|
121
121
|
} else {
|
|
122
|
+
if (region.selector && !region.type) {
|
|
123
|
+
region.region = region.selector;
|
|
124
|
+
delete region.selector;
|
|
125
|
+
}
|
|
122
126
|
resRegions.push(region);
|
|
123
127
|
}
|
|
124
128
|
}
|
|
@@ -141,6 +145,10 @@ function eyesCheckMapValues({args, refer}) {
|
|
|
141
145
|
for (const element of elements) {
|
|
142
146
|
accessibility.push(Object.assign({}, accessabilityRegion, {region: element}));
|
|
143
147
|
}
|
|
148
|
+
} else if (region.hasOwnProperty('region')) {
|
|
149
|
+
region.type = region.region.accessibilityType;
|
|
150
|
+
delete region.region.accessibilityType;
|
|
151
|
+
accessibility.push(region);
|
|
144
152
|
} else {
|
|
145
153
|
accessabilityRegion.region = {
|
|
146
154
|
y: region.top,
|
|
@@ -174,6 +182,8 @@ function eyesCheckMapValues({args, refer}) {
|
|
|
174
182
|
for (const element of elements) {
|
|
175
183
|
floating.push(Object.assign({}, floatingRegion, {region: element}));
|
|
176
184
|
}
|
|
185
|
+
} else if (region.hasOwnProperty('region')) {
|
|
186
|
+
floating.push(region);
|
|
177
187
|
} else {
|
|
178
188
|
floatingRegion.region = {
|
|
179
189
|
y: region.top,
|
|
@@ -5,10 +5,22 @@ const makeGlobalRunHooks = require('./hooks');
|
|
|
5
5
|
|
|
6
6
|
function makePluginExport({startServer, eyesConfig}) {
|
|
7
7
|
return function pluginExport(pluginModule) {
|
|
8
|
-
let eyesServer;
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
|
|
8
|
+
let eyesServer, pluginModuleExports, pluginExportsE2E, pluginExportsComponent;
|
|
9
|
+
const pluginExports =
|
|
10
|
+
pluginModule.exports && pluginModule.exports.default
|
|
11
|
+
? pluginModule.exports.default
|
|
12
|
+
: pluginModule.exports;
|
|
13
|
+
|
|
14
|
+
if (pluginExports.component) {
|
|
15
|
+
pluginExportsComponent = pluginExports.component.setupNodeEvents;
|
|
16
|
+
}
|
|
17
|
+
if (pluginExports.e2e) {
|
|
18
|
+
pluginExportsE2E = pluginExports.e2e.setupNodeEvents;
|
|
19
|
+
}
|
|
20
|
+
if (!pluginExports.e2e && !pluginExports.component) {
|
|
21
|
+
pluginModuleExports = pluginExports;
|
|
22
|
+
}
|
|
23
|
+
|
|
12
24
|
const setupNodeEvents = async function(...args) {
|
|
13
25
|
const {server, port, closeManager, closeBatches, closeUniversalServer} = await startServer();
|
|
14
26
|
eyesServer = server;
|
|
@@ -16,9 +28,19 @@ function makePluginExport({startServer, eyesConfig}) {
|
|
|
16
28
|
const globalHooks = makeGlobalRunHooks({closeManager, closeBatches, closeUniversalServer});
|
|
17
29
|
|
|
18
30
|
const [origOn, config] = args;
|
|
31
|
+
|
|
32
|
+
if (!pluginModuleExports) {
|
|
33
|
+
pluginModuleExports =
|
|
34
|
+
config.testingType === 'e2e' ? pluginExportsE2E : pluginExportsComponent;
|
|
35
|
+
}
|
|
36
|
+
|
|
19
37
|
const isGlobalHookCalledFromUserHandlerMap = new Map();
|
|
20
38
|
eyesConfig.eyesIsGlobalHooksSupported = isGlobalHooksSupported(config);
|
|
21
|
-
|
|
39
|
+
let moduleExportsResult = {};
|
|
40
|
+
// in case setupNodeEvents is not defined in cypress.config file
|
|
41
|
+
if (typeof pluginModuleExports === 'function') {
|
|
42
|
+
moduleExportsResult = await pluginModuleExports(onThatCallsUserDefinedHandler, config);
|
|
43
|
+
}
|
|
22
44
|
if (eyesConfig.eyesIsGlobalHooksSupported) {
|
|
23
45
|
for (const [eventName, eventHandler] of Object.entries(globalHooks)) {
|
|
24
46
|
if (!isGlobalHookCalledFromUserHandlerMap.get(eventName)) {
|
|
@@ -53,11 +75,21 @@ function makePluginExport({startServer, eyesConfig}) {
|
|
|
53
75
|
}
|
|
54
76
|
}
|
|
55
77
|
};
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
78
|
+
|
|
79
|
+
if (pluginExports.component) {
|
|
80
|
+
pluginExports.component.setupNodeEvents = setupNodeEvents;
|
|
81
|
+
}
|
|
82
|
+
if (pluginExports.e2e) {
|
|
83
|
+
pluginExports.e2e.setupNodeEvents = setupNodeEvents;
|
|
60
84
|
}
|
|
85
|
+
if (!pluginExports.component && !pluginExports.e2e) {
|
|
86
|
+
if (pluginModule.exports.default) {
|
|
87
|
+
pluginModule.exports.default = setupNodeEvents;
|
|
88
|
+
} else {
|
|
89
|
+
pluginModule.exports = setupNodeEvents;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
61
93
|
return function getCloseServer() {
|
|
62
94
|
return eyesServer.close();
|
|
63
95
|
};
|
package/src/plugin/server.js
CHANGED
|
@@ -4,8 +4,10 @@ const {makeServerProcess} = require('@applitools/eyes-universal');
|
|
|
4
4
|
const handleTestResults = require('./handleTestResults');
|
|
5
5
|
const path = require('path');
|
|
6
6
|
const fs = require('fs');
|
|
7
|
+
const semverLt = require('semver/functions/lt');
|
|
7
8
|
const {Server: HttpsServer} = require('https');
|
|
8
9
|
const {Server: WSServer} = require('ws');
|
|
10
|
+
const which = require('which');
|
|
9
11
|
|
|
10
12
|
function makeStartServer({logger}) {
|
|
11
13
|
return async function startServer() {
|
|
@@ -30,19 +32,32 @@ function makeStartServer({logger}) {
|
|
|
30
32
|
|
|
31
33
|
wss.on('close', () => https.close());
|
|
32
34
|
|
|
35
|
+
const forkOptions = {
|
|
36
|
+
detached: true,
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
const cypressVersion = require('cypress/package.json').version;
|
|
40
|
+
|
|
41
|
+
// `cypress` version below `7.0.0` has an old Electron version which not support async shell process.
|
|
42
|
+
// By passing `execPath` with the node process cwd it will switch the `node` process to be the like the OS have
|
|
43
|
+
// and will not use the unsupported `Cypress Helper.app` with the not supported shell process Electron
|
|
44
|
+
if (semverLt(cypressVersion, '7.0.0')) {
|
|
45
|
+
forkOptions.execPath = await which('node');
|
|
46
|
+
}
|
|
47
|
+
|
|
33
48
|
const {port: universalPort, close: closeUniversalServer} = await makeServerProcess({
|
|
34
|
-
key: path.resolve(__dirname, '../pem/server.key'),
|
|
35
|
-
cert: path.resolve(__dirname, '../pem/server.cert'),
|
|
36
|
-
detached: false,
|
|
37
49
|
idleTimeout: 0,
|
|
38
50
|
shutdownMode: 'stdin',
|
|
51
|
+
forkOptions,
|
|
52
|
+
singleton: false,
|
|
53
|
+
portResolutionMode: 'random',
|
|
39
54
|
});
|
|
40
55
|
|
|
41
56
|
const managers = [];
|
|
42
57
|
let socketWithUniversal;
|
|
43
58
|
|
|
44
59
|
wss.on('connection', socketWithClient => {
|
|
45
|
-
socketWithUniversal = connectSocket(`
|
|
60
|
+
socketWithUniversal = connectSocket(`ws://localhost:${universalPort}/eyes`);
|
|
46
61
|
|
|
47
62
|
socketWithUniversal.setPassthroughListener(message => {
|
|
48
63
|
logger.log('<== ', message.toString().slice(0, 1000));
|
|
@@ -12,8 +12,13 @@ function getCypressPaths({cwd, isCypress10}) {
|
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
function getCypressPaths10AndAbove(cwd) {
|
|
15
|
-
const cypressConfigPath = path.resolve(cwd, 'cypress.config.js')
|
|
16
|
-
|
|
15
|
+
const cypressConfigPath = fs.existsSync(path.resolve(cwd, 'cypress.config.js'))
|
|
16
|
+
? path.resolve(cwd, 'cypress.config.js')
|
|
17
|
+
: fs.existsSync(path.resolve(cwd, 'cypress.config.ts'))
|
|
18
|
+
? path.resolve(cwd, 'cypress.config.ts')
|
|
19
|
+
: undefined;
|
|
20
|
+
|
|
21
|
+
if (cypressConfigPath) {
|
|
17
22
|
const configContent = fs.readFileSync(cypressConfigPath, 'utf-8');
|
|
18
23
|
const supportFilePath = getSupportFilePathFromCypress10Config({cwd, configContent});
|
|
19
24
|
const typeScriptFilePath = supportFilePath
|
|
@@ -27,7 +32,7 @@ function getCypressPaths10AndAbove(cwd) {
|
|
|
27
32
|
};
|
|
28
33
|
} else {
|
|
29
34
|
throw new Error(
|
|
30
|
-
`No configuration file found at ${
|
|
35
|
+
`No configuration file found at ${cwd}. This is usually caused by setting up Eyes before setting up Cypress. Please run "npx cypress open" first.`,
|
|
31
36
|
);
|
|
32
37
|
}
|
|
33
38
|
}
|
|
@@ -45,6 +50,8 @@ function getSupportFilePathFromCypress10Config({cwd, configContent}) {
|
|
|
45
50
|
supportFilePath = path.resolve(cwd, 'cypress/support/e2e.ts');
|
|
46
51
|
} else if (fs.existsSync(path.resolve(cwd, 'cypress/support/component.js'))) {
|
|
47
52
|
supportFilePath = path.resolve(cwd, 'cypress/support/component.js');
|
|
53
|
+
} else if (fs.existsSync(path.resolve(cwd, 'cypress/support/component.ts'))) {
|
|
54
|
+
supportFilePath = path.resolve(cwd, 'cypress/support/component.ts');
|
|
48
55
|
}
|
|
49
56
|
}
|
|
50
57
|
return supportFilePath;
|