@applitools/eyes-playwright 1.41.2 → 1.42.2
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 +44 -0
- package/dist/fixture/index.js +2 -2
- package/dist/fixture/report-plugin/handlers/statusUpdateHandler.js +3 -0
- package/dist/fixture/report-plugin/management/reportDataManager.js +0 -7
- package/dist/fixture/report-plugin/reportRenderer.js +3 -0
- package/dist/fixture/report-plugin/ui/eyesResultsBatchLinkUI.js +21 -4
- package/dist/fixture/report-plugin/ui/navigationUI.js +2 -1
- package/dist/fixture/report-plugin/ui/testDetailUI.js +8 -4
- package/dist/fixture/report-plugin/utils/scriptTagRestorer.js +54 -0
- package/dist/fixture/reportRenderer.js +1 -1
- package/dist/fixture/reportRenderer.js.map +1 -1
- package/dist/fixture/reporterStyle.css +12 -0
- package/package.json +5 -5
- package/types/index.d.ts +7 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,49 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [1.42.2](https://github.com/Applitools-Dev/sdk/compare/js/eyes-playwright@1.42.1...js/eyes-playwright@1.42.2) (2025-12-07)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Dependencies
|
|
7
|
+
|
|
8
|
+
* @applitools/dom-snapshot bumped to 4.15.3
|
|
9
|
+
#### Bug Fixes
|
|
10
|
+
|
|
11
|
+
* capture JavaScript-modified CSS selectors in nested [@layer](https://github.com/layer) rules ([#3391](https://github.com/Applitools-Dev/sdk/issues/3391)) ([b3bceb5](https://github.com/Applitools-Dev/sdk/commit/b3bceb5bfe894f3548173d23942e09d0e04b7e04))
|
|
12
|
+
* @applitools/core bumped to 4.53.2
|
|
13
|
+
#### Bug Fixes
|
|
14
|
+
|
|
15
|
+
* Upgrade core version ([#3398](https://github.com/Applitools-Dev/sdk/issues/3398)) ([68858c7](https://github.com/Applitools-Dev/sdk/commit/68858c7024e0413c1cc6af68752b1c3a9a04bb0b))
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
* @applitools/eyes bumped to 1.36.17
|
|
20
|
+
#### Bug Fixes
|
|
21
|
+
|
|
22
|
+
* capture JavaScript-modified CSS selectors in nested [@layer](https://github.com/layer) rules ([#3391](https://github.com/Applitools-Dev/sdk/issues/3391)) ([b3bceb5](https://github.com/Applitools-Dev/sdk/commit/b3bceb5bfe894f3548173d23942e09d0e04b7e04))
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
## [1.42.1](https://github.com/Applitools-Dev/sdk/compare/js/eyes-playwright@1.42.0...js/eyes-playwright@1.42.1) (2025-11-25)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
### Bug Fixes
|
|
31
|
+
|
|
32
|
+
* remove local storage in playwright reporter ([#3374](https://github.com/Applitools-Dev/sdk/issues/3374)) ([a030b42](https://github.com/Applitools-Dev/sdk/commit/a030b42371eec1bcfa6368dbeb340a95557b63d1))
|
|
33
|
+
|
|
34
|
+
## [1.42.0](https://github.com/Applitools-Dev/sdk/compare/js/eyes-playwright@1.41.2...js/eyes-playwright@1.42.0) (2025-11-24)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
### Features
|
|
38
|
+
|
|
39
|
+
* Add support for the playwright 1.57+ | AD-11932 ([#3369](https://github.com/Applitools-Dev/sdk/issues/3369)) ([7a42481](https://github.com/Applitools-Dev/sdk/commit/7a42481f4e6cf6af96954a1e5567d13d82c68d3a))
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
### Bug Fixes
|
|
43
|
+
|
|
44
|
+
* display missing PW report test details | AD-11932 ([#3368](https://github.com/Applitools-Dev/sdk/issues/3368)) ([1660412](https://github.com/Applitools-Dev/sdk/commit/16604124d1165b564b33d7b2f79336d7de37a4ec))
|
|
45
|
+
* Playwright reporter not handling upload ETIMEOUT | FLD-3838 ([#3364](https://github.com/Applitools-Dev/sdk/issues/3364)) ([56d564a](https://github.com/Applitools-Dev/sdk/commit/56d564aa3cb6fadea547ed2b21b8adb3f34f4635))
|
|
46
|
+
|
|
3
47
|
## [1.41.2](https://github.com/Applitools-Dev/sdk/compare/js/eyes-playwright@1.41.1...js/eyes-playwright@1.41.2) (2025-11-19)
|
|
4
48
|
|
|
5
49
|
|
package/dist/fixture/index.js
CHANGED
|
@@ -22,7 +22,7 @@ exports.test = test_1.test.extend({
|
|
|
22
22
|
output(`Waiting on eyes results for worker #${workerInfo.parallelIndex}-${workerInfo.workerIndex} - it might take a while`);
|
|
23
23
|
}
|
|
24
24
|
try {
|
|
25
|
-
await Promise.
|
|
25
|
+
await Promise.allSettled((_a = runner === null || runner === void 0 ? void 0 : runner.fixturePromises) !== null && _a !== void 0 ? _a : []);
|
|
26
26
|
await runner.getAllTestResults(eyesConfig.failTestsOnDiff === 'afterAll').catch(err => {
|
|
27
27
|
const newError = new Error(err.message);
|
|
28
28
|
newError.stack = undefined;
|
|
@@ -116,7 +116,7 @@ async function writeResultsWhenReady({ eyes, runner, testInfo, logger, }) {
|
|
|
116
116
|
.catch((e) => {
|
|
117
117
|
var _a;
|
|
118
118
|
// TODO error handling
|
|
119
|
-
|
|
119
|
+
logger.error(`Failed to get eyes test results: ${(_a = e === null || e === void 0 ? void 0 : e.message) !== null && _a !== void 0 ? _a : e} ${e === null || e === void 0 ? void 0 : e.stack}`);
|
|
120
120
|
}));
|
|
121
121
|
}
|
|
122
122
|
async function getEyesConfigForWorker(workerInfo) {
|
|
@@ -5,6 +5,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.StatusUpdateHandler = void 0;
|
|
7
7
|
const urlManager_js_1 = require("../data/urlManager.js");
|
|
8
|
+
const scriptTagRestorer_js_1 = require("../utils/scriptTagRestorer.js");
|
|
8
9
|
const log_1 = __importDefault(require("../core/log"));
|
|
9
10
|
const logger = (0, log_1.default)();
|
|
10
11
|
class StatusUpdateHandler {
|
|
@@ -12,6 +13,8 @@ class StatusUpdateHandler {
|
|
|
12
13
|
this.handleStatusUpdate = async (testResults) => {
|
|
13
14
|
// Capture scroll position before triggering window.onload
|
|
14
15
|
this.scrollPreserver.captureScrollPosition();
|
|
16
|
+
// Ensure the script tag exists before calling window.onload (Playwright 1.57+ compatibility)
|
|
17
|
+
(0, scriptTagRestorer_js_1.ensureScriptTagExists)();
|
|
15
18
|
if (typeof window.onload === 'function') {
|
|
16
19
|
const onloadHandler = window.onload;
|
|
17
20
|
onloadHandler(new Event('load'));
|
|
@@ -21,12 +21,5 @@ async function refreshReportData(testsFiles, report) {
|
|
|
21
21
|
const generatedZip = await newZip.generateAsync({ type: 'base64' });
|
|
22
22
|
window.playwrightReportBase64 = `data:application/zip;base64,${generatedZip}`;
|
|
23
23
|
logger.log('[Report Data Manager] Report data refreshed.');
|
|
24
|
-
// Also store in localStorage for HMR support PW 1.55 and above
|
|
25
|
-
try {
|
|
26
|
-
localStorage.setItem('playwrightReportStorageForHMR', generatedZip);
|
|
27
|
-
}
|
|
28
|
-
catch (e) {
|
|
29
|
-
logger.warn('[Report Data Manager] Unable to access localStorage:', e);
|
|
30
|
-
}
|
|
31
24
|
}
|
|
32
25
|
exports.refreshReportData = refreshReportData;
|
|
@@ -22,6 +22,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
22
22
|
const dataParser_js_1 = require("./data/dataParser.js");
|
|
23
23
|
const navigationState_js_1 = require("./state/navigationState.js");
|
|
24
24
|
const scrollPreserver_js_1 = require("./utils/scrollPreserver.js");
|
|
25
|
+
const scriptTagRestorer_js_1 = require("./utils/scriptTagRestorer.js");
|
|
25
26
|
const eyesResultsBatchLinkUI_js_1 = require("./ui/eyesResultsBatchLinkUI.js");
|
|
26
27
|
const navigationUI_js_1 = require("./ui/navigationUI.js");
|
|
27
28
|
const filterManager_js_1 = require("./ui/filterManager.js");
|
|
@@ -38,6 +39,8 @@ class ReportRenderer {
|
|
|
38
39
|
this.updatePlaywrightWithEyesResults = () => {
|
|
39
40
|
// Capture scroll position before triggering window.onload
|
|
40
41
|
this.scrollPreserver.captureScrollPosition();
|
|
42
|
+
// Ensure the script tag exists before calling window.onload (Playwright 1.57+ compatibility)
|
|
43
|
+
(0, scriptTagRestorer_js_1.ensureScriptTagExists)();
|
|
41
44
|
if (typeof window.onload === 'function') {
|
|
42
45
|
const onloadHandler = window.onload;
|
|
43
46
|
onloadHandler(new Event('load'));
|
|
@@ -12,7 +12,6 @@ class EyesResultsBatchLinkUI {
|
|
|
12
12
|
this._linkCreated = false;
|
|
13
13
|
}
|
|
14
14
|
createLinkToBatch(testResults) {
|
|
15
|
-
var _a, _b;
|
|
16
15
|
if (!(0, urlManager_js_1.isListMode)()) {
|
|
17
16
|
this.removeLinkToBatch();
|
|
18
17
|
return;
|
|
@@ -26,14 +25,32 @@ class EyesResultsBatchLinkUI {
|
|
|
26
25
|
logger.warn('No chip element found, cannot create link');
|
|
27
26
|
return;
|
|
28
27
|
}
|
|
29
|
-
|
|
30
|
-
|
|
28
|
+
// Collect all distinct batch URLs
|
|
29
|
+
const batchesMap = new Map();
|
|
30
|
+
Object.values(testResults.eyesTestResult).forEach(testResult => {
|
|
31
|
+
testResult === null || testResult === void 0 ? void 0 : testResult.eyesResults.forEach(result => {
|
|
32
|
+
var _a;
|
|
33
|
+
if ((_a = result.appUrls) === null || _a === void 0 ? void 0 : _a.batch) {
|
|
34
|
+
batchesMap.set(result.batchName, result.appUrls.batch);
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
if (batchesMap.size === 0) {
|
|
31
39
|
logger.warn('No Eyes results with batch URL found');
|
|
32
40
|
return;
|
|
33
41
|
}
|
|
34
42
|
const linkContainer = document.createElement('div');
|
|
35
43
|
linkContainer.classList.add('eyes-batch-link');
|
|
36
|
-
|
|
44
|
+
// Create a link for each distinct batch
|
|
45
|
+
Array.from(batchesMap).forEach((batchEntry, index) => {
|
|
46
|
+
const link = document.createElement('a');
|
|
47
|
+
const batchName = batchEntry[0] !== '' ? ` - ${batchEntry[0]}` : batchesMap.size > 1 ? ` (Batch ${index + 1})` : '';
|
|
48
|
+
link.target = '_blank';
|
|
49
|
+
link.href = batchEntry[1];
|
|
50
|
+
link.textContent =
|
|
51
|
+
batchesMap.size > 1 ? `Results in Eyes Dashboard${batchName}` : `Results in Eyes Dashboard${batchName}`;
|
|
52
|
+
linkContainer.appendChild(link);
|
|
53
|
+
});
|
|
37
54
|
firstChip.parentNode.insertBefore(linkContainer, firstChip);
|
|
38
55
|
this._linkCreated = true;
|
|
39
56
|
}
|
|
@@ -21,7 +21,8 @@ class NavigationUI {
|
|
|
21
21
|
return;
|
|
22
22
|
}
|
|
23
23
|
const allFilters = document.getElementsByClassName('subnav-item');
|
|
24
|
-
const navTextButtons = Array.from(allFilters).filter(filter => filter.tagName === 'A'
|
|
24
|
+
const navTextButtons = Array.from(allFilters).filter(filter => filter.tagName === 'A' &&
|
|
25
|
+
(filter.querySelector('.subnav-item-label') !== null || filter.querySelector('.d-inline') !== null));
|
|
25
26
|
const lastFilter = navTextButtons[navTextButtons.length - 1];
|
|
26
27
|
if (!lastFilter) {
|
|
27
28
|
logger.warn('[Eyes Navigation] No subnav items found, cannot create filters');
|
|
@@ -155,7 +155,9 @@ class TestDetailUI {
|
|
|
155
155
|
}
|
|
156
156
|
}
|
|
157
157
|
createTemplateChip() {
|
|
158
|
-
const
|
|
158
|
+
const testResultElement = document.querySelector('.test-result');
|
|
159
|
+
const firstChip = ((testResultElement === null || testResultElement === void 0 ? void 0 : testResultElement.querySelector('.chip')) ||
|
|
160
|
+
document.getElementsByClassName('chip')[0]);
|
|
159
161
|
const chipTemplate = firstChip.cloneNode(true);
|
|
160
162
|
chipTemplate.classList.add('eyes-test-results');
|
|
161
163
|
const chipTemplateHeader = chipTemplate.querySelector('.chip-header');
|
|
@@ -168,9 +170,11 @@ class TestDetailUI {
|
|
|
168
170
|
const target = event.currentTarget;
|
|
169
171
|
target.classList.toggle('expanded-false');
|
|
170
172
|
target.classList.toggle('expanded-true');
|
|
171
|
-
target.parentNode.querySelector('.
|
|
173
|
+
const bodyElement = target.parentNode.querySelector('.test-result') || target.parentNode.querySelector('.chip-body');
|
|
174
|
+
bodyElement.classList.toggle('hidden');
|
|
172
175
|
};
|
|
173
|
-
const chipTemplateBody = chipTemplate.querySelector('.
|
|
176
|
+
const chipTemplateBody = (chipTemplate.querySelector('.test-result') ||
|
|
177
|
+
chipTemplate.querySelector('.chip-body'));
|
|
174
178
|
chipTemplateBody.innerHTML = '';
|
|
175
179
|
return { chipTemplate, chipTemplateHeader, firstChip };
|
|
176
180
|
}
|
|
@@ -240,7 +244,7 @@ class TestDetailUI {
|
|
|
240
244
|
if (shouldFilterUnresolved && (0, statusUtils_js_1.getSingleSessionStatus)(result).status !== 'unresolved')
|
|
241
245
|
return;
|
|
242
246
|
const chip = this.createChipForTest(result, chipTemplate, chipTemplateHeader);
|
|
243
|
-
const chipBody = chip.querySelector('.chip-body');
|
|
247
|
+
const chipBody = (chip.querySelector('.test-result') || chip.querySelector('.chip-body'));
|
|
244
248
|
let bodyElement;
|
|
245
249
|
if (result.steps === 0) {
|
|
246
250
|
bodyElement = document.createElement('div');
|
|
@@ -0,0 +1,54 @@
|
|
|
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
|
+
exports.ensureScriptTagExists = void 0;
|
|
7
|
+
const log_js_1 = __importDefault(require("../core/log.js"));
|
|
8
|
+
const logger = (0, log_js_1.default)('[Script Tag Restorer]');
|
|
9
|
+
/**
|
|
10
|
+
* Restores the playwrightReportBase64 script tag if it's been removed by Playwright's host code.
|
|
11
|
+
* This is necessary for Playwright 1.57+ where the host removes the tag after reading it in window.onload.
|
|
12
|
+
*
|
|
13
|
+
* When we invoke window.onload() to trigger React re-renders, the host code expects the script tag
|
|
14
|
+
* to exist. If it doesn't exist, we recreate it from the data stored in window.playwrightReportBase64.
|
|
15
|
+
*/
|
|
16
|
+
function ensureScriptTagExists() {
|
|
17
|
+
var _a;
|
|
18
|
+
const scriptTagId = 'playwrightReportBase64';
|
|
19
|
+
let scriptTag = document.getElementById(scriptTagId);
|
|
20
|
+
// If the script tag already exists, no action needed
|
|
21
|
+
if (scriptTag) {
|
|
22
|
+
logger.log('Script tag already exists, no restoration needed');
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
// Get the data from window.playwrightReportBase64
|
|
26
|
+
const reportData = window.playwrightReportBase64;
|
|
27
|
+
if (!reportData) {
|
|
28
|
+
logger.warn('No playwrightReportBase64 data found in window, cannot restore script tag');
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
// Extract the base64 string (handles both string and object with textContent)
|
|
32
|
+
const base64String = typeof reportData === 'string' ? reportData : (_a = reportData === null || reportData === void 0 ? void 0 : reportData.textContent) !== null && _a !== void 0 ? _a : '';
|
|
33
|
+
if (!base64String) {
|
|
34
|
+
logger.warn('playwrightReportBase64 data is empty, cannot restore script tag');
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
// Create and insert the script tag
|
|
38
|
+
const applicationZipAttribute = document.createAttribute('type');
|
|
39
|
+
applicationZipAttribute.value = 'application/zip';
|
|
40
|
+
scriptTag = document.createElement('script');
|
|
41
|
+
scriptTag.id = scriptTagId;
|
|
42
|
+
scriptTag.attributes.setNamedItem(applicationZipAttribute);
|
|
43
|
+
scriptTag.textContent = base64String;
|
|
44
|
+
// Insert at the beginning of the head or body
|
|
45
|
+
const targetElement = document.head || document.body;
|
|
46
|
+
if (targetElement) {
|
|
47
|
+
targetElement.insertBefore(scriptTag, targetElement.firstChild);
|
|
48
|
+
logger.log('Successfully restored playwrightReportBase64 script tag');
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
logger.error('Cannot find head or body element to insert script tag');
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
exports.ensureScriptTagExists = ensureScriptTagExists;
|