@percy/core 1.6.4 → 1.7.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/percy.js +16 -18
- package/dist/snapshot.js +7 -8
- package/dist/utils.js +38 -5
- package/package.json +6 -6
package/dist/percy.js
CHANGED
|
@@ -5,7 +5,7 @@ import Queue from './queue.js';
|
|
|
5
5
|
import Browser from './browser.js';
|
|
6
6
|
import { createPercyServer, createStaticServer } from './api.js';
|
|
7
7
|
import { gatherSnapshots, validateSnapshotOptions, discoverSnapshotResources } from './snapshot.js';
|
|
8
|
-
import { generatePromise } from './utils.js'; // A Percy instance will create a new build when started, handle snapshot
|
|
8
|
+
import { generatePromise, yieldAll } from './utils.js'; // A Percy instance will create a new build when started, handle snapshot
|
|
9
9
|
// creation, asset discovery, and resource uploads, and will finalize the build
|
|
10
10
|
// when stopped. Snapshots are processed concurrently and the build is not
|
|
11
11
|
// finalized until all snapshots have been handled.
|
|
@@ -69,10 +69,6 @@ export class Percy {
|
|
|
69
69
|
this.#snapshots.concurrency = concurrency;
|
|
70
70
|
}
|
|
71
71
|
|
|
72
|
-
if (this.delayUploads) {
|
|
73
|
-
this.#uploads.concurrency = 1;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
72
|
this.client = new PercyClient({
|
|
77
73
|
token,
|
|
78
74
|
clientInfo,
|
|
@@ -162,17 +158,20 @@ export class Percy {
|
|
|
162
158
|
let buildTask = this.#uploads.push('build/create', () => {
|
|
163
159
|
// pause other queued tasks until after the build is created
|
|
164
160
|
this.#uploads.stop();
|
|
161
|
+
this.build = {};
|
|
165
162
|
return this.client.createBuild().then(({
|
|
166
163
|
data: {
|
|
167
164
|
id,
|
|
168
165
|
attributes
|
|
169
166
|
}
|
|
170
167
|
}) => {
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
168
|
+
let url = attributes['web-url'];
|
|
169
|
+
let number = attributes['build-number'];
|
|
170
|
+
Object.assign(this.build, {
|
|
171
|
+
id,
|
|
172
|
+
url,
|
|
173
|
+
number
|
|
174
|
+
});
|
|
176
175
|
if (!this.delayUploads) this.#uploads.run();
|
|
177
176
|
});
|
|
178
177
|
}, 0); // handle deferred build errors
|
|
@@ -246,6 +245,7 @@ export class Percy {
|
|
|
246
245
|
if (close) this.#uploads.close(); // prevent creating an empty build when deferred
|
|
247
246
|
|
|
248
247
|
if (!this.deferUploads || !this.#uploads.has('build/create') || this.#uploads.size > 1) {
|
|
248
|
+
if (this.build && !this.build.id) yield* this.#uploads.idle();
|
|
249
249
|
yield* this.#uploads.flush(s => {
|
|
250
250
|
// do not log a count when not closing or while creating a build
|
|
251
251
|
if (!close || this.#uploads.has('build/create')) return;
|
|
@@ -371,7 +371,7 @@ export class Percy {
|
|
|
371
371
|
} else if ((_this$build3 = this.build) !== null && _this$build3 !== void 0 && _this$build3.error) {
|
|
372
372
|
throw new Error(this.build.error);
|
|
373
373
|
} else if (Array.isArray(options)) {
|
|
374
|
-
return
|
|
374
|
+
return yieldAll(options.map(o => this.yield.snapshot(o)));
|
|
375
375
|
}
|
|
376
376
|
|
|
377
377
|
if (typeof options === 'string') {
|
|
@@ -398,13 +398,11 @@ export class Percy {
|
|
|
398
398
|
} // gather snapshots from options
|
|
399
399
|
|
|
400
400
|
|
|
401
|
-
let snapshots = yield gatherSnapshots(this, options);
|
|
401
|
+
let snapshots = yield* gatherSnapshots(this, options);
|
|
402
402
|
|
|
403
403
|
try {
|
|
404
|
-
//
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
for (let task of tasks) yield task;
|
|
404
|
+
// use a try-catch to cancel snapshots that haven't started when the error occurred
|
|
405
|
+
yield* yieldAll(snapshots.map(s => this._takeSnapshot(s)));
|
|
408
406
|
} catch (error) {
|
|
409
407
|
// cancel queued snapshots that may not have started
|
|
410
408
|
snapshots.map(s => this._cancelSnapshot(s));
|
|
@@ -458,10 +456,10 @@ export class Percy {
|
|
|
458
456
|
|
|
459
457
|
if ((_this$build4 = this.build) !== null && _this$build4 !== void 0 && _this$build4.error) throw new Error(this.build.error); // maybe process any existing delayed uploads
|
|
460
458
|
|
|
461
|
-
if (!this.skipUploads && this.delayUploads) this.#uploads.run();
|
|
459
|
+
if (!this.skipUploads && this.delayUploads && (!this.build || this.build.id)) this.#uploads.run();
|
|
462
460
|
return this.#uploads.push(`upload/${name}`, async () => {
|
|
463
461
|
// when delayed, stop the queue before other uploads are processed
|
|
464
|
-
if (this.delayUploads) this.#uploads.stop();
|
|
462
|
+
if (this.readyState < 2 && this.delayUploads) this.#uploads.stop();
|
|
465
463
|
|
|
466
464
|
try {
|
|
467
465
|
/* istanbul ignore if: useful for other internal packages */
|
package/dist/snapshot.js
CHANGED
|
@@ -2,7 +2,7 @@ import logger from '@percy/logger';
|
|
|
2
2
|
import PercyConfig from '@percy/config';
|
|
3
3
|
import micromatch from 'micromatch';
|
|
4
4
|
import { configSchema } from './config.js';
|
|
5
|
-
import { request, hostnameMatches, createRootResource, createPercyCSSResource, createLogResource } from './utils.js'; // Throw a better error message for missing or invalid urls
|
|
5
|
+
import { request, hostnameMatches, createRootResource, createPercyCSSResource, createLogResource, yieldTo } from './utils.js'; // Throw a better error message for missing or invalid urls
|
|
6
6
|
|
|
7
7
|
export function validURL(url, base) {
|
|
8
8
|
if (!url) {
|
|
@@ -92,21 +92,20 @@ export function mapSnapshotOptions(percy, snapshots, config) {
|
|
|
92
92
|
}, []);
|
|
93
93
|
} // Returns an array of derived snapshot options
|
|
94
94
|
|
|
95
|
-
export async function gatherSnapshots(percy, options) {
|
|
95
|
+
export async function* gatherSnapshots(percy, options) {
|
|
96
96
|
let {
|
|
97
97
|
baseUrl,
|
|
98
98
|
snapshots
|
|
99
99
|
} = options;
|
|
100
100
|
if ('url' in options) snapshots = [options];
|
|
101
|
-
if ('sitemap' in options) snapshots =
|
|
101
|
+
if ('sitemap' in options) snapshots = yield getSitemapSnapshots(options); // validate evaluated snapshots
|
|
102
102
|
|
|
103
103
|
if (typeof snapshots === 'function') {
|
|
104
|
-
(
|
|
105
|
-
|
|
106
|
-
} = validateSnapshotOptions({
|
|
104
|
+
snapshots = yield* yieldTo(snapshots(baseUrl));
|
|
105
|
+
snapshots = validateSnapshotOptions({
|
|
107
106
|
baseUrl,
|
|
108
|
-
snapshots
|
|
109
|
-
})
|
|
107
|
+
snapshots
|
|
108
|
+
}).snapshots;
|
|
110
109
|
} // map snapshots with snapshot options
|
|
111
110
|
|
|
112
111
|
|
package/dist/utils.js
CHANGED
|
@@ -46,23 +46,25 @@ export function createPercyCSSResource(url, css) {
|
|
|
46
46
|
|
|
47
47
|
export function createLogResource(logs) {
|
|
48
48
|
return createResource(`/percy.${Date.now()}.log`, JSON.stringify(logs), 'text/plain');
|
|
49
|
+
} // Returns true or false if the provided object is a generator or not
|
|
50
|
+
|
|
51
|
+
export function isGenerator(subject) {
|
|
52
|
+
return typeof (subject === null || subject === void 0 ? void 0 : subject.next) === 'function' && (typeof subject[Symbol.iterator] === 'function' || typeof subject[Symbol.asyncIterator] === 'function');
|
|
49
53
|
} // Iterates over the provided generator and resolves to the final value when done. With an
|
|
50
54
|
// AbortSignal, the generator will throw with the abort reason when aborted. Also accepts an
|
|
51
55
|
// optional node-style callback, called before the returned promise resolves.
|
|
52
56
|
|
|
53
57
|
export async function generatePromise(gen, signal, cb) {
|
|
54
58
|
try {
|
|
55
|
-
var _gen;
|
|
56
|
-
|
|
57
59
|
if (typeof signal === 'function') [cb, signal] = [signal];
|
|
58
60
|
if (typeof gen === 'function') gen = await gen();
|
|
59
61
|
let {
|
|
60
62
|
done,
|
|
61
63
|
value
|
|
62
|
-
} =
|
|
64
|
+
} = !isGenerator(gen) ? {
|
|
63
65
|
done: true,
|
|
64
66
|
value: await gen
|
|
65
|
-
};
|
|
67
|
+
} : await gen.next();
|
|
66
68
|
|
|
67
69
|
while (!done) {
|
|
68
70
|
var _signal;
|
|
@@ -103,6 +105,37 @@ export class AbortError extends Error {
|
|
|
103
105
|
});
|
|
104
106
|
}
|
|
105
107
|
|
|
108
|
+
} // An async generator that yields after every event loop until the promise settles
|
|
109
|
+
|
|
110
|
+
export async function* yieldTo(subject) {
|
|
111
|
+
// yield to any provided generator or return non-promise values
|
|
112
|
+
if (isGenerator(subject)) return yield* subject;
|
|
113
|
+
if (typeof (subject === null || subject === void 0 ? void 0 : subject.then) !== 'function') return subject; // update local variables with the provided promise
|
|
114
|
+
|
|
115
|
+
let result,
|
|
116
|
+
error,
|
|
117
|
+
pending = !!subject.then(r => result = r, e => error = e).finally(() => pending = false);
|
|
118
|
+
/* eslint-disable-next-line no-unmodified-loop-condition */
|
|
119
|
+
|
|
120
|
+
while (pending) yield new Promise(r => setImmediate(r));
|
|
121
|
+
|
|
122
|
+
if (error) throw error;
|
|
123
|
+
return result;
|
|
124
|
+
} // An async generator that runs provided generators concurrently
|
|
125
|
+
|
|
126
|
+
export async function* yieldAll(all) {
|
|
127
|
+
let res = new Array(all.length).fill();
|
|
128
|
+
all = all.map(yieldTo);
|
|
129
|
+
|
|
130
|
+
while (true) {
|
|
131
|
+
res = await Promise.all(all.map((g, i) => {
|
|
132
|
+
var _res$i, _res$i2;
|
|
133
|
+
|
|
134
|
+
return (_res$i = res[i]) !== null && _res$i !== void 0 && _res$i.done ? res[i] : g.next((_res$i2 = res[i]) === null || _res$i2 === void 0 ? void 0 : _res$i2.value);
|
|
135
|
+
}));
|
|
136
|
+
let vals = res.map(r => r === null || r === void 0 ? void 0 : r.value);
|
|
137
|
+
if (res.some(r => !(r !== null && r !== void 0 && r.done))) yield vals;else return vals;
|
|
138
|
+
}
|
|
106
139
|
} // An async generator that infinitely yields to the predicate function until a truthy value is
|
|
107
140
|
// returned. When a timeout is provided, an error will be thrown during the next iteration after the
|
|
108
141
|
// timeout has been exceeded. If an idle option is provided, the predicate will be yielded to a
|
|
@@ -207,7 +240,7 @@ export function serializeFunction(fn) {
|
|
|
207
240
|
} // wrap the function body with percy helpers
|
|
208
241
|
|
|
209
242
|
|
|
210
|
-
fnbody = 'function withPercyHelpers() {\n' + ['const { config, snapshot } = window.__PERCY__ ?? {};', `return (${fnbody})({`, ' config, snapshot, generatePromise, yieldFor,', ' waitFor, waitForTimeout, waitForSelector, waitForXPath,', ' scrollToBottom', '}, ...arguments);', `${generatePromise}`, `${yieldFor}`, `${waitFor}`, `${waitForTimeout}`, `${waitForSelector}`, `${waitForXPath}`, `${scrollToBottom}`].join('\n') + '\n}';
|
|
243
|
+
fnbody = 'function withPercyHelpers() {\n' + ['const { config, snapshot } = window.__PERCY__ ?? {};', `return (${fnbody})({`, ' config, snapshot, generatePromise, yieldFor,', ' waitFor, waitForTimeout, waitForSelector, waitForXPath,', ' scrollToBottom', '}, ...arguments);', `${isGenerator}`, `${generatePromise}`, `${yieldFor}`, `${waitFor}`, `${waitForTimeout}`, `${waitForSelector}`, `${waitForXPath}`, `${scrollToBottom}`].join('\n') + '\n}';
|
|
211
244
|
/* istanbul ignore else: ironic. */
|
|
212
245
|
|
|
213
246
|
if (fnbody.includes('cov_')) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@percy/core",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.7.2",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -39,10 +39,10 @@
|
|
|
39
39
|
"test:types": "tsd"
|
|
40
40
|
},
|
|
41
41
|
"dependencies": {
|
|
42
|
-
"@percy/client": "1.
|
|
43
|
-
"@percy/config": "1.
|
|
44
|
-
"@percy/dom": "1.
|
|
45
|
-
"@percy/logger": "1.
|
|
42
|
+
"@percy/client": "1.7.2",
|
|
43
|
+
"@percy/config": "1.7.2",
|
|
44
|
+
"@percy/dom": "1.7.2",
|
|
45
|
+
"@percy/logger": "1.7.2",
|
|
46
46
|
"content-disposition": "^0.5.4",
|
|
47
47
|
"cross-spawn": "^7.0.3",
|
|
48
48
|
"extract-zip": "^2.0.1",
|
|
@@ -53,5 +53,5 @@
|
|
|
53
53
|
"rimraf": "^3.0.2",
|
|
54
54
|
"ws": "^8.0.0"
|
|
55
55
|
},
|
|
56
|
-
"gitHead": "
|
|
56
|
+
"gitHead": "d9da4a4f9eafc3c3ac361a50f679f030172ad362"
|
|
57
57
|
}
|