@percy/core 1.28.8 → 1.28.9-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/discovery.js +23 -3
- package/dist/percy.js +137 -32
- package/dist/snapshot.js +21 -3
- package/package.json +8 -8
package/dist/discovery.js
CHANGED
|
@@ -321,6 +321,9 @@ export function createDiscoveryQueue(percy) {
|
|
|
321
321
|
// on start, launch the browser and run the queue
|
|
322
322
|
.handle('start', async () => {
|
|
323
323
|
cache = percy[RESOURCE_CACHE_KEY] = new Map();
|
|
324
|
+
|
|
325
|
+
// If browser.launch() fails it will get captured in
|
|
326
|
+
// *percy.start()
|
|
324
327
|
await percy.browser.launch();
|
|
325
328
|
queue.run();
|
|
326
329
|
})
|
|
@@ -395,17 +398,34 @@ export function createDiscoveryQueue(percy) {
|
|
|
395
398
|
throwOn: ['AbortError']
|
|
396
399
|
});
|
|
397
400
|
});
|
|
398
|
-
}).handle('error', ({
|
|
401
|
+
}).handle('error', async ({
|
|
399
402
|
name,
|
|
400
403
|
meta
|
|
401
404
|
}, error) => {
|
|
402
405
|
if (error.name === 'AbortError' && queue.readyState < 3) {
|
|
403
406
|
// only error about aborted snapshots when not closed
|
|
404
|
-
|
|
407
|
+
let errMsg = 'Received a duplicate snapshot, ' + `the previous snapshot was aborted: ${snapshotLogName(name, meta)}`;
|
|
408
|
+
percy.log.error(errMsg, {
|
|
409
|
+
snapshotLevel: true,
|
|
410
|
+
snapshotName: name
|
|
411
|
+
});
|
|
412
|
+
await percy.suggestionsForFix(errMsg, meta);
|
|
405
413
|
} else {
|
|
406
414
|
// log all other encountered errors
|
|
407
|
-
|
|
415
|
+
let errMsg = `Encountered an error taking snapshot: ${name}`;
|
|
416
|
+
percy.log.error(errMsg, meta);
|
|
408
417
|
percy.log.error(error, meta);
|
|
418
|
+
let assetDiscoveryErrors = [{
|
|
419
|
+
message: errMsg,
|
|
420
|
+
meta
|
|
421
|
+
}, {
|
|
422
|
+
message: error === null || error === void 0 ? void 0 : error.message,
|
|
423
|
+
meta
|
|
424
|
+
}];
|
|
425
|
+
await percy.suggestionsForFix(assetDiscoveryErrors, {
|
|
426
|
+
snapshotLevel: true,
|
|
427
|
+
snapshotName: name
|
|
428
|
+
});
|
|
409
429
|
}
|
|
410
430
|
});
|
|
411
431
|
}
|
package/dist/percy.js
CHANGED
|
@@ -1,6 +1,20 @@
|
|
|
1
|
+
function _classPrivateMethodInitSpec(e, a) { _checkPrivateRedeclaration(e, a), a.add(e); }
|
|
2
|
+
function _classPrivateFieldInitSpec(e, t, a) { _checkPrivateRedeclaration(e, t), t.set(e, a); }
|
|
3
|
+
function _checkPrivateRedeclaration(e, t) { if (t.has(e)) throw new TypeError("Cannot initialize the same private elements twice on an object"); }
|
|
4
|
+
function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
|
|
5
|
+
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
|
|
6
|
+
function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
|
7
|
+
function _classPrivateMethodGet(s, a, r) { return _assertClassBrand(a, s), r; }
|
|
8
|
+
function _classPrivateFieldGet2(e, t) { var r = _classPrivateFieldGet(t, e); return _classApplyDescriptorGet(e, r); }
|
|
9
|
+
function _classApplyDescriptorGet(e, t) { return t.get ? t.get.call(e) : t.value; }
|
|
10
|
+
function _classPrivateFieldSet(e, t, r) { var s = _classPrivateFieldGet(t, e); return _classApplyDescriptorSet(e, s, r), r; }
|
|
11
|
+
function _classPrivateFieldGet(s, a) { return s.get(_assertClassBrand(s, a)); }
|
|
12
|
+
function _assertClassBrand(e, t, n) { if ("function" == typeof e ? e === t : e.has(t)) return arguments.length < 3 ? t : n; throw new TypeError("Private element is not present on this object"); }
|
|
13
|
+
function _classApplyDescriptorSet(e, t, l) { if (t.set) t.set.call(e, l);else { if (!t.writable) throw new TypeError("attempted to set read only private field"); t.value = l; } }
|
|
1
14
|
import PercyClient from '@percy/client';
|
|
2
15
|
import PercyConfig from '@percy/config';
|
|
3
16
|
import logger from '@percy/logger';
|
|
17
|
+
import { getProxy } from '@percy/client/utils';
|
|
4
18
|
import Browser from './browser.js';
|
|
5
19
|
import Pako from 'pako';
|
|
6
20
|
import { base64encode, generatePromise, yieldAll, yieldTo, redactSecrets } from './utils.js';
|
|
@@ -12,12 +26,11 @@ import { WaitForJob } from './wait-for-job.js';
|
|
|
12
26
|
// A Percy instance will create a new build when started, handle snapshot creation, asset discovery,
|
|
13
27
|
// and resource uploads, and will finalize the build when stopped. Snapshots are processed
|
|
14
28
|
// concurrently and the build is not finalized until all snapshots have been handled.
|
|
29
|
+
var _discovery = /*#__PURE__*/new WeakMap();
|
|
30
|
+
var _snapshots = /*#__PURE__*/new WeakMap();
|
|
31
|
+
var _displaySuggestionLogs = /*#__PURE__*/new WeakSet();
|
|
32
|
+
var _proxyEnabled = /*#__PURE__*/new WeakSet();
|
|
15
33
|
export class Percy {
|
|
16
|
-
log = logger('core');
|
|
17
|
-
readyState = null;
|
|
18
|
-
#discovery = null;
|
|
19
|
-
#snapshots = null;
|
|
20
|
-
|
|
21
34
|
// Static shortcut to create and start an instance in one call
|
|
22
35
|
static async start(options) {
|
|
23
36
|
let instance = new this(options);
|
|
@@ -52,11 +65,23 @@ export class Percy {
|
|
|
52
65
|
projectType = null,
|
|
53
66
|
// options such as `snapshot` and `discovery` that are valid Percy config
|
|
54
67
|
// options which will become accessible via the `.config` property
|
|
55
|
-
...
|
|
68
|
+
..._options
|
|
56
69
|
} = {}) {
|
|
57
70
|
var _config$percy, _config$percy2;
|
|
71
|
+
_classPrivateMethodInitSpec(this, _proxyEnabled);
|
|
72
|
+
_classPrivateMethodInitSpec(this, _displaySuggestionLogs);
|
|
73
|
+
_defineProperty(this, "log", logger('core'));
|
|
74
|
+
_defineProperty(this, "readyState", null);
|
|
75
|
+
_classPrivateFieldInitSpec(this, _discovery, {
|
|
76
|
+
writable: true,
|
|
77
|
+
value: null
|
|
78
|
+
});
|
|
79
|
+
_classPrivateFieldInitSpec(this, _snapshots, {
|
|
80
|
+
writable: true,
|
|
81
|
+
value: null
|
|
82
|
+
});
|
|
58
83
|
let config = PercyConfig.load({
|
|
59
|
-
overrides:
|
|
84
|
+
overrides: _options,
|
|
60
85
|
path: configFile
|
|
61
86
|
});
|
|
62
87
|
labels ?? (labels = (_config$percy = config.percy) === null || _config$percy === void 0 ? void 0 : _config$percy.labels);
|
|
@@ -64,6 +89,7 @@ export class Percy {
|
|
|
64
89
|
this.config = config;
|
|
65
90
|
if (testing) loglevel = 'silent';
|
|
66
91
|
if (loglevel) this.loglevel(loglevel);
|
|
92
|
+
this.port = port;
|
|
67
93
|
this.projectType = projectType;
|
|
68
94
|
this.testing = testing ? {} : null;
|
|
69
95
|
this.dryRun = !!testing || !!dryRun;
|
|
@@ -81,8 +107,8 @@ export class Percy {
|
|
|
81
107
|
});
|
|
82
108
|
if (server) this.server = createPercyServer(this, port);
|
|
83
109
|
this.browser = new Browser(this);
|
|
84
|
-
this
|
|
85
|
-
this
|
|
110
|
+
_classPrivateFieldSet(this, _discovery, createDiscoveryQueue(this));
|
|
111
|
+
_classPrivateFieldSet(this, _snapshots, createSnapshotsQueue(this));
|
|
86
112
|
|
|
87
113
|
// generator methods are wrapped to autorun and return promises
|
|
88
114
|
for (let m of ['start', 'stop', 'flush', 'idle', 'snapshot', 'upload']) {
|
|
@@ -135,10 +161,10 @@ export class Percy {
|
|
|
135
161
|
let {
|
|
136
162
|
concurrency
|
|
137
163
|
} = this.config.discovery;
|
|
138
|
-
this
|
|
164
|
+
_classPrivateFieldGet2(this, _discovery).set({
|
|
139
165
|
concurrency
|
|
140
166
|
});
|
|
141
|
-
this
|
|
167
|
+
_classPrivateFieldGet2(this, _snapshots).set({
|
|
142
168
|
concurrency
|
|
143
169
|
});
|
|
144
170
|
return this.config;
|
|
@@ -154,9 +180,9 @@ export class Percy {
|
|
|
154
180
|
this.log.warn('Notice: Percy collects CI logs for service improvement, stored for 30 days. Opt-out anytime with export PERCY_CLIENT_ERROR_LOGS=false');
|
|
155
181
|
}
|
|
156
182
|
// start the snapshots queue immediately when not delayed or deferred
|
|
157
|
-
if (!this.delayUploads && !this.deferUploads) yield this
|
|
183
|
+
if (!this.delayUploads && !this.deferUploads) yield _classPrivateFieldGet2(this, _snapshots).start();
|
|
158
184
|
// do not start the discovery queue when not needed
|
|
159
|
-
if (!this.skipDiscovery) yield this
|
|
185
|
+
if (!this.skipDiscovery) yield _classPrivateFieldGet2(this, _discovery).start();
|
|
160
186
|
// start a local API server for SDK communication
|
|
161
187
|
if (this.server) yield this.server.listen();
|
|
162
188
|
if (this.projectType === 'web') {
|
|
@@ -174,16 +200,19 @@ export class Percy {
|
|
|
174
200
|
var _this$server2;
|
|
175
201
|
// on error, close any running server and end queues
|
|
176
202
|
await ((_this$server2 = this.server) === null || _this$server2 === void 0 ? void 0 : _this$server2.close());
|
|
177
|
-
await this
|
|
178
|
-
await this
|
|
203
|
+
await _classPrivateFieldGet2(this, _discovery).end();
|
|
204
|
+
await _classPrivateFieldGet2(this, _snapshots).end();
|
|
179
205
|
|
|
180
206
|
// mark this instance as closed unless aborting
|
|
181
207
|
this.readyState = error.name !== 'AbortError' ? 3 : null;
|
|
182
208
|
|
|
183
209
|
// throw an easier-to-understand error when the port is in use
|
|
184
210
|
if (error.code === 'EADDRINUSE') {
|
|
185
|
-
|
|
211
|
+
let errMsg = `Percy is already running or the port ${this.port} is in use`;
|
|
212
|
+
await this.suggestionsForFix(errMsg);
|
|
213
|
+
throw new Error(errMsg);
|
|
186
214
|
} else {
|
|
215
|
+
await this.suggestionsForFix(error.message);
|
|
187
216
|
throw error;
|
|
188
217
|
}
|
|
189
218
|
}
|
|
@@ -191,8 +220,8 @@ export class Percy {
|
|
|
191
220
|
|
|
192
221
|
// Resolves once snapshot and upload queues are idle
|
|
193
222
|
async *idle() {
|
|
194
|
-
yield* this
|
|
195
|
-
yield* this
|
|
223
|
+
yield* _classPrivateFieldGet2(this, _discovery).idle();
|
|
224
|
+
yield* _classPrivateFieldGet2(this, _snapshots).idle();
|
|
196
225
|
}
|
|
197
226
|
|
|
198
227
|
// Wait for currently queued snapshots then run and wait for resulting uploads
|
|
@@ -205,13 +234,13 @@ export class Percy {
|
|
|
205
234
|
yield new Promise(r => setImmediate(r));
|
|
206
235
|
|
|
207
236
|
// flush and log progress for discovery before snapshots
|
|
208
|
-
if (!this.skipDiscovery && this
|
|
209
|
-
if (options) yield* yieldAll(options.map(o => this
|
|
237
|
+
if (!this.skipDiscovery && _classPrivateFieldGet2(this, _discovery).size) {
|
|
238
|
+
if (options) yield* yieldAll(options.map(o => _classPrivateFieldGet2(this, _discovery).process(o)));else yield* _classPrivateFieldGet2(this, _discovery).flush(size => callback === null || callback === void 0 ? void 0 : callback('Processing', size));
|
|
210
239
|
}
|
|
211
240
|
|
|
212
241
|
// flush and log progress for snapshot uploads
|
|
213
|
-
if (!this.skipUploads && this
|
|
214
|
-
if (options) yield* yieldAll(options.map(o => this
|
|
242
|
+
if (!this.skipUploads && _classPrivateFieldGet2(this, _snapshots).size) {
|
|
243
|
+
if (options) yield* yieldAll(options.map(o => _classPrivateFieldGet2(this, _snapshots).process(o)));else yield* _classPrivateFieldGet2(this, _snapshots).flush(size => callback === null || callback === void 0 ? void 0 : callback('Uploading', size));
|
|
215
244
|
}
|
|
216
245
|
}
|
|
217
246
|
|
|
@@ -230,8 +259,8 @@ export class Percy {
|
|
|
230
259
|
|
|
231
260
|
// close queues asap
|
|
232
261
|
if (force) {
|
|
233
|
-
this
|
|
234
|
-
this
|
|
262
|
+
_classPrivateFieldGet2(this, _discovery).close(true);
|
|
263
|
+
_classPrivateFieldGet2(this, _snapshots).close(true);
|
|
235
264
|
}
|
|
236
265
|
|
|
237
266
|
// already stopping
|
|
@@ -256,14 +285,14 @@ export class Percy {
|
|
|
256
285
|
}
|
|
257
286
|
|
|
258
287
|
// if dry-running, log the total number of snapshots
|
|
259
|
-
if (this.dryRun && this
|
|
260
|
-
this.log.info(info('Found', this
|
|
288
|
+
if (this.dryRun && _classPrivateFieldGet2(this, _snapshots).size) {
|
|
289
|
+
this.log.info(info('Found', _classPrivateFieldGet2(this, _snapshots).size));
|
|
261
290
|
}
|
|
262
291
|
|
|
263
292
|
// close server and end queues
|
|
264
293
|
await ((_this$server3 = this.server) === null || _this$server3 === void 0 ? void 0 : _this$server3.close());
|
|
265
|
-
await this
|
|
266
|
-
await this
|
|
294
|
+
await _classPrivateFieldGet2(this, _discovery).end();
|
|
295
|
+
await _classPrivateFieldGet2(this, _snapshots).end();
|
|
267
296
|
|
|
268
297
|
// mark instance as stopped
|
|
269
298
|
this.readyState = 3;
|
|
@@ -271,6 +300,9 @@ export class Percy {
|
|
|
271
300
|
this.log.error(err);
|
|
272
301
|
throw err;
|
|
273
302
|
} finally {
|
|
303
|
+
// This issue doesn't comes under regular error logs,
|
|
304
|
+
// it's detected if we just and stop percy server
|
|
305
|
+
await this.checkForNoSnapshotCommandError();
|
|
274
306
|
await this.sendBuildLogs();
|
|
275
307
|
}
|
|
276
308
|
}
|
|
@@ -323,7 +355,7 @@ export class Percy {
|
|
|
323
355
|
}
|
|
324
356
|
|
|
325
357
|
// gather snapshots and discover snapshot resources
|
|
326
|
-
yield* discoverSnapshotResources(this
|
|
358
|
+
yield* discoverSnapshotResources(_classPrivateFieldGet2(this, _discovery), {
|
|
327
359
|
skipDiscovery: this.skipDiscovery,
|
|
328
360
|
dryRun: this.dryRun,
|
|
329
361
|
snapshots: yield* gatherSnapshots(options, {
|
|
@@ -343,7 +375,7 @@ export class Percy {
|
|
|
343
375
|
});
|
|
344
376
|
}
|
|
345
377
|
// push each finished snapshot to the snapshots queue
|
|
346
|
-
this
|
|
378
|
+
_classPrivateFieldGet2(this, _snapshots).push(snapshot);
|
|
347
379
|
});
|
|
348
380
|
} finally {
|
|
349
381
|
var _server;
|
|
@@ -403,9 +435,11 @@ export class Percy {
|
|
|
403
435
|
// return an async generator to allow cancelation
|
|
404
436
|
return async function* () {
|
|
405
437
|
try {
|
|
406
|
-
return yield* yieldTo(this
|
|
438
|
+
return yield* yieldTo(_classPrivateFieldGet2(this, _snapshots).push(options));
|
|
407
439
|
} catch (error) {
|
|
408
|
-
this
|
|
440
|
+
_classPrivateFieldGet2(this, _snapshots).cancel(options);
|
|
441
|
+
// Detecting and suggesting fix for errors;
|
|
442
|
+
await this.suggestionsForFix(error.message);
|
|
409
443
|
throw error;
|
|
410
444
|
}
|
|
411
445
|
}.call(this);
|
|
@@ -437,6 +471,48 @@ export class Percy {
|
|
|
437
471
|
if (syncMode) options.sync = syncMode;
|
|
438
472
|
return syncMode;
|
|
439
473
|
}
|
|
474
|
+
|
|
475
|
+
// This specific error will be hard coded
|
|
476
|
+
async checkForNoSnapshotCommandError() {
|
|
477
|
+
let isPercyStarted = false;
|
|
478
|
+
let containsSnapshotTaken = false;
|
|
479
|
+
logger.query(item => {
|
|
480
|
+
var _item$message, _item$message2, _item$message3;
|
|
481
|
+
isPercyStarted || (isPercyStarted = item === null || item === void 0 ? void 0 : (_item$message = item.message) === null || _item$message === void 0 ? void 0 : _item$message.includes('Percy has started'));
|
|
482
|
+
containsSnapshotTaken || (containsSnapshotTaken = item === null || item === void 0 ? void 0 : (_item$message2 = item.message) === null || _item$message2 === void 0 ? void 0 : _item$message2.includes('Snapshot taken'));
|
|
483
|
+
|
|
484
|
+
// This case happens when you directly upload it using cli-upload
|
|
485
|
+
containsSnapshotTaken || (containsSnapshotTaken = item === null || item === void 0 ? void 0 : (_item$message3 = item.message) === null || _item$message3 === void 0 ? void 0 : _item$message3.includes('Snapshot uploaded'));
|
|
486
|
+
return item;
|
|
487
|
+
});
|
|
488
|
+
if (isPercyStarted && !containsSnapshotTaken) {
|
|
489
|
+
// This is the case for No snapshot command called
|
|
490
|
+
_classPrivateMethodGet(this, _displaySuggestionLogs, _displaySuggestionLogs2).call(this, [{
|
|
491
|
+
failure_reason: 'Snapshot command was not called',
|
|
492
|
+
reason_message: 'Snapshot Command was not called. please check your CI for errors',
|
|
493
|
+
suggestion: 'Try using percy snapshot command to take snapshots',
|
|
494
|
+
reference_doc_link: ['https://www.browserstack.com/docs/percy/take-percy-snapshots/']
|
|
495
|
+
}]);
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
async suggestionsForFix(errors, options = {}) {
|
|
499
|
+
try {
|
|
500
|
+
const suggestionResponse = await this.client.getErrorAnalysis(errors);
|
|
501
|
+
_classPrivateMethodGet(this, _displaySuggestionLogs, _displaySuggestionLogs2).call(this, suggestionResponse, options);
|
|
502
|
+
} catch (e) {
|
|
503
|
+
// Common error code for Proxy issues
|
|
504
|
+
const PROXY_CODES = ['ECONNREFUSED', 'ECONNRESET', 'EHOSTUNREACH'];
|
|
505
|
+
if (!!e.code && PROXY_CODES.includes(e.code)) {
|
|
506
|
+
// This can be due to proxy issue
|
|
507
|
+
this.log.error('percy.io might not be reachable, check network connection, proxy and ensure that percy.io is whitelisted.');
|
|
508
|
+
if (!_classPrivateMethodGet(this, _proxyEnabled, _proxyEnabled2).call(this)) {
|
|
509
|
+
this.log.error('If inside a proxied envirnment, please configure the following environment variables: HTTP_PROXY, [ and optionally HTTPS_PROXY if you need it ]. Refer to our documentation for more details');
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
this.log.error('Unable to analyze error logs');
|
|
513
|
+
this.log.debug(e);
|
|
514
|
+
}
|
|
515
|
+
}
|
|
440
516
|
async sendBuildLogs() {
|
|
441
517
|
if (!process.env.PERCY_TOKEN) return;
|
|
442
518
|
try {
|
|
@@ -444,6 +520,7 @@ export class Percy {
|
|
|
444
520
|
const logsObject = {
|
|
445
521
|
clilogs: logger.query(log => !['ci'].includes(log.debug))
|
|
446
522
|
};
|
|
523
|
+
|
|
447
524
|
// Only add CI logs if not disabled voluntarily.
|
|
448
525
|
const sendCILogs = process.env.PERCY_CLIENT_ERROR_LOGS !== 'false';
|
|
449
526
|
if (sendCILogs) {
|
|
@@ -467,4 +544,32 @@ export class Percy {
|
|
|
467
544
|
}
|
|
468
545
|
}
|
|
469
546
|
}
|
|
547
|
+
function _displaySuggestionLogs2(suggestions, options = {}) {
|
|
548
|
+
if (!(suggestions !== null && suggestions !== void 0 && suggestions.length)) return;
|
|
549
|
+
suggestions.forEach(item => {
|
|
550
|
+
const failure = item === null || item === void 0 ? void 0 : item.failure_reason;
|
|
551
|
+
const failureReason = item === null || item === void 0 ? void 0 : item.reason_message;
|
|
552
|
+
const suggestion = item === null || item === void 0 ? void 0 : item.suggestion;
|
|
553
|
+
const referenceDocLinks = item === null || item === void 0 ? void 0 : item.reference_doc_link;
|
|
554
|
+
if (options !== null && options !== void 0 && options.snapshotLevel) {
|
|
555
|
+
this.log.warn(`Detected erorr for Snapshot: ${options === null || options === void 0 ? void 0 : options.snapshotName}`);
|
|
556
|
+
} else {
|
|
557
|
+
this.log.warn('Detected error for percy build');
|
|
558
|
+
}
|
|
559
|
+
this.log.warn(`Failure: ${failure}`);
|
|
560
|
+
this.log.warn(`Failure Reason: ${failureReason}`);
|
|
561
|
+
this.log.warn(`Suggestion: ${suggestion}`);
|
|
562
|
+
if ((referenceDocLinks === null || referenceDocLinks === void 0 ? void 0 : referenceDocLinks.length) > 0) {
|
|
563
|
+
this.log.warn('Refer to the below Doc Links for the same');
|
|
564
|
+
referenceDocLinks === null || referenceDocLinks === void 0 ? void 0 : referenceDocLinks.forEach(_docLink => {
|
|
565
|
+
this.log.warn(`* ${_docLink}`);
|
|
566
|
+
});
|
|
567
|
+
}
|
|
568
|
+
});
|
|
569
|
+
}
|
|
570
|
+
function _proxyEnabled2() {
|
|
571
|
+
return !!(getProxy({
|
|
572
|
+
protocol: 'https:'
|
|
573
|
+
}) || getProxy({}));
|
|
574
|
+
}
|
|
470
575
|
export default Percy;
|
package/dist/snapshot.js
CHANGED
|
@@ -234,6 +234,7 @@ export async function handleSyncJob(jobPromise, percy, type) {
|
|
|
234
234
|
data = await percy.client.getComparisonDetails(id);
|
|
235
235
|
}
|
|
236
236
|
} catch (e) {
|
|
237
|
+
await percy.suggestionsForFix(e.message);
|
|
237
238
|
data = {
|
|
238
239
|
error: e.message
|
|
239
240
|
};
|
|
@@ -453,7 +454,7 @@ export function createSnapshotsQueue(percy) {
|
|
|
453
454
|
};
|
|
454
455
|
})
|
|
455
456
|
// handle possible build errors returned by the API
|
|
456
|
-
.handle('error', (snapshot, error) => {
|
|
457
|
+
.handle('error', async (snapshot, error) => {
|
|
457
458
|
var _error$response, _error$response2, _error$response2$body;
|
|
458
459
|
let result = {
|
|
459
460
|
...snapshot,
|
|
@@ -478,12 +479,29 @@ export function createSnapshotsQueue(percy) {
|
|
|
478
479
|
let duplicate = (errors === null || errors === void 0 ? void 0 : errors.length) > 1 && errors[1].detail.includes('must be unique');
|
|
479
480
|
if (duplicate) {
|
|
480
481
|
if (process.env.PERCY_IGNORE_DUPLICATES !== 'true') {
|
|
481
|
-
|
|
482
|
+
let errMsg = `Ignored duplicate snapshot. ${errors[1].detail}`;
|
|
483
|
+
percy.log.warn(errMsg);
|
|
484
|
+
await percy.suggestionsForFix(errMsg, {
|
|
485
|
+
snapshotLevel: true,
|
|
486
|
+
snapshotName: name
|
|
487
|
+
});
|
|
482
488
|
}
|
|
483
489
|
return result;
|
|
484
490
|
}
|
|
485
|
-
|
|
491
|
+
let errMsg = `Encountered an error uploading snapshot: ${name}`;
|
|
492
|
+
percy.log.error(errMsg, meta);
|
|
486
493
|
percy.log.error(error, meta);
|
|
494
|
+
let snapshotErrors = [{
|
|
495
|
+
message: errMsg,
|
|
496
|
+
meta
|
|
497
|
+
}, {
|
|
498
|
+
message: error === null || error === void 0 ? void 0 : error.message,
|
|
499
|
+
meta
|
|
500
|
+
}];
|
|
501
|
+
await percy.suggestionsForFix(snapshotErrors, {
|
|
502
|
+
snapshotLevel: true,
|
|
503
|
+
snapshotName: name
|
|
504
|
+
});
|
|
487
505
|
if (snapshot.sync) snapshot.reject(error);
|
|
488
506
|
return result;
|
|
489
507
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@percy/core",
|
|
3
|
-
"version": "1.28.
|
|
3
|
+
"version": "1.28.9-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.28.
|
|
47
|
-
"@percy/config": "1.28.
|
|
48
|
-
"@percy/dom": "1.28.
|
|
49
|
-
"@percy/logger": "1.28.
|
|
50
|
-
"@percy/webdriver-utils": "1.28.
|
|
46
|
+
"@percy/client": "1.28.9-beta.1",
|
|
47
|
+
"@percy/config": "1.28.9-beta.1",
|
|
48
|
+
"@percy/dom": "1.28.9-beta.1",
|
|
49
|
+
"@percy/logger": "1.28.9-beta.1",
|
|
50
|
+
"@percy/webdriver-utils": "1.28.9-beta.1",
|
|
51
51
|
"content-disposition": "^0.5.4",
|
|
52
52
|
"cross-spawn": "^7.0.3",
|
|
53
53
|
"extract-zip": "^2.0.1",
|
|
@@ -60,5 +60,5 @@
|
|
|
60
60
|
"ws": "^8.17.1",
|
|
61
61
|
"yaml": "^2.4.1"
|
|
62
62
|
},
|
|
63
|
-
"gitHead": "
|
|
63
|
+
"gitHead": "bc0085f5c8ad4e86ac643618579d541c3bbcaf0b"
|
|
64
64
|
}
|