@percy/core 1.28.2-beta.1 → 1.28.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/dist/config.js +19 -0
- package/dist/discovery.js +40 -31
- package/dist/network.js +10 -1
- package/dist/queue.js +7 -1
- package/dist/snapshot.js +2 -1
- package/dist/utils.js +23 -0
- package/package.json +8 -8
package/dist/config.js
CHANGED
|
@@ -74,6 +74,9 @@ export const configSchema = {
|
|
|
74
74
|
testCase: {
|
|
75
75
|
type: 'string'
|
|
76
76
|
},
|
|
77
|
+
thTestCaseExecutionId: {
|
|
78
|
+
type: 'string'
|
|
79
|
+
},
|
|
77
80
|
fullPage: {
|
|
78
81
|
type: 'boolean',
|
|
79
82
|
onlyAutomate: true
|
|
@@ -255,6 +258,10 @@ export const configSchema = {
|
|
|
255
258
|
type: 'integer',
|
|
256
259
|
minimum: 1
|
|
257
260
|
},
|
|
261
|
+
retry: {
|
|
262
|
+
type: 'boolean',
|
|
263
|
+
default: false
|
|
264
|
+
},
|
|
258
265
|
launchOptions: {
|
|
259
266
|
type: 'object',
|
|
260
267
|
additionalProperties: false,
|
|
@@ -321,6 +328,9 @@ export const snapshotSchema = {
|
|
|
321
328
|
testCase: {
|
|
322
329
|
$ref: '/config/snapshot#/properties/testCase'
|
|
323
330
|
},
|
|
331
|
+
thTestCaseExecutionId: {
|
|
332
|
+
$ref: '/config/snapshot#/properties/thTestCaseExecutionId'
|
|
333
|
+
},
|
|
324
334
|
reshuffleInvalidTags: {
|
|
325
335
|
$ref: '/config/snapshot#/properties/reshuffleInvalidTags'
|
|
326
336
|
},
|
|
@@ -357,6 +367,9 @@ export const snapshotSchema = {
|
|
|
357
367
|
},
|
|
358
368
|
devicePixelRatio: {
|
|
359
369
|
$ref: '/config/discovery#/properties/devicePixelRatio'
|
|
370
|
+
},
|
|
371
|
+
retry: {
|
|
372
|
+
$ref: '/config/discovery#/properties/retry'
|
|
360
373
|
}
|
|
361
374
|
}
|
|
362
375
|
}
|
|
@@ -725,6 +738,12 @@ export const comparisonSchema = {
|
|
|
725
738
|
sync: {
|
|
726
739
|
type: 'boolean'
|
|
727
740
|
},
|
|
741
|
+
testCase: {
|
|
742
|
+
type: 'string'
|
|
743
|
+
},
|
|
744
|
+
thTestCaseExecutionId: {
|
|
745
|
+
type: 'string'
|
|
746
|
+
},
|
|
728
747
|
metadata: {
|
|
729
748
|
type: 'object',
|
|
730
749
|
additionalProperties: false,
|
package/dist/discovery.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import logger from '@percy/logger';
|
|
2
2
|
import Queue from './queue.js';
|
|
3
|
-
import { normalizeURL, hostnameMatches, createResource, createRootResource, createPercyCSSResource, createLogResource, yieldAll, snapshotLogName } from './utils.js';
|
|
3
|
+
import { normalizeURL, hostnameMatches, createResource, createRootResource, createPercyCSSResource, createLogResource, yieldAll, snapshotLogName, withRetries } from './utils.js';
|
|
4
4
|
|
|
5
5
|
// Logs verbose debug logs detailing various snapshot options.
|
|
6
6
|
function debugSnapshotOptions(snapshot) {
|
|
@@ -340,40 +340,49 @@ export function createDiscoveryQueue(percy) {
|
|
|
340
340
|
/* istanbul ignore next: tested, but coverage is stripped */
|
|
341
341
|
let assetDiscoveryPageEnableJS = snapshot.cliEnableJavaScript && !snapshot.domSnapshot || (snapshot.enableJavaScript ?? !snapshot.domSnapshot);
|
|
342
342
|
percy.log.debug(`Asset discovery Browser Page enable JS: ${assetDiscoveryPageEnableJS}`);
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
343
|
+
await withRetries(async function* () {
|
|
344
|
+
// create a new browser page
|
|
345
|
+
let page = yield percy.browser.page({
|
|
346
|
+
enableJavaScript: assetDiscoveryPageEnableJS,
|
|
347
|
+
networkIdleTimeout: snapshot.discovery.networkIdleTimeout,
|
|
348
|
+
requestHeaders: snapshot.discovery.requestHeaders,
|
|
349
|
+
authorization: snapshot.discovery.authorization,
|
|
350
|
+
userAgent: snapshot.discovery.userAgent,
|
|
351
|
+
captureMockedServiceWorker: snapshot.discovery.captureMockedServiceWorker,
|
|
352
|
+
meta: snapshot.meta,
|
|
353
|
+
// enable network inteception
|
|
354
|
+
intercept: {
|
|
355
|
+
enableJavaScript: snapshot.enableJavaScript,
|
|
356
|
+
disableCache: snapshot.discovery.disableCache,
|
|
357
|
+
allowedHostnames: snapshot.discovery.allowedHostnames,
|
|
358
|
+
disallowedHostnames: snapshot.discovery.disallowedHostnames,
|
|
359
|
+
getResource: u => snapshot.resources.get(u) || cache.get(u),
|
|
360
|
+
saveResource: r => {
|
|
361
|
+
snapshot.resources.set(r.url, r);
|
|
362
|
+
if (!r.root) {
|
|
363
|
+
cache.set(r.url, r);
|
|
364
|
+
}
|
|
363
365
|
}
|
|
364
366
|
}
|
|
367
|
+
});
|
|
368
|
+
try {
|
|
369
|
+
yield* captureSnapshotResources(page, snapshot, {
|
|
370
|
+
captureWidths: !snapshot.domSnapshot && percy.deferUploads,
|
|
371
|
+
capture: callback,
|
|
372
|
+
captureForDevices: percy.deviceDetails || []
|
|
373
|
+
});
|
|
374
|
+
} finally {
|
|
375
|
+
// always close the page when done
|
|
376
|
+
await page.close();
|
|
365
377
|
}
|
|
378
|
+
}, {
|
|
379
|
+
count: snapshot.discovery.retry ? 3 : 1,
|
|
380
|
+
onRetry: () => {
|
|
381
|
+
percy.log.info(`Retrying snapshot: ${snapshotLogName(snapshot.name, snapshot.meta)}`, snapshot.meta);
|
|
382
|
+
},
|
|
383
|
+
signal: snapshot._ctrl.signal,
|
|
384
|
+
throwOn: ['AbortError']
|
|
366
385
|
});
|
|
367
|
-
try {
|
|
368
|
-
yield* captureSnapshotResources(page, snapshot, {
|
|
369
|
-
captureWidths: !snapshot.domSnapshot && percy.deferUploads,
|
|
370
|
-
capture: callback,
|
|
371
|
-
captureForDevices: percy.deviceDetails || []
|
|
372
|
-
});
|
|
373
|
-
} finally {
|
|
374
|
-
// always close the page when done
|
|
375
|
-
await page.close();
|
|
376
|
-
}
|
|
377
386
|
}).handle('error', ({
|
|
378
387
|
name,
|
|
379
388
|
meta
|
package/dist/network.js
CHANGED
|
@@ -28,6 +28,7 @@ export class Network {
|
|
|
28
28
|
#requests = new Map();
|
|
29
29
|
#authentications = new Set();
|
|
30
30
|
#aborted = new Set();
|
|
31
|
+
#finishedUrls = new Set();
|
|
31
32
|
constructor(page, options) {
|
|
32
33
|
this.page = page;
|
|
33
34
|
this.timeout = options.networkIdleTimeout ?? 100;
|
|
@@ -78,6 +79,12 @@ export class Network {
|
|
|
78
79
|
throw new Error(`Network error: ${this.page.session.closedReason}`);
|
|
79
80
|
}
|
|
80
81
|
requests = Array.from(this.#requests.values()).filter(filter);
|
|
82
|
+
// remove requests which are finished at least once
|
|
83
|
+
// this happens when same request is made multiple times by browser in parallel and one of
|
|
84
|
+
// them gets stuck in pending state in browser [ need to debug why ]. So we dont receive
|
|
85
|
+
// loadingFinished event, causing it to show up in Active requests, but we can only store one
|
|
86
|
+
// response per url so as long as we have captured one, we dont care about other such requests
|
|
87
|
+
requests = requests.filter(req => !this.#finishedUrls.has(req.url));
|
|
81
88
|
return requests.length === 0;
|
|
82
89
|
}, {
|
|
83
90
|
timeout: Network.TIMEOUT,
|
|
@@ -120,10 +127,12 @@ export class Network {
|
|
|
120
127
|
// Called when a request should be removed from various trackers
|
|
121
128
|
_forgetRequest({
|
|
122
129
|
requestId,
|
|
123
|
-
interceptId
|
|
130
|
+
interceptId,
|
|
131
|
+
url
|
|
124
132
|
}, keepPending) {
|
|
125
133
|
this.#requests.delete(requestId);
|
|
126
134
|
this.#authentications.delete(interceptId);
|
|
135
|
+
this.#finishedUrls.add(url);
|
|
127
136
|
if (!keepPending) {
|
|
128
137
|
this.#pending.delete(requestId);
|
|
129
138
|
}
|
package/dist/queue.js
CHANGED
|
@@ -122,9 +122,15 @@ export class Queue {
|
|
|
122
122
|
|
|
123
123
|
// call or set up other handlers
|
|
124
124
|
let exists = this.cancel(item);
|
|
125
|
+
task.ctrl = new AbortController();
|
|
126
|
+
// duplicate abortion controller on task, so it can can be used in further
|
|
127
|
+
// generators and can be cancelled internally
|
|
128
|
+
// TODO fix this for non object item usecase
|
|
129
|
+
if (typeof item === 'object' && !Array.isArray(item) && item !== null) {
|
|
130
|
+
item._ctrl = task.ctrl;
|
|
131
|
+
}
|
|
125
132
|
task.item = item = _classPrivateFieldGet(this, _handlers).push ? _classPrivateFieldGet(this, _handlers).push(item, exists) : item;
|
|
126
133
|
task.handler = () => _classPrivateFieldGet(this, _handlers).task ? _classPrivateFieldGet(this, _handlers).task(item, ...args) : item;
|
|
127
|
-
task.ctrl = new AbortController();
|
|
128
134
|
|
|
129
135
|
// queue this task & maybe dequeue the next task
|
|
130
136
|
_classPrivateFieldGet(this, _queued).add(task);
|
package/dist/snapshot.js
CHANGED
|
@@ -129,7 +129,8 @@ function getSnapshotOptions(options, {
|
|
|
129
129
|
disableCache: config.discovery.disableCache,
|
|
130
130
|
captureMockedServiceWorker: config.discovery.captureMockedServiceWorker,
|
|
131
131
|
captureSrcset: config.discovery.captureSrcset,
|
|
132
|
-
userAgent: config.discovery.userAgent
|
|
132
|
+
userAgent: config.discovery.userAgent,
|
|
133
|
+
retry: config.discovery.retry
|
|
133
134
|
}
|
|
134
135
|
}, options], (path, prev, next) => {
|
|
135
136
|
var _next, _next2;
|
package/dist/utils.js
CHANGED
|
@@ -328,6 +328,29 @@ export function serializeFunction(fn) {
|
|
|
328
328
|
}
|
|
329
329
|
return fnbody;
|
|
330
330
|
}
|
|
331
|
+
export async function withRetries(fn, {
|
|
332
|
+
count,
|
|
333
|
+
onRetry,
|
|
334
|
+
signal,
|
|
335
|
+
throwOn
|
|
336
|
+
}) {
|
|
337
|
+
count || (count = 1); // default a single try
|
|
338
|
+
let run = 0;
|
|
339
|
+
while (true) {
|
|
340
|
+
run += 1;
|
|
341
|
+
try {
|
|
342
|
+
return await generatePromise(fn, signal);
|
|
343
|
+
} catch (e) {
|
|
344
|
+
// if this error should not be retried on, we want to skip errors
|
|
345
|
+
let throwError = throwOn === null || throwOn === void 0 ? void 0 : throwOn.includes(e.name);
|
|
346
|
+
if (!throwError && run < count) {
|
|
347
|
+
await (onRetry === null || onRetry === void 0 ? void 0 : onRetry());
|
|
348
|
+
continue;
|
|
349
|
+
}
|
|
350
|
+
throw e;
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
}
|
|
331
354
|
export function snapshotLogName(name, meta) {
|
|
332
355
|
var _meta$snapshot;
|
|
333
356
|
if (meta !== null && meta !== void 0 && (_meta$snapshot = meta.snapshot) !== null && _meta$snapshot !== void 0 && _meta$snapshot.testCase) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@percy/core",
|
|
3
|
-
"version": "1.28.2
|
|
3
|
+
"version": "1.28.2",
|
|
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": "
|
|
12
|
+
"tag": "latest"
|
|
13
13
|
},
|
|
14
14
|
"engines": {
|
|
15
15
|
"node": ">=14"
|
|
@@ -43,11 +43,11 @@
|
|
|
43
43
|
"test:types": "tsd"
|
|
44
44
|
},
|
|
45
45
|
"dependencies": {
|
|
46
|
-
"@percy/client": "1.28.2
|
|
47
|
-
"@percy/config": "1.28.2
|
|
48
|
-
"@percy/dom": "1.28.2
|
|
49
|
-
"@percy/logger": "1.28.2
|
|
50
|
-
"@percy/webdriver-utils": "1.28.2
|
|
46
|
+
"@percy/client": "1.28.2",
|
|
47
|
+
"@percy/config": "1.28.2",
|
|
48
|
+
"@percy/dom": "1.28.2",
|
|
49
|
+
"@percy/logger": "1.28.2",
|
|
50
|
+
"@percy/webdriver-utils": "1.28.2",
|
|
51
51
|
"content-disposition": "^0.5.4",
|
|
52
52
|
"cross-spawn": "^7.0.3",
|
|
53
53
|
"extract-zip": "^2.0.1",
|
|
@@ -58,5 +58,5 @@
|
|
|
58
58
|
"rimraf": "^3.0.2",
|
|
59
59
|
"ws": "^8.0.0"
|
|
60
60
|
},
|
|
61
|
-
"gitHead": "
|
|
61
|
+
"gitHead": "88105fef569632b816955fcd1320bcc4b218bf67"
|
|
62
62
|
}
|