@percy/core 1.27.7 → 1.28.0-beta.1
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/api.js +43 -13
- package/dist/browser.js +2 -2
- package/dist/config.js +9 -0
- package/dist/percy.js +44 -4
- package/dist/snapshot.js +26 -0
- package/dist/utils.js +1 -0
- package/dist/wait-for-job.js +97 -0
- package/package.json +8 -8
package/dist/api.js
CHANGED
|
@@ -5,6 +5,7 @@ import logger from '@percy/logger';
|
|
|
5
5
|
import { normalize } from '@percy/config/utils';
|
|
6
6
|
import { getPackageJSON, Server, percyAutomateRequestHandler, percyBuildEventHandler } from './utils.js';
|
|
7
7
|
import WebdriverUtils from '@percy/webdriver-utils';
|
|
8
|
+
import { handleSyncJob } from './snapshot.js';
|
|
8
9
|
// need require.resolve until import.meta.resolve can be transpiled
|
|
9
10
|
export const PERCY_DOM = createRequire(import.meta.url).resolve('@percy/dom');
|
|
10
11
|
|
|
@@ -99,16 +100,29 @@ export function createPercyServer(percy, port) {
|
|
|
99
100
|
})
|
|
100
101
|
// post one or more snapshots, optionally async
|
|
101
102
|
.route('post', '/percy/snapshot', async (req, res) => {
|
|
102
|
-
let
|
|
103
|
+
let data;
|
|
104
|
+
const snapshotPromise = {};
|
|
105
|
+
const snapshot = percy.snapshot(req.body, snapshotPromise);
|
|
103
106
|
if (!req.url.searchParams.has('async')) await snapshot;
|
|
107
|
+
if (percy.syncMode(req.body)) data = await handleSyncJob(snapshotPromise[req.body.name], percy, 'snapshot');
|
|
104
108
|
return res.json(200, {
|
|
105
|
-
success: true
|
|
109
|
+
success: true,
|
|
110
|
+
data: data
|
|
106
111
|
});
|
|
107
112
|
})
|
|
108
113
|
// post one or more comparisons, optionally waiting
|
|
109
114
|
.route('post', '/percy/comparison', async (req, res) => {
|
|
110
|
-
let
|
|
111
|
-
if (req.
|
|
115
|
+
let data;
|
|
116
|
+
if (percy.syncMode(req.body)) {
|
|
117
|
+
const snapshotPromise = new Promise((resolve, reject) => percy.upload(req.body, {
|
|
118
|
+
resolve,
|
|
119
|
+
reject
|
|
120
|
+
}));
|
|
121
|
+
data = await handleSyncJob(snapshotPromise, percy, 'comparison');
|
|
122
|
+
} else {
|
|
123
|
+
let upload = percy.upload(req.body);
|
|
124
|
+
if (req.url.searchParams.has('await')) await upload;
|
|
125
|
+
}
|
|
112
126
|
|
|
113
127
|
// generate and include one or more redirect links to comparisons
|
|
114
128
|
let link = ({
|
|
@@ -126,22 +140,38 @@ export function createPercyServer(percy, port) {
|
|
|
126
140
|
snake: true
|
|
127
141
|
}))].join('');
|
|
128
142
|
};
|
|
129
|
-
|
|
130
|
-
success: true
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
143
|
+
const response = {
|
|
144
|
+
success: true,
|
|
145
|
+
data: data
|
|
146
|
+
};
|
|
147
|
+
if (req.body) {
|
|
148
|
+
if (Array.isArray(req.body)) {
|
|
149
|
+
response.links = req.body.map(link);
|
|
150
|
+
} else {
|
|
151
|
+
response.link = link(req.body);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
return res.json(200, response);
|
|
136
155
|
})
|
|
137
156
|
// flushes one or more snapshots from the internal queue
|
|
138
157
|
.route('post', '/percy/flush', async (req, res) => res.json(200, {
|
|
139
158
|
success: await percy.flush(req.body).then(() => true)
|
|
140
159
|
})).route('post', '/percy/automateScreenshot', async (req, res) => {
|
|
160
|
+
let data;
|
|
141
161
|
percyAutomateRequestHandler(req, percy);
|
|
142
|
-
|
|
162
|
+
let comparisonData = await WebdriverUtils.automateScreenshot(req.body);
|
|
163
|
+
if (percy.syncMode(comparisonData)) {
|
|
164
|
+
const snapshotPromise = new Promise((resolve, reject) => percy.upload(comparisonData, {
|
|
165
|
+
resolve,
|
|
166
|
+
reject
|
|
167
|
+
}));
|
|
168
|
+
data = await handleSyncJob(snapshotPromise, percy, 'comparison');
|
|
169
|
+
} else {
|
|
170
|
+
percy.upload(comparisonData);
|
|
171
|
+
}
|
|
143
172
|
res.json(200, {
|
|
144
|
-
success: true
|
|
173
|
+
success: true,
|
|
174
|
+
data: data
|
|
145
175
|
});
|
|
146
176
|
})
|
|
147
177
|
// Recieves events from sdk's.
|
package/dist/browser.js
CHANGED
|
@@ -17,8 +17,8 @@ export class Browser extends EventEmitter {
|
|
|
17
17
|
#callbacks = new Map();
|
|
18
18
|
#lastid = 0;
|
|
19
19
|
args = [
|
|
20
|
-
// disable the translate popup
|
|
21
|
-
'--disable-features=Translate',
|
|
20
|
+
// disable the translate popup and optimization downloads
|
|
21
|
+
'--disable-features=Translate,OptimizationGuideModelDownloading',
|
|
22
22
|
// disable several subsystems which run network requests in the background
|
|
23
23
|
'--disable-background-networking',
|
|
24
24
|
// disable task throttling of timer tasks from background pages
|
package/dist/config.js
CHANGED
|
@@ -68,6 +68,9 @@ export const configSchema = {
|
|
|
68
68
|
}
|
|
69
69
|
}
|
|
70
70
|
},
|
|
71
|
+
sync: {
|
|
72
|
+
type: 'boolean'
|
|
73
|
+
},
|
|
71
74
|
fullPage: {
|
|
72
75
|
type: 'boolean',
|
|
73
76
|
onlyAutomate: true
|
|
@@ -306,6 +309,9 @@ export const snapshotSchema = {
|
|
|
306
309
|
enableLayout: {
|
|
307
310
|
$ref: '/config/snapshot#/properties/enableLayout'
|
|
308
311
|
},
|
|
312
|
+
sync: {
|
|
313
|
+
$ref: '/config/snapshot#/properties/sync'
|
|
314
|
+
},
|
|
309
315
|
reshuffleInvalidTags: {
|
|
310
316
|
$ref: '/config/snapshot#/properties/reshuffleInvalidTags'
|
|
311
317
|
},
|
|
@@ -704,6 +710,9 @@ export const comparisonSchema = {
|
|
|
704
710
|
domInfoSha: {
|
|
705
711
|
type: 'string'
|
|
706
712
|
},
|
|
713
|
+
sync: {
|
|
714
|
+
type: 'boolean'
|
|
715
|
+
},
|
|
707
716
|
metadata: {
|
|
708
717
|
type: 'object',
|
|
709
718
|
additionalProperties: false,
|
package/dist/percy.js
CHANGED
|
@@ -6,6 +6,7 @@ import { createPercyServer, createStaticServer } from './api.js';
|
|
|
6
6
|
import { gatherSnapshots, createSnapshotsQueue, validateSnapshotOptions } from './snapshot.js';
|
|
7
7
|
import { discoverSnapshotResources, createDiscoveryQueue } from './discovery.js';
|
|
8
8
|
import { generatePromise, yieldAll, yieldTo } from './utils.js';
|
|
9
|
+
import { WaitForJob } from './wait-for-job.js';
|
|
9
10
|
|
|
10
11
|
// A Percy instance will create a new build when started, handle snapshot creation, asset discovery,
|
|
11
12
|
// and resource uploads, and will finalize the build when stopped. Snapshots are processed
|
|
@@ -150,6 +151,8 @@ export class Percy {
|
|
|
150
151
|
if (!this.skipDiscovery) yield this.#discovery.start();
|
|
151
152
|
// start a local API server for SDK communication
|
|
152
153
|
if (this.server) yield this.server.listen();
|
|
154
|
+
const snapshotType = this.projectType === 'web' ? 'snapshot' : 'comparison';
|
|
155
|
+
this.syncQueue = new WaitForJob(snapshotType, this);
|
|
153
156
|
// log and mark this instance as started
|
|
154
157
|
this.log.info('Percy has started!');
|
|
155
158
|
this.readyState = 1;
|
|
@@ -206,7 +209,7 @@ export class Percy {
|
|
|
206
209
|
if (!this.readyState && this.browser.isConnected()) {
|
|
207
210
|
await this.browser.close();
|
|
208
211
|
}
|
|
209
|
-
|
|
212
|
+
if (this.syncQueue) this.syncQueue.stop();
|
|
210
213
|
// not started or already stopped
|
|
211
214
|
if (!this.readyState || this.readyState > 2) return;
|
|
212
215
|
|
|
@@ -254,14 +257,14 @@ export class Percy {
|
|
|
254
257
|
// Takes one or more snapshots of a page while discovering resources to upload with the resulting
|
|
255
258
|
// snapshots. Once asset discovery has completed for the provided snapshots, the queued task will
|
|
256
259
|
// resolve and an upload task will be queued separately.
|
|
257
|
-
snapshot(options) {
|
|
260
|
+
snapshot(options, snapshotPromise = {}) {
|
|
258
261
|
var _this$build;
|
|
259
262
|
if (this.readyState !== 1) {
|
|
260
263
|
throw new Error('Not running');
|
|
261
264
|
} else if ((_this$build = this.build) !== null && _this$build !== void 0 && _this$build.error) {
|
|
262
265
|
throw new Error(this.build.error);
|
|
263
266
|
} else if (Array.isArray(options)) {
|
|
264
|
-
return yieldAll(options.map(o => this.yield.snapshot(o)));
|
|
267
|
+
return yieldAll(options.map(o => this.yield.snapshot(o, snapshotPromise)));
|
|
265
268
|
}
|
|
266
269
|
|
|
267
270
|
// accept a url for a sitemap or snapshot
|
|
@@ -309,6 +312,15 @@ export class Percy {
|
|
|
309
312
|
config: this.config
|
|
310
313
|
})
|
|
311
314
|
}, snapshot => {
|
|
315
|
+
// attaching promise resolve reject so to wait for snapshot to complete
|
|
316
|
+
if (this.syncMode(snapshot)) {
|
|
317
|
+
snapshotPromise[snapshot.name] = new Promise((resolve, reject) => {
|
|
318
|
+
Object.assign(snapshot, {
|
|
319
|
+
resolve,
|
|
320
|
+
reject
|
|
321
|
+
});
|
|
322
|
+
});
|
|
323
|
+
}
|
|
312
324
|
// push each finished snapshot to the snapshots queue
|
|
313
325
|
this.#snapshots.push(snapshot);
|
|
314
326
|
});
|
|
@@ -321,7 +333,7 @@ export class Percy {
|
|
|
321
333
|
}
|
|
322
334
|
|
|
323
335
|
// Uploads one or more snapshots directly to the current Percy build
|
|
324
|
-
upload(options) {
|
|
336
|
+
upload(options, callback = null) {
|
|
325
337
|
if (this.readyState !== 1) {
|
|
326
338
|
throw new Error('Not running');
|
|
327
339
|
} else if (Array.isArray(options)) {
|
|
@@ -353,6 +365,13 @@ export class Percy {
|
|
|
353
365
|
this.client.addClientInfo(options.clientInfo);
|
|
354
366
|
this.client.addEnvironmentInfo(options.environmentInfo);
|
|
355
367
|
|
|
368
|
+
// Sync CLI support, attached resolve, reject promise
|
|
369
|
+
if (this.syncMode(options)) {
|
|
370
|
+
Object.assign(options, {
|
|
371
|
+
...callback
|
|
372
|
+
});
|
|
373
|
+
}
|
|
374
|
+
|
|
356
375
|
// return an async generator to allow cancelation
|
|
357
376
|
return async function* () {
|
|
358
377
|
try {
|
|
@@ -369,5 +388,26 @@ export class Percy {
|
|
|
369
388
|
}
|
|
370
389
|
return tokenType !== 'web';
|
|
371
390
|
}
|
|
391
|
+
syncMode(options) {
|
|
392
|
+
var _this$config, _this$config$snapshot;
|
|
393
|
+
let syncMode = false;
|
|
394
|
+
if ((_this$config = this.config) !== null && _this$config !== void 0 && (_this$config$snapshot = _this$config.snapshot) !== null && _this$config$snapshot !== void 0 && _this$config$snapshot.sync) syncMode = true;
|
|
395
|
+
if (options !== null && options !== void 0 && options.sync) syncMode = true;
|
|
396
|
+
if ((options === null || options === void 0 ? void 0 : options.sync) === false) syncMode = false;
|
|
397
|
+
if ((this.skipUploads || this.deferUploads || this.delayUploads) && syncMode) {
|
|
398
|
+
syncMode = false;
|
|
399
|
+
options.sync = false;
|
|
400
|
+
if (this.delayUploads && !this.skipUploads) {
|
|
401
|
+
this.log.warn('Synchronous CLI functionality is not compatible with the snapshot command. Kindly consider taking screenshots via SDKs to achieve synchronous results instead.');
|
|
402
|
+
} else {
|
|
403
|
+
let type = 'deferUploads option';
|
|
404
|
+
if (this.skipDiscovery && this.deferUploads) type = 'upload command';
|
|
405
|
+
if (this.skipUploads) type = 'skipUploads option';
|
|
406
|
+
this.log.warn(`The Synchronous CLI functionality is not compatible with ${type}.`);
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
if (syncMode) options.sync = syncMode;
|
|
410
|
+
return syncMode;
|
|
411
|
+
}
|
|
372
412
|
}
|
|
373
413
|
export default Percy;
|
package/dist/snapshot.js
CHANGED
|
@@ -4,6 +4,7 @@ import micromatch from 'micromatch';
|
|
|
4
4
|
import { configSchema } from './config.js';
|
|
5
5
|
import Queue from './queue.js';
|
|
6
6
|
import { request, hostnameMatches, yieldTo } from './utils.js';
|
|
7
|
+
import { JobData } from './wait-for-job.js';
|
|
7
8
|
|
|
8
9
|
// Throw a better error message for missing or invalid urls
|
|
9
10
|
function validURL(url, base) {
|
|
@@ -219,6 +220,22 @@ export function validateSnapshotOptions(options) {
|
|
|
219
220
|
...migrated
|
|
220
221
|
};
|
|
221
222
|
}
|
|
223
|
+
export async function handleSyncJob(jobPromise, percy, type) {
|
|
224
|
+
let data;
|
|
225
|
+
try {
|
|
226
|
+
const id = await jobPromise;
|
|
227
|
+
if (type === 'snapshot') {
|
|
228
|
+
data = await percy.client.getSnapshotDetails(id);
|
|
229
|
+
} else {
|
|
230
|
+
data = await percy.client.getComparisonDetails(id);
|
|
231
|
+
}
|
|
232
|
+
} catch (e) {
|
|
233
|
+
data = {
|
|
234
|
+
error: e.message
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
return data;
|
|
238
|
+
}
|
|
222
239
|
|
|
223
240
|
// Fetches a sitemap and parses it into a list of URLs for taking snapshots. Duplicate URLs,
|
|
224
241
|
// including a trailing slash, are removed from the resulting list.
|
|
@@ -411,6 +428,14 @@ export function createSnapshotsQueue(percy) {
|
|
|
411
428
|
let send = 'tag' in snapshot ? 'sendComparison' : 'sendSnapshot';
|
|
412
429
|
let response = yield percy.client[send](build.id, snapshot);
|
|
413
430
|
if (percy.deferUploads) percy.log.info(`Snapshot uploaded: ${name}`, meta);
|
|
431
|
+
|
|
432
|
+
// Pushing to syncQueue, that will check for
|
|
433
|
+
// snapshot processing status, and will resolve once done
|
|
434
|
+
if (snapshot.sync) {
|
|
435
|
+
percy.log.info(`Waiting for snapshot '${name}' to be completed`);
|
|
436
|
+
const data = new JobData(response.data.id, null, snapshot.resolve, snapshot.reject);
|
|
437
|
+
percy.syncQueue.push(data);
|
|
438
|
+
}
|
|
414
439
|
return {
|
|
415
440
|
...snapshot,
|
|
416
441
|
response
|
|
@@ -448,6 +473,7 @@ export function createSnapshotsQueue(percy) {
|
|
|
448
473
|
}
|
|
449
474
|
percy.log.error(`Encountered an error uploading snapshot: ${name}`, meta);
|
|
450
475
|
percy.log.error(error, meta);
|
|
476
|
+
if (snapshot.sync) snapshot.reject(error);
|
|
451
477
|
return result;
|
|
452
478
|
});
|
|
453
479
|
}
|
package/dist/utils.js
CHANGED
|
@@ -46,6 +46,7 @@ export function percyAutomateRequestHandler(req, percy) {
|
|
|
46
46
|
ignoreRegionXpaths: (_percy$config$snapsho4 = percy.config.snapshot.ignoreRegions) === null || _percy$config$snapsho4 === void 0 ? void 0 : _percy$config$snapsho4.ignoreRegionXpaths,
|
|
47
47
|
considerRegionSelectors: (_percy$config$snapsho5 = percy.config.snapshot.considerRegions) === null || _percy$config$snapsho5 === void 0 ? void 0 : _percy$config$snapsho5.considerRegionSelectors,
|
|
48
48
|
considerRegionXpaths: (_percy$config$snapsho6 = percy.config.snapshot.considerRegions) === null || _percy$config$snapsho6 === void 0 ? void 0 : _percy$config$snapsho6.considerRegionXpaths,
|
|
49
|
+
sync: percy.config.snapshot.sync,
|
|
49
50
|
version: 'v2'
|
|
50
51
|
}, camelCasedOptions], (path, prev, next) => {
|
|
51
52
|
switch (path.map(k => k.toString()).join('.')) {
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import logger from '@percy/logger';
|
|
2
|
+
const MIN_POLLING_INTERVAL = 5_000;
|
|
3
|
+
// Poll atleast once in 2 min
|
|
4
|
+
const MAX_POLLING_INTERVAL_SECONDS = 120;
|
|
5
|
+
const THRESHOLD_OPTIMAL_POLL_TIME = 5;
|
|
6
|
+
const JOB_TIMEOUT = Number(process.env.SYNC_TIMEOUT) || 90_000;
|
|
7
|
+
|
|
8
|
+
// Job is either for snapshot or comparison only
|
|
9
|
+
export class WaitForJob {
|
|
10
|
+
log = logger('core:wait-for-job');
|
|
11
|
+
constructor(type, percy) {
|
|
12
|
+
this.percy = percy;
|
|
13
|
+
this.jobs = [];
|
|
14
|
+
if (type !== 'comparison' && type !== 'snapshot') throw new Error('Type should be either comparison or snapshot');
|
|
15
|
+
this.type = type;
|
|
16
|
+
this.timer = null;
|
|
17
|
+
this.exit = false;
|
|
18
|
+
this.running = false;
|
|
19
|
+
}
|
|
20
|
+
push(job) {
|
|
21
|
+
if (!(job instanceof JobData)) throw new Error('Invalid job passed, use JobData');
|
|
22
|
+
if (this.type === 'snapshot') job.timeout += 420_000; // For snapshot timeout after 08:30 min
|
|
23
|
+
|
|
24
|
+
this.jobs.push(job);
|
|
25
|
+
if (!this.running) this.run();
|
|
26
|
+
}
|
|
27
|
+
run(interval = MIN_POLLING_INTERVAL) {
|
|
28
|
+
if (this.exit) return;
|
|
29
|
+
this.running = true;
|
|
30
|
+
if (interval < MIN_POLLING_INTERVAL) {
|
|
31
|
+
interval = MIN_POLLING_INTERVAL;
|
|
32
|
+
}
|
|
33
|
+
this.log.debug(`Polling for ${this.type} status in ${interval}ms`);
|
|
34
|
+
this.timer = setTimeout(async () => {
|
|
35
|
+
let nextPoll = MAX_POLLING_INTERVAL_SECONDS;
|
|
36
|
+
const jobIds = this.jobs.map(job => job.id);
|
|
37
|
+
const response = await this.percy.client.getStatus(this.type, jobIds);
|
|
38
|
+
this.jobs = this.jobs.filter(job => {
|
|
39
|
+
if (response[job.id]) {
|
|
40
|
+
const jobStatus = response[job.id];
|
|
41
|
+
if (jobStatus.status) {
|
|
42
|
+
job.resolve(job.id);
|
|
43
|
+
return false;
|
|
44
|
+
} else if (jobStatus.error != null) {
|
|
45
|
+
job.reject(jobStatus.error);
|
|
46
|
+
return false;
|
|
47
|
+
} else if (Date.now() - job.timeout >= 0) {
|
|
48
|
+
job.reject(new Error(`Timeout waiting for ${this.type} with id ${job.id}`));
|
|
49
|
+
return false;
|
|
50
|
+
} else {
|
|
51
|
+
job.nextPoll = jobStatus.next_poll;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
nextPoll = Math.min(nextPoll, job.nextPoll);
|
|
55
|
+
return true;
|
|
56
|
+
});
|
|
57
|
+
if (this.jobs.length === 0) {
|
|
58
|
+
this.running = false;
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
const optimalNextPollTime = this.getOptimalPollTime(nextPoll);
|
|
62
|
+
this.run(optimalNextPollTime * 1000);
|
|
63
|
+
}, interval);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// If there are other snapshots which can be completed in next
|
|
67
|
+
// 5 seconds, calling after x seconds will reduce network call
|
|
68
|
+
getOptimalPollTime(lowestPollTime) {
|
|
69
|
+
let pollTime = lowestPollTime;
|
|
70
|
+
this.jobs.forEach(job => {
|
|
71
|
+
const jobPollTime = job.nextPoll;
|
|
72
|
+
if (jobPollTime - lowestPollTime <= THRESHOLD_OPTIMAL_POLL_TIME) {
|
|
73
|
+
pollTime = Math.max(pollTime, jobPollTime);
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
return pollTime;
|
|
77
|
+
}
|
|
78
|
+
stop() {
|
|
79
|
+
this.exit = true;
|
|
80
|
+
if (this.timer) {
|
|
81
|
+
clearTimeout(this.timer);
|
|
82
|
+
this.timer = null;
|
|
83
|
+
}
|
|
84
|
+
this.jobs.forEach(job => {
|
|
85
|
+
job.reject(new Error('Unable to process synchronous results as the CLI was exited while awaiting completion of the snapshot.'));
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
export class JobData {
|
|
90
|
+
constructor(id, nextPoll, resolve, reject) {
|
|
91
|
+
this.id = id;
|
|
92
|
+
this.nextPoll = nextPoll || 60;
|
|
93
|
+
this.timeout = Date.now() + JOB_TIMEOUT;
|
|
94
|
+
this.resolve = resolve;
|
|
95
|
+
this.reject = reject;
|
|
96
|
+
}
|
|
97
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@percy/core",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.28.0-beta.1",
|
|
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": "beta"
|
|
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.
|
|
47
|
-
"@percy/config": "1.
|
|
48
|
-
"@percy/dom": "1.
|
|
49
|
-
"@percy/logger": "1.
|
|
50
|
-
"@percy/webdriver-utils": "1.
|
|
46
|
+
"@percy/client": "1.28.0-beta.1",
|
|
47
|
+
"@percy/config": "1.28.0-beta.1",
|
|
48
|
+
"@percy/dom": "1.28.0-beta.1",
|
|
49
|
+
"@percy/logger": "1.28.0-beta.1",
|
|
50
|
+
"@percy/webdriver-utils": "1.28.0-beta.1",
|
|
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": "726fe9b1688c640a4806623d1d34aaafeb79d8c7"
|
|
62
62
|
}
|