@percy/core 1.28.1-alpha.1 → 1.28.1-alpha.3
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 +10 -0
- package/dist/discovery.js +47 -36
- package/dist/queue.js +7 -1
- package/dist/snapshot.js +9 -7
- package/dist/utils.js +30 -0
- package/package.json +7 -7
package/dist/config.js
CHANGED
|
@@ -71,6 +71,9 @@ export const configSchema = {
|
|
|
71
71
|
sync: {
|
|
72
72
|
type: 'boolean'
|
|
73
73
|
},
|
|
74
|
+
testCase: {
|
|
75
|
+
type: 'string'
|
|
76
|
+
},
|
|
74
77
|
fullPage: {
|
|
75
78
|
type: 'boolean',
|
|
76
79
|
onlyAutomate: true
|
|
@@ -249,6 +252,10 @@ export const configSchema = {
|
|
|
249
252
|
type: 'integer',
|
|
250
253
|
minimum: 1
|
|
251
254
|
},
|
|
255
|
+
retry: {
|
|
256
|
+
type: 'boolean',
|
|
257
|
+
default: false
|
|
258
|
+
},
|
|
252
259
|
launchOptions: {
|
|
253
260
|
type: 'object',
|
|
254
261
|
additionalProperties: false,
|
|
@@ -312,6 +319,9 @@ export const snapshotSchema = {
|
|
|
312
319
|
sync: {
|
|
313
320
|
$ref: '/config/snapshot#/properties/sync'
|
|
314
321
|
},
|
|
322
|
+
testCase: {
|
|
323
|
+
$ref: '/config/snapshot#/properties/testCase'
|
|
324
|
+
},
|
|
315
325
|
reshuffleInvalidTags: {
|
|
316
326
|
$ref: '/config/snapshot#/properties/reshuffleInvalidTags'
|
|
317
327
|
},
|
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 } 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) {
|
|
@@ -139,8 +139,8 @@ function processSnapshotResources({
|
|
|
139
139
|
|
|
140
140
|
// include associated snapshot logs matched by meta information
|
|
141
141
|
resources.push(createLogResource(logger.query(log => {
|
|
142
|
-
var _log$meta$snapshot;
|
|
143
|
-
return ((_log$meta$snapshot = log.meta.snapshot) === null || _log$meta$snapshot === void 0 ? void 0 : _log$meta$snapshot.name) === snapshot.meta.snapshot.name;
|
|
142
|
+
var _log$meta$snapshot, _log$meta$snapshot2;
|
|
143
|
+
return ((_log$meta$snapshot = log.meta.snapshot) === null || _log$meta$snapshot === void 0 ? void 0 : _log$meta$snapshot.testCase) === snapshot.meta.snapshot.testCase && ((_log$meta$snapshot2 = log.meta.snapshot) === null || _log$meta$snapshot2 === void 0 ? void 0 : _log$meta$snapshot2.name) === snapshot.meta.snapshot.name;
|
|
144
144
|
})));
|
|
145
145
|
return {
|
|
146
146
|
...snapshot,
|
|
@@ -279,7 +279,8 @@ export const RESOURCE_CACHE_KEY = Symbol('resource-cache');
|
|
|
279
279
|
// snapshot which is used to intercept and capture snapshot resource requests.
|
|
280
280
|
export function createDiscoveryQueue(percy) {
|
|
281
281
|
let {
|
|
282
|
-
concurrency
|
|
282
|
+
concurrency,
|
|
283
|
+
retry
|
|
283
284
|
} = percy.config.discovery;
|
|
284
285
|
let queue = new Queue('discovery');
|
|
285
286
|
let cache;
|
|
@@ -296,11 +297,12 @@ export function createDiscoveryQueue(percy) {
|
|
|
296
297
|
.handle('end', async () => {
|
|
297
298
|
await percy.browser.close();
|
|
298
299
|
})
|
|
299
|
-
// snapshots are unique by name; when deferred also by widths
|
|
300
|
+
// snapshots are unique by name and testCase; when deferred also by widths
|
|
300
301
|
.handle('find', ({
|
|
301
302
|
name,
|
|
303
|
+
testCase,
|
|
302
304
|
widths
|
|
303
|
-
}, snapshot) => snapshot.name === name && (!percy.deferUploads || !widths || widths.join() === snapshot.widths.join()))
|
|
305
|
+
}, snapshot) => snapshot.testCase === testCase && snapshot.name === name && (!percy.deferUploads || !widths || widths.join() === snapshot.widths.join()))
|
|
304
306
|
// initialize the resources for DOM snapshots
|
|
305
307
|
.handle('push', snapshot => {
|
|
306
308
|
let resources = parseDomResources(snapshot);
|
|
@@ -317,46 +319,55 @@ export function createDiscoveryQueue(percy) {
|
|
|
317
319
|
/* istanbul ignore next: tested, but coverage is stripped */
|
|
318
320
|
let assetDiscoveryPageEnableJS = snapshot.cliEnableJavaScript && !snapshot.domSnapshot || (snapshot.enableJavaScript ?? !snapshot.domSnapshot);
|
|
319
321
|
percy.log.debug(`Asset discovery Browser Page enable JS: ${assetDiscoveryPageEnableJS}`);
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
322
|
+
await withRetries(async function* () {
|
|
323
|
+
// create a new browser page
|
|
324
|
+
let page = yield percy.browser.page({
|
|
325
|
+
enableJavaScript: assetDiscoveryPageEnableJS,
|
|
326
|
+
networkIdleTimeout: snapshot.discovery.networkIdleTimeout,
|
|
327
|
+
requestHeaders: snapshot.discovery.requestHeaders,
|
|
328
|
+
authorization: snapshot.discovery.authorization,
|
|
329
|
+
userAgent: snapshot.discovery.userAgent,
|
|
330
|
+
captureMockedServiceWorker: snapshot.discovery.captureMockedServiceWorker,
|
|
331
|
+
meta: snapshot.meta,
|
|
332
|
+
// enable network inteception
|
|
333
|
+
intercept: {
|
|
334
|
+
enableJavaScript: snapshot.enableJavaScript,
|
|
335
|
+
disableCache: snapshot.discovery.disableCache,
|
|
336
|
+
allowedHostnames: snapshot.discovery.allowedHostnames,
|
|
337
|
+
disallowedHostnames: snapshot.discovery.disallowedHostnames,
|
|
338
|
+
getResource: u => snapshot.resources.get(u) || cache.get(u),
|
|
339
|
+
saveResource: r => {
|
|
340
|
+
snapshot.resources.set(r.url, r);
|
|
341
|
+
if (!r.root) {
|
|
342
|
+
cache.set(r.url, r);
|
|
343
|
+
}
|
|
340
344
|
}
|
|
341
345
|
}
|
|
346
|
+
});
|
|
347
|
+
try {
|
|
348
|
+
yield* captureSnapshotResources(page, snapshot, {
|
|
349
|
+
captureWidths: !snapshot.domSnapshot && percy.deferUploads,
|
|
350
|
+
capture: callback
|
|
351
|
+
});
|
|
352
|
+
} finally {
|
|
353
|
+
// always close the page when done
|
|
354
|
+
await page.close();
|
|
342
355
|
}
|
|
356
|
+
}, {
|
|
357
|
+
count: retry ? 3 : 1,
|
|
358
|
+
onRetry: () => {
|
|
359
|
+
percy.log.info(`Retrying snapshot: ${snapshotLogName(snapshot.name, snapshot.meta)}`, snapshot.meta);
|
|
360
|
+
},
|
|
361
|
+
signal: snapshot._ctrl.signal,
|
|
362
|
+
throwOn: ['AbortError']
|
|
343
363
|
});
|
|
344
|
-
try {
|
|
345
|
-
yield* captureSnapshotResources(page, snapshot, {
|
|
346
|
-
captureWidths: !snapshot.domSnapshot && percy.deferUploads,
|
|
347
|
-
capture: callback
|
|
348
|
-
});
|
|
349
|
-
} finally {
|
|
350
|
-
// always close the page when done
|
|
351
|
-
await page.close();
|
|
352
|
-
}
|
|
353
364
|
}).handle('error', ({
|
|
354
365
|
name,
|
|
355
366
|
meta
|
|
356
367
|
}, error) => {
|
|
357
368
|
if (error.name === 'AbortError' && queue.readyState < 3) {
|
|
358
369
|
// only error about aborted snapshots when not closed
|
|
359
|
-
percy.log.error('Received a duplicate snapshot, ' + `the previous snapshot was aborted: ${name}`, meta);
|
|
370
|
+
percy.log.error('Received a duplicate snapshot, ' + `the previous snapshot was aborted: ${snapshotLogName(name, meta)}`, meta);
|
|
360
371
|
} else {
|
|
361
372
|
// log all other encountered errors
|
|
362
373
|
percy.log.error(`Encountered an error taking snapshot: ${name}`, meta);
|
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
|
@@ -3,7 +3,7 @@ import PercyConfig from '@percy/config';
|
|
|
3
3
|
import micromatch from 'micromatch';
|
|
4
4
|
import { configSchema } from './config.js';
|
|
5
5
|
import Queue from './queue.js';
|
|
6
|
-
import { request, hostnameMatches, yieldTo } from './utils.js';
|
|
6
|
+
import { request, hostnameMatches, yieldTo, snapshotLogName } from './utils.js';
|
|
7
7
|
import { JobData } from './wait-for-job.js';
|
|
8
8
|
|
|
9
9
|
// Throw a better error message for missing or invalid urls
|
|
@@ -113,7 +113,8 @@ function getSnapshotOptions(options, {
|
|
|
113
113
|
meta: {
|
|
114
114
|
...meta,
|
|
115
115
|
snapshot: {
|
|
116
|
-
name: options.name
|
|
116
|
+
name: options.name,
|
|
117
|
+
testCase: options.testCase
|
|
117
118
|
}
|
|
118
119
|
}
|
|
119
120
|
}, config.snapshot, {
|
|
@@ -391,10 +392,11 @@ export function createSnapshotsQueue(percy) {
|
|
|
391
392
|
});
|
|
392
393
|
}
|
|
393
394
|
})
|
|
394
|
-
// snapshots are unique by name
|
|
395
|
+
// snapshots are unique by name and testCase both
|
|
395
396
|
.handle('find', ({
|
|
396
|
-
name
|
|
397
|
-
|
|
397
|
+
name,
|
|
398
|
+
testCase
|
|
399
|
+
}, snapshot) => snapshot.testCase === testCase && snapshot.name === name)
|
|
398
400
|
// when pushed, maybe flush old snapshots or possibly merge with existing snapshots
|
|
399
401
|
.handle('push', (snapshot, existing) => {
|
|
400
402
|
let {
|
|
@@ -403,8 +405,8 @@ export function createSnapshotsQueue(percy) {
|
|
|
403
405
|
} = snapshot;
|
|
404
406
|
|
|
405
407
|
// log immediately when not deferred or dry-running
|
|
406
|
-
if (!percy.deferUploads) percy.log.info(`Snapshot taken: ${name}`, meta);
|
|
407
|
-
if (percy.dryRun) percy.log.info(`Snapshot found: ${name}`, meta);
|
|
408
|
+
if (!percy.deferUploads) percy.log.info(`Snapshot taken: ${snapshotLogName(name, meta)}`, meta);
|
|
409
|
+
if (percy.dryRun) percy.log.info(`Snapshot found: ${snapshotLogName(name, meta)}`, meta);
|
|
408
410
|
|
|
409
411
|
// immediately flush when uploads are delayed but not skipped
|
|
410
412
|
if (percy.delayUploads && !percy.deferUploads) queue.flush();
|
package/dist/utils.js
CHANGED
|
@@ -328,6 +328,36 @@ 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
|
+
}
|
|
354
|
+
export function snapshotLogName(name, meta) {
|
|
355
|
+
var _meta$snapshot;
|
|
356
|
+
if (meta !== null && meta !== void 0 && (_meta$snapshot = meta.snapshot) !== null && _meta$snapshot !== void 0 && _meta$snapshot.testCase) {
|
|
357
|
+
return `testCase: ${meta.snapshot.testCase}, ${name}`;
|
|
358
|
+
}
|
|
359
|
+
return name;
|
|
360
|
+
}
|
|
331
361
|
|
|
332
362
|
// DefaultMap, which returns a default value for an uninitialized key
|
|
333
363
|
// Similar to defaultDict in python
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@percy/core",
|
|
3
|
-
"version": "1.28.1-alpha.
|
|
3
|
+
"version": "1.28.1-alpha.3",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -43,11 +43,11 @@
|
|
|
43
43
|
"test:types": "tsd"
|
|
44
44
|
},
|
|
45
45
|
"dependencies": {
|
|
46
|
-
"@percy/client": "1.28.1-alpha.
|
|
47
|
-
"@percy/config": "1.28.1-alpha.
|
|
48
|
-
"@percy/dom": "1.28.1-alpha.
|
|
49
|
-
"@percy/logger": "1.28.1-alpha.
|
|
50
|
-
"@percy/webdriver-utils": "1.28.1-alpha.
|
|
46
|
+
"@percy/client": "1.28.1-alpha.3",
|
|
47
|
+
"@percy/config": "1.28.1-alpha.3",
|
|
48
|
+
"@percy/dom": "1.28.1-alpha.3",
|
|
49
|
+
"@percy/logger": "1.28.1-alpha.3",
|
|
50
|
+
"@percy/webdriver-utils": "1.28.1-alpha.3",
|
|
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": "46d1e874e1092fee45899d70cd97cf793db17de5"
|
|
62
62
|
}
|