@enact/ui-test-utils 4.0.2 → 4.0.4
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/.github/PULL_REQUEST_TEMPLATE.md +0 -1
- package/.github/workflows/ci-branch.yml +24 -0
- package/.github/workflows/ci-pull-request.yml +19 -0
- package/.github/workflows/ci-reusable.yml +38 -0
- package/.github/workflows/update-copyright-years.yml +23 -0
- package/CHANGELOG.md +8 -0
- package/README.md +4 -4
- package/npm-shrinkwrap.json +1824 -1668
- package/package.json +15 -15
- package/screenshot/TestChooser.module.css +1 -1
- package/screenshot/utils/confHelpers.js +11 -3
- package/screenshot/utils/headerTemplate.js +1 -0
- package/screenshot/utils/redist/failedTests.js +20 -4
- package/screenshot/utils/redist/newFiles.js +19 -4
- package/screenshot/utils/redist/styles.css +12 -3
- package/utils/generateTestData.js +5 -2
- package/utils/runTest.js +4 -1
- package/.travis.yml +0 -13
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@enact/ui-test-utils",
|
|
3
|
-
"version": "4.0.
|
|
3
|
+
"version": "4.0.4",
|
|
4
4
|
"description": "UI Testing for the Enact framework",
|
|
5
5
|
"repository": "https://github.com/enactjs/ui-test-utils",
|
|
6
6
|
"type": "module",
|
|
@@ -29,28 +29,28 @@
|
|
|
29
29
|
"access": "public"
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@wdio/cli": "^9.
|
|
33
|
-
"@wdio/dot-reporter": "^9.
|
|
34
|
-
"@wdio/local-runner": "^9.
|
|
35
|
-
"@wdio/mocha-framework": "^9.
|
|
36
|
-
"@wdio/spec-reporter": "^9.
|
|
37
|
-
"@wdio/static-server-service": "^9.
|
|
38
|
-
"@wdio/visual-service": "^9.2.
|
|
32
|
+
"@wdio/cli": "^9.29.1",
|
|
33
|
+
"@wdio/dot-reporter": "^9.29.1",
|
|
34
|
+
"@wdio/local-runner": "^9.29.1",
|
|
35
|
+
"@wdio/mocha-framework": "^9.29.1",
|
|
36
|
+
"@wdio/spec-reporter": "^9.29.1",
|
|
37
|
+
"@wdio/static-server-service": "^9.29.1",
|
|
38
|
+
"@wdio/visual-service": "^9.2.3",
|
|
39
39
|
"chalk": "^5.6.2",
|
|
40
40
|
"cross-spawn": "^7.0.6",
|
|
41
|
-
"expect-webdriverio": "^5.
|
|
42
|
-
"fs-extra": "^11.3.
|
|
41
|
+
"expect-webdriverio": "^5.7.0",
|
|
42
|
+
"fs-extra": "^11.3.6",
|
|
43
43
|
"minimist": "^1.2.8",
|
|
44
|
-
"query-string": "^
|
|
44
|
+
"query-string": "^9.4.1",
|
|
45
45
|
"ramda": "^0.32.0",
|
|
46
46
|
"readdirp": "^5.0.0",
|
|
47
47
|
"wdio-docker-service": "^3.2.1",
|
|
48
|
-
"webdriverio": "^9.
|
|
48
|
+
"webdriverio": "^9.29.1"
|
|
49
49
|
},
|
|
50
50
|
"devDependencies": {
|
|
51
|
-
"eslint": "^9.39.
|
|
52
|
-
"eslint-config-enact": "^5.1.
|
|
53
|
-
"globals": "^17.
|
|
51
|
+
"eslint": "^9.39.4",
|
|
52
|
+
"eslint-config-enact": "^5.1.2",
|
|
53
|
+
"globals": "^17.7.0"
|
|
54
54
|
},
|
|
55
55
|
"overrides": {
|
|
56
56
|
"serialize-javascript": "^7.0.4",
|
|
@@ -27,6 +27,15 @@ function getScreenshotName (basePath) {
|
|
|
27
27
|
};
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
+
async function setScreenResolution (data) {
|
|
31
|
+
// in Chrome 132, the browser window size takes into account also the address bar and tab area
|
|
32
|
+
const [width, height] = (data?.portrait || data.ctx?.portrait) ? [1080, 2007] : [1920, 1167];
|
|
33
|
+
|
|
34
|
+
await browser.setWindowSize(width, height);
|
|
35
|
+
// Small pause to let window resize complete
|
|
36
|
+
await browser.pause(500);
|
|
37
|
+
}
|
|
38
|
+
|
|
30
39
|
const distPath = path.join(process.cwd(), 'tests', 'screenshot', 'dist');
|
|
31
40
|
const baselineRelativePath = 'screenshots/reference';
|
|
32
41
|
const screenshotRelativePath = 'screenshots/screen';
|
|
@@ -120,7 +129,6 @@ async function checkSessionHealth () {
|
|
|
120
129
|
console.log(`Attempting quick recovery for session ${sessionId}...`);
|
|
121
130
|
try {
|
|
122
131
|
await browser.reloadSession();
|
|
123
|
-
await browser.setWindowSize(1920, 1167);
|
|
124
132
|
console.log(`Session ${sessionId} recovered`);
|
|
125
133
|
} catch (recoveryError) {
|
|
126
134
|
console.log(`Recovery attempt failed, will retry next test`);
|
|
@@ -196,8 +204,6 @@ async function cleanUpSessionHealthCheck (testData, error) {
|
|
|
196
204
|
}
|
|
197
205
|
await browser.deleteSession();
|
|
198
206
|
await browser.reloadSession();
|
|
199
|
-
await browser.setWindowSize(1920, 1167);
|
|
200
|
-
await browser.pause(1000);
|
|
201
207
|
})(),
|
|
202
208
|
new Promise((_, reject) =>
|
|
203
209
|
setTimeout(() => reject(new Error('Recovery timeout')), 10000)
|
|
@@ -234,6 +240,7 @@ async function cleanUpSessionHealthCheck (testData, error) {
|
|
|
234
240
|
|
|
235
241
|
async function beforeTest (testData) {
|
|
236
242
|
await checkSessionHealth();
|
|
243
|
+
await setScreenResolution(testData);
|
|
237
244
|
|
|
238
245
|
// If title doesn't have a '/', it's not a screenshot test, don't save
|
|
239
246
|
if (testData && testData.title && testData.title.indexOf('/') > 0) {
|
|
@@ -299,6 +306,7 @@ async function afterTest (testData, _context, {error, passed}) {
|
|
|
299
306
|
}
|
|
300
307
|
|
|
301
308
|
await cleanUpSessionHealthCheck(testData, error);
|
|
309
|
+
await setScreenResolution(testData);
|
|
302
310
|
}
|
|
303
311
|
|
|
304
312
|
function onComplete () {
|
|
@@ -16,6 +16,7 @@ export function makeHeader (title) {
|
|
|
16
16
|
<div class="cell preview">
|
|
17
17
|
<div class="column">
|
|
18
18
|
<div class="cell fixed preview-header">
|
|
19
|
+
<button id="menu">☰</button>
|
|
19
20
|
<button id="dec"><</button>
|
|
20
21
|
<button id="inc">></button>
|
|
21
22
|
<div id="title">Select an image</div>
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
((results) => {
|
|
2
2
|
const h = document.querySelector('h1');
|
|
3
3
|
const list = document.querySelector('.list > ol');
|
|
4
|
+
const drawer = document.querySelector('.list');
|
|
4
5
|
const count = results.length;
|
|
5
6
|
let currentIndex = -1;
|
|
6
7
|
|
|
@@ -56,9 +57,20 @@
|
|
|
56
57
|
target.appendChild(btn);
|
|
57
58
|
return btn;
|
|
58
59
|
}
|
|
60
|
+
|
|
61
|
+
function toggleDrawer ({collapsed}) {
|
|
62
|
+
if (collapsed) {
|
|
63
|
+
return drawer.classList.toggle('collapsed', collapsed);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const currentState = !drawer.classList.contains('collapsed');
|
|
67
|
+
drawer.classList.toggle('collapsed', currentState);
|
|
68
|
+
}
|
|
69
|
+
|
|
59
70
|
function initializeButtons () {
|
|
60
71
|
const inc = document.querySelector('#inc'),
|
|
61
|
-
dec = document.querySelector('#dec')
|
|
72
|
+
dec = document.querySelector('#dec'),
|
|
73
|
+
menu = document.querySelector('#menu');
|
|
62
74
|
let nextTarget = inc;
|
|
63
75
|
|
|
64
76
|
const buttonbox = document.createElement('span');
|
|
@@ -86,6 +98,7 @@
|
|
|
86
98
|
|
|
87
99
|
inc.onclick = nextImage;
|
|
88
100
|
dec.onclick = prevImage;
|
|
101
|
+
menu.onclick = toggleDrawer;
|
|
89
102
|
}
|
|
90
103
|
|
|
91
104
|
function updateButtons (type) {
|
|
@@ -108,13 +121,16 @@
|
|
|
108
121
|
}
|
|
109
122
|
|
|
110
123
|
document.onkeydown = (ev) => {
|
|
111
|
-
switch (ev.
|
|
112
|
-
case
|
|
124
|
+
switch (ev.key) {
|
|
125
|
+
case "Escape":
|
|
126
|
+
toggleDrawer({collapsed: true});
|
|
127
|
+
break;
|
|
128
|
+
case "ArrowLeft":
|
|
113
129
|
if (count > 0 && currentIndex > 0) {
|
|
114
130
|
prevImage();
|
|
115
131
|
}
|
|
116
132
|
break;
|
|
117
|
-
case
|
|
133
|
+
case "ArrowRight":
|
|
118
134
|
if (count > 0 && currentIndex < (count - 1)) {
|
|
119
135
|
nextImage();
|
|
120
136
|
}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
((results) => {
|
|
3
3
|
const h = document.querySelector('h1');
|
|
4
4
|
const list = document.querySelector('.list > ol');
|
|
5
|
+
const drawer = document.querySelector('.list');
|
|
5
6
|
const count = results.length;
|
|
6
7
|
let currentIndex = -1;
|
|
7
8
|
|
|
@@ -46,11 +47,22 @@
|
|
|
46
47
|
loadImage(currentIndex - 1);
|
|
47
48
|
}
|
|
48
49
|
|
|
50
|
+
function toggleDrawer ({collapsed}) {
|
|
51
|
+
if (collapsed) {
|
|
52
|
+
return drawer.classList.toggle('collapsed', collapsed);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const currentState = !drawer.classList.contains('collapsed');
|
|
56
|
+
drawer.classList.toggle('collapsed', currentState);
|
|
57
|
+
}
|
|
58
|
+
|
|
49
59
|
function initializeButtons () {
|
|
50
60
|
const inc = document.querySelector('#inc'),
|
|
51
|
-
dec = document.querySelector('#dec')
|
|
61
|
+
dec = document.querySelector('#dec'),
|
|
62
|
+
menu = document.querySelector('#menu');
|
|
52
63
|
inc.onclick = nextImage;
|
|
53
64
|
dec.onclick = prevImage;
|
|
65
|
+
menu.onclick = toggleDrawer;
|
|
54
66
|
|
|
55
67
|
const btn = document.createElement('button');
|
|
56
68
|
btn.innerText = 'test case';
|
|
@@ -76,13 +88,16 @@
|
|
|
76
88
|
}
|
|
77
89
|
|
|
78
90
|
document.onkeydown = (ev) => {
|
|
79
|
-
switch (ev.
|
|
80
|
-
case
|
|
91
|
+
switch (ev.key) {
|
|
92
|
+
case "Escape":
|
|
93
|
+
toggleDrawer({collapsed: true});
|
|
94
|
+
break;
|
|
95
|
+
case "ArrowLeft":
|
|
81
96
|
if (count > 0 && currentIndex > 0) {
|
|
82
97
|
prevImage();
|
|
83
98
|
}
|
|
84
99
|
break;
|
|
85
|
-
case
|
|
100
|
+
case "ArrowRight":
|
|
86
101
|
if (count > 0 && currentIndex < (count - 1)) {
|
|
87
102
|
nextImage();
|
|
88
103
|
}
|
|
@@ -9,6 +9,7 @@ body {
|
|
|
9
9
|
}
|
|
10
10
|
|
|
11
11
|
header h1 {
|
|
12
|
+
margin-top: 0;
|
|
12
13
|
padding: 0 1em;
|
|
13
14
|
}
|
|
14
15
|
|
|
@@ -42,7 +43,8 @@ ol li {
|
|
|
42
43
|
}
|
|
43
44
|
|
|
44
45
|
.cell {
|
|
45
|
-
flex: 1 1
|
|
46
|
+
flex: 1 1 0;
|
|
47
|
+
min-height: 0;
|
|
46
48
|
position: relative;
|
|
47
49
|
}
|
|
48
50
|
.cell.fixed {
|
|
@@ -55,9 +57,13 @@ ol li {
|
|
|
55
57
|
|
|
56
58
|
.list {
|
|
57
59
|
margin-right: 12px;
|
|
60
|
+
max-width: 25%;
|
|
58
61
|
overflow: auto;
|
|
59
|
-
max-width: 40%;
|
|
60
62
|
}
|
|
63
|
+
.list.collapsed {
|
|
64
|
+
max-width: 0;
|
|
65
|
+
}
|
|
66
|
+
|
|
61
67
|
.list ol {
|
|
62
68
|
margin-top: 0;
|
|
63
69
|
}
|
|
@@ -146,9 +152,12 @@ button.active {
|
|
|
146
152
|
#title {
|
|
147
153
|
display: inline;
|
|
148
154
|
}
|
|
149
|
-
|
|
150
155
|
#image {
|
|
151
156
|
cursor: zoom-in;
|
|
157
|
+
display: block;
|
|
158
|
+
margin: 0 auto;
|
|
159
|
+
max-width: 100%;
|
|
160
|
+
max-height: 100%;
|
|
152
161
|
}
|
|
153
162
|
#image:focus {
|
|
154
163
|
transform: scale(4);
|
|
@@ -79,6 +79,7 @@ export const generateTestData = (component, componentTests) => {
|
|
|
79
79
|
let metaData = [];
|
|
80
80
|
componentTests.forEach((testCase) => {
|
|
81
81
|
let title = testCase.title;
|
|
82
|
+
const portrait = testCase.portrait;
|
|
82
83
|
|
|
83
84
|
if (!title) {
|
|
84
85
|
// Note: This isn't terribly extensible, but we need to correct the order of props
|
|
@@ -92,12 +93,14 @@ export const generateTestData = (component, componentTests) => {
|
|
|
92
93
|
props: testCase.props ? testCase.props : testCase.component.props,
|
|
93
94
|
wrapper: testCase.wrapper,
|
|
94
95
|
textSize: testCase.textSize,
|
|
95
|
-
skinVariants: testCase.skinVariants
|
|
96
|
+
skinVariants: testCase.skinVariants,
|
|
97
|
+
...(portrait && {portrait})
|
|
96
98
|
});
|
|
97
99
|
}
|
|
98
100
|
|
|
99
101
|
const meta = {
|
|
100
|
-
title
|
|
102
|
+
title,
|
|
103
|
+
...(portrait && {portrait})
|
|
101
104
|
};
|
|
102
105
|
metaData.push(meta);
|
|
103
106
|
});
|
package/utils/runTest.js
CHANGED
|
@@ -43,7 +43,7 @@ export const runTest = ({concurrency, filter, Page, testName, ...rest}) => {
|
|
|
43
43
|
if (titlePattern && !testCase.title.match(titlePattern)) {
|
|
44
44
|
return;
|
|
45
45
|
}
|
|
46
|
-
it(`${component}~/${testName}~/${testCase.title}`, async function () {
|
|
46
|
+
const componentTest = it(`${component}~/${testName}~/${testCase.title}`, async function () {
|
|
47
47
|
const params = Page.serializeParams(Object.assign({
|
|
48
48
|
component,
|
|
49
49
|
testId
|
|
@@ -59,6 +59,7 @@ export const runTest = ({concurrency, filter, Page, testName, ...rest}) => {
|
|
|
59
59
|
|
|
60
60
|
const context = {params, component, testName, url: Page.url, fileName: screenshotFileName};
|
|
61
61
|
this.test.context = context;
|
|
62
|
+
this.portrait = !!testCase.portrait; // Used when screenshots are compared; otherwise, it may compare portrait with landscape
|
|
62
63
|
|
|
63
64
|
await Page.open(`?${params}`);
|
|
64
65
|
|
|
@@ -70,6 +71,8 @@ export const runTest = ({concurrency, filter, Page, testName, ...rest}) => {
|
|
|
70
71
|
waitForFontsLoaded: true
|
|
71
72
|
})).toBe(0);
|
|
72
73
|
});
|
|
74
|
+
// Used for creating references for portrait mode; otherwise, references for portrait mode may not be saved
|
|
75
|
+
componentTest.portrait = !!testCase.portrait;
|
|
73
76
|
});
|
|
74
77
|
});
|
|
75
78
|
}
|
package/.travis.yml
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
dist: jammy
|
|
2
|
-
language: node_js
|
|
3
|
-
node_js:
|
|
4
|
-
- 20
|
|
5
|
-
before_install:
|
|
6
|
-
- sudo apt-get update
|
|
7
|
-
- sudo apt-get install build-essential libcairo2-dev libpango1.0-dev libjpeg-dev libgif-dev librsvg2-dev
|
|
8
|
-
install:
|
|
9
|
-
- npm install
|
|
10
|
-
script:
|
|
11
|
-
- echo -e "\x1b\x5b35;1m*** Linting...\x1b\x5b0m"
|
|
12
|
-
- npm run lint -- --report-unused-disable-directives --max-warnings 0
|
|
13
|
-
- echo -e "\x1b\x5b35;1m*** Linting complete...\x1b\x5b0m"
|