@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 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
 
@@ -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.all((_a = runner === null || runner === void 0 ? void 0 : runner.fixturePromises) !== null && _a !== void 0 ? _a : []);
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
- throw new 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}`);
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
- const firstResult = (_a = Object.values(testResults.eyesTestResult)[0]) === null || _a === void 0 ? void 0 : _a.eyesResults[0];
30
- if (!firstResult || !((_b = firstResult.appUrls) === null || _b === void 0 ? void 0 : _b.batch)) {
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
- linkContainer.innerHTML = `<a target='_blank' href='${firstResult.appUrls.batch}'>Results in Eyes Dashboard</a>`;
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 firstChip = document.getElementsByClassName('chip')[0];
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('.chip-body').classList.toggle('hidden');
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('.chip-body');
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;