@percy/webdriver-utils 1.31.5 → 1.31.6-beta.5

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/LICENSE ADDED
@@ -0,0 +1,18 @@
1
+ Copyright © Perceptual Inc.
2
+
3
+ The MIT License (MIT)
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
6
+ associated documentation files (the "Software"), to deal in the Software without restriction,
7
+ including without limitation the rights to use, copy, modify, merge, publish, distribute,
8
+ sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
9
+ furnished to do so, subject to the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be included in all copies or substantial
12
+ portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
15
+ NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
16
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
17
+ OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
18
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -1,3 +1,28 @@
1
+ const OS_VERSION_MAP = {
2
+ winxp: 'XP',
3
+ win7: '7',
4
+ win8: '8',
5
+ 'win8.1': '8.1',
6
+ win10: '10',
7
+ win11: '11',
8
+ win12: '12',
9
+ mactho: 'Tahoe',
10
+ macsqa: 'Sequoia',
11
+ macson: 'Sonoma',
12
+ macven: 'Ventura',
13
+ macmty: 'Monterey',
14
+ macbsr: 'Big Sur',
15
+ maccat: 'Catalina',
16
+ macmo: 'Mojave',
17
+ machs: 'High Sierra',
18
+ macsie: 'Sierra',
19
+ macelc: 'El Capitan',
20
+ macyos: 'Yosemite',
21
+ macmav: 'Mavericks',
22
+ macml: 'Mountain Lion',
23
+ maclion: 'Lion',
24
+ macsl: 'Snow Leopard'
25
+ };
1
26
  export default class NormalizeData {
2
27
  osRollUp(os) {
3
28
  if (os.toLowerCase().startsWith('win')) {
@@ -11,6 +36,10 @@ export default class NormalizeData {
11
36
  }
12
37
  return os;
13
38
  }
39
+ osVersionRollUp(osVersion) {
40
+ const normVersion = osVersion.toLowerCase();
41
+ return OS_VERSION_MAP[normVersion] || osVersion;
42
+ }
14
43
  browserRollUp(browserName, device) {
15
44
  if (device) {
16
45
  if (browserName !== null && browserName !== void 0 && browserName.toLowerCase().includes('chrome')) {
@@ -9,9 +9,11 @@ export default class GenericProvider {
9
9
  clientInfoDetails = new Set();
10
10
  environmentInfoDetails = new Set();
11
11
  constructor(args) {
12
+ var _this$options;
12
13
  Object.assign(this, args);
13
14
  this.addClientInfo(this.clientInfo);
14
15
  this.addEnvironmentInfo(this.environmentInfo);
16
+ this.platforms = this.sortPlatforms(((_this$options = this.options) === null || _this$options === void 0 ? void 0 : _this$options.platforms) || []);
15
17
  this._markedPercy = false;
16
18
  this.metaData = null;
17
19
  this.debugUrl = null;
@@ -25,6 +27,22 @@ export default class GenericProvider {
25
27
  this.removeElementShiftFactor = 50000;
26
28
  this.initialScrollLocation = null;
27
29
  }
30
+
31
+ // Sort platforms so that entries without browserVersion or with 'latest' come last
32
+ // As we want to prioritize specific versions first while matching
33
+ sortPlatforms(platforms) {
34
+ const isMissingOrLatest = v => {
35
+ if (!v) return true;
36
+ const s = String(v).toLowerCase();
37
+ return s.includes('latest');
38
+ };
39
+ return [...platforms].sort((a, b) => {
40
+ const aFlag = isMissingOrLatest(a === null || a === void 0 ? void 0 : a.browserVersion);
41
+ const bFlag = isMissingOrLatest(b === null || b === void 0 ? void 0 : b.browserVersion);
42
+ if (aFlag === bFlag) return 0; // keep original order when both are same group
43
+ return aFlag ? 1 : -1; // push missing/latest to the end
44
+ });
45
+ }
28
46
  addDefaultOptions() {
29
47
  this.options.freezeAnimation = this.options.freezeAnimatedImage || this.options.freezeAnimation || false;
30
48
  }
@@ -122,14 +140,14 @@ export default class GenericProvider {
122
140
  async percyScreenshotEnd(name, error) {
123
141
  return await TimeIt.run('percyScreenshotEnd', async () => {
124
142
  try {
125
- var _this$buildInfo, _this$options;
143
+ var _this$buildInfo, _this$options2;
126
144
  await this.browserstackExecutor('percyScreenshot', {
127
145
  name,
128
146
  percyScreenshotUrl: (_this$buildInfo = this.buildInfo) === null || _this$buildInfo === void 0 ? void 0 : _this$buildInfo.url,
129
147
  status: error ? 'failure' : 'success',
130
148
  statusMessage: error ? `${error}` : '',
131
149
  state: 'end',
132
- sync: (_this$options = this.options) === null || _this$options === void 0 ? void 0 : _this$options.sync
150
+ sync: (_this$options2 = this.options) === null || _this$options2 === void 0 ? void 0 : _this$options2.sync
133
151
  });
134
152
  } catch (e) {
135
153
  log.debug(`[${name}] : Could not execute percyScreenshot command for Automate`);
@@ -231,7 +249,7 @@ export default class GenericProvider {
231
249
  this.debugUrl = 'https://localhost/v1';
232
250
  }
233
251
  async doTransformations() {
234
- var _this$options2;
252
+ var _this$options3;
235
253
  const hideScrollbarStyle = `
236
254
  /* Hide scrollbar for Chrome, Safari and Opera */
237
255
  ::-webkit-scrollbar {
@@ -252,7 +270,7 @@ export default class GenericProvider {
252
270
  script: jsScript,
253
271
  args: []
254
272
  });
255
- if ((_this$options2 = this.options) !== null && _this$options2 !== void 0 && _this$options2.fullPage || this.isIOS()) {
273
+ if ((_this$options3 = this.options) !== null && _this$options3 !== void 0 && _this$options3.fullPage || this.isIOS()) {
256
274
  await this.getInitialScrollLocation();
257
275
  }
258
276
  }
@@ -280,11 +298,11 @@ export default class GenericProvider {
280
298
  }
281
299
  }
282
300
  async getRegionObjectFromBoundingBox(selector, element) {
283
- var _this$options3;
301
+ var _this$options4;
284
302
  const scaleFactor = await this.metaData.devicePixelRatio();
285
303
  let scrollX = 0,
286
304
  scrollY = 0;
287
- if ((_this$options3 = this.options) !== null && _this$options3 !== void 0 && _this$options3.fullPage) {
305
+ if ((_this$options4 = this.options) !== null && _this$options4 !== void 0 && _this$options4.fullPage) {
288
306
  scrollX = this.initialScrollLocation.value[0];
289
307
  scrollY = this.initialScrollLocation.value[1];
290
308
  }
@@ -320,14 +338,14 @@ export default class GenericProvider {
320
338
  return regionsArray;
321
339
  }
322
340
  async updatePageShiftFactor(location, scaleFactor, scrollFactors) {
323
- var _this$options4;
341
+ var _this$options5;
324
342
  if (this.isIOS() || this.currentTag.osName === 'OS X' && parseInt(this.currentTag.browserVersion) > 13 && this.currentTag.browserName.toLowerCase() === 'safari') {
325
343
  this.pageYShiftFactor = this.statusBarHeight;
326
344
  } else {
327
345
  this.pageYShiftFactor = this.statusBarHeight - scrollFactors.value[1] * scaleFactor;
328
346
  }
329
347
  this.pageXShiftFactor = this.isIOS() ? 0 : -(scrollFactors.value[0] * scaleFactor);
330
- if (this.isIOS() && !((_this$options4 = this.options) !== null && _this$options4 !== void 0 && _this$options4.fullPage)) {
348
+ if (this.isIOS() && !((_this$options5 = this.options) !== null && _this$options5 !== void 0 && _this$options5.fullPage)) {
331
349
  if (scrollFactors.value[0] !== this.initialScrollLocation.value[0] || scrollFactors.value[1] !== this.initialScrollLocation.value[1]) {
332
350
  this.pageXShiftFactor = -1 * this.removeElementShiftFactor;
333
351
  this.pageYShiftFactor = -1 * this.removeElementShiftFactor;
@@ -337,7 +355,7 @@ export default class GenericProvider {
337
355
  }
338
356
  }
339
357
  async getRegionObject(selector, elementId) {
340
- var _this$options5;
358
+ var _this$options6;
341
359
  const scaleFactor = await this.metaData.devicePixelRatio();
342
360
  const rect = await this.driver.rect(elementId);
343
361
  const location = {
@@ -351,7 +369,7 @@ export default class GenericProvider {
351
369
  let scrollX = 0,
352
370
  scrollY = 0;
353
371
  const scrollFactors = await this.getScrollDetails();
354
- if ((_this$options5 = this.options) !== null && _this$options5 !== void 0 && _this$options5.fullPage) {
372
+ if ((_this$options6 = this.options) !== null && _this$options6 !== void 0 && _this$options6.fullPage) {
355
373
  scrollX = scrollFactors.value[0];
356
374
  scrollY = scrollFactors.value[1];
357
375
  }
@@ -417,6 +435,42 @@ export default class GenericProvider {
417
435
  }
418
436
  return elementsArray;
419
437
  }
438
+ resolvePercyBrowserCustomNameFor({
439
+ osName,
440
+ osVersion,
441
+ browserName,
442
+ browserVersion,
443
+ deviceName,
444
+ isMobile
445
+ }) {
446
+ if (this.platforms.length === 0) return null;
447
+ const norm = v => v.toString().toLowerCase(); // normalize
448
+ const match = (userInput, output) => {
449
+ if (!userInput) return true;
450
+ return norm(userInput) === norm(output);
451
+ };
452
+ const includes = (a, b) => {
453
+ const na = norm(a);
454
+ const nb = norm(b);
455
+ return na.includes(nb);
456
+ };
457
+ for (const platform of this.platforms) {
458
+ const percyBrowserCustomName = platform.percyBrowserCustomName;
459
+ const pDevice = platform.deviceName || '';
460
+ const pOsName = platform.osName || '';
461
+ const pOsVersion = (platform.osVersion || '').toString();
462
+ const pBrowserName = platform.browserName || '';
463
+ const pBrowserVersion = (platform.browserVersion || '').toString();
464
+ if (match(pOsName, osName) && match(pBrowserName, browserName) && match(pOsVersion, osVersion) && (!pBrowserVersion || pBrowserVersion.toLowerCase() === 'latest' || includes(browserVersion, pBrowserVersion))) {
465
+ if (isMobile) {
466
+ if (!match(pDevice, deviceName)) continue;
467
+ return percyBrowserCustomName;
468
+ }
469
+ return percyBrowserCustomName;
470
+ }
471
+ }
472
+ return null;
473
+ }
420
474
  async getTag(tagData) {
421
475
  var _automateCaps$os_vers;
422
476
  if (!this.automateResults) throw new Error('Comparison tag details not available');
@@ -424,7 +478,7 @@ export default class GenericProvider {
424
478
  const normalizeTags = new NormalizeData();
425
479
  let deviceName = this.automateResults.deviceName;
426
480
  const osName = normalizeTags.osRollUp(automateCaps.os);
427
- const osVersion = (_automateCaps$os_vers = automateCaps.os_version) === null || _automateCaps$os_vers === void 0 ? void 0 : _automateCaps$os_vers.split('.')[0];
481
+ const osVersion = normalizeTags.osVersionRollUp((_automateCaps$os_vers = automateCaps.os_version) === null || _automateCaps$os_vers === void 0 ? void 0 : _automateCaps$os_vers.split('.')[0]);
428
482
  const browserName = normalizeTags.browserRollUp(automateCaps.browserName, tagData.device);
429
483
  const browserVersion = normalizeTags.browserVersionOrDeviceNameRollup(automateCaps.browserVersion, deviceName, tagData.device);
430
484
  if (!tagData.device) {
@@ -439,6 +493,16 @@ export default class GenericProvider {
439
493
  };
440
494
  const resolution = tagData.resolution;
441
495
  const orientation = tagData.orientation || automateCaps.deviceOrientation || 'landscape';
496
+ log.debug(`Tag Details - Device: ${deviceName}, OS: ${osName}, ` + `OS Version: ${osVersion}, Browser: ${browserName}, ` + `Browser Version: ${browserVersion}, Width: ${width}, ` + `Height: ${height}, Orientation: ${orientation}, ` + `Resolution: ${resolution}`);
497
+ const percyBrowserCustomName = this.resolvePercyBrowserCustomNameFor({
498
+ osName,
499
+ osVersion,
500
+ browserName,
501
+ browserVersion,
502
+ deviceName,
503
+ isMobile: !!tagData.device
504
+ });
505
+ log.debug(`Resolved percyBrowserCustomName: ${percyBrowserCustomName}`);
442
506
  return {
443
507
  name: deviceName,
444
508
  osName,
@@ -448,7 +512,8 @@ export default class GenericProvider {
448
512
  orientation,
449
513
  browserName,
450
514
  browserVersion,
451
- resolution
515
+ resolution,
516
+ percyBrowserCustomName
452
517
  };
453
518
  }
454
519
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@percy/webdriver-utils",
3
- "version": "1.31.5",
3
+ "version": "1.31.6-beta.5",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",
@@ -9,7 +9,7 @@
9
9
  },
10
10
  "publishConfig": {
11
11
  "access": "public",
12
- "tag": "latest"
12
+ "tag": "beta"
13
13
  },
14
14
  "engines": {
15
15
  "node": ">=14"
@@ -29,8 +29,8 @@
29
29
  "test:coverage": "yarn test --coverage"
30
30
  },
31
31
  "dependencies": {
32
- "@percy/config": "1.31.5",
33
- "@percy/sdk-utils": "1.31.5"
32
+ "@percy/config": "1.31.6-beta.5",
33
+ "@percy/sdk-utils": "1.31.6-beta.5"
34
34
  },
35
- "gitHead": "835297c48a25843d8c719d6b476134c603721d13"
35
+ "gitHead": "fbcc28ce81ae902a32a5856c46efa0de6ae19300"
36
36
  }