@percy/core 1.28.0 → 1.28.1-alpha.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/api.js CHANGED
@@ -117,10 +117,10 @@ export function createPercyServer(percy, port) {
117
117
  const snapshotPromise = new Promise((resolve, reject) => percy.upload(req.body, {
118
118
  resolve,
119
119
  reject
120
- }));
120
+ }, 'app'));
121
121
  data = await handleSyncJob(snapshotPromise, percy, 'comparison');
122
122
  } else {
123
- let upload = percy.upload(req.body);
123
+ let upload = percy.upload(req.body, null, 'app');
124
124
  if (req.url.searchParams.has('await')) await upload;
125
125
  }
126
126
 
@@ -164,10 +164,10 @@ export function createPercyServer(percy, port) {
164
164
  const snapshotPromise = new Promise((resolve, reject) => percy.upload(comparisonData, {
165
165
  resolve,
166
166
  reject
167
- }));
167
+ }, 'automate'));
168
168
  data = await handleSyncJob(snapshotPromise, percy, 'comparison');
169
169
  } else {
170
- percy.upload(comparisonData);
170
+ percy.upload(comparisonData, null, 'automate');
171
171
  }
172
172
  res.json(200, {
173
173
  success: true,
package/dist/config.js CHANGED
@@ -249,6 +249,10 @@ export const configSchema = {
249
249
  type: 'integer',
250
250
  minimum: 1
251
251
  },
252
+ retry: {
253
+ type: 'boolean',
254
+ default: false
255
+ },
252
256
  launchOptions: {
253
257
  type: 'object',
254
258
  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 } from './utils.js';
3
+ import { normalizeURL, hostnameMatches, createResource, createRootResource, createPercyCSSResource, createLogResource, yieldAll, withRetries } from './utils.js';
4
4
 
5
5
  // Logs verbose debug logs detailing various snapshot options.
6
6
  function debugSnapshotOptions(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;
@@ -317,39 +318,46 @@ export function createDiscoveryQueue(percy) {
317
318
  /* istanbul ignore next: tested, but coverage is stripped */
318
319
  let assetDiscoveryPageEnableJS = snapshot.cliEnableJavaScript && !snapshot.domSnapshot || (snapshot.enableJavaScript ?? !snapshot.domSnapshot);
319
320
  percy.log.debug(`Asset discovery Browser Page enable JS: ${assetDiscoveryPageEnableJS}`);
320
- // create a new browser page
321
- let page = yield percy.browser.page({
322
- enableJavaScript: assetDiscoveryPageEnableJS,
323
- networkIdleTimeout: snapshot.discovery.networkIdleTimeout,
324
- requestHeaders: snapshot.discovery.requestHeaders,
325
- authorization: snapshot.discovery.authorization,
326
- userAgent: snapshot.discovery.userAgent,
327
- captureMockedServiceWorker: snapshot.discovery.captureMockedServiceWorker,
328
- meta: snapshot.meta,
329
- // enable network inteception
330
- intercept: {
331
- enableJavaScript: snapshot.enableJavaScript,
332
- disableCache: snapshot.discovery.disableCache,
333
- allowedHostnames: snapshot.discovery.allowedHostnames,
334
- disallowedHostnames: snapshot.discovery.disallowedHostnames,
335
- getResource: u => snapshot.resources.get(u) || cache.get(u),
336
- saveResource: r => {
337
- snapshot.resources.set(r.url, r);
338
- if (!r.root) {
339
- cache.set(r.url, r);
321
+ await withRetries(async function* () {
322
+ // create a new browser page
323
+ let page = yield percy.browser.page({
324
+ enableJavaScript: assetDiscoveryPageEnableJS,
325
+ networkIdleTimeout: snapshot.discovery.networkIdleTimeout,
326
+ requestHeaders: snapshot.discovery.requestHeaders,
327
+ authorization: snapshot.discovery.authorization,
328
+ userAgent: snapshot.discovery.userAgent,
329
+ captureMockedServiceWorker: snapshot.discovery.captureMockedServiceWorker,
330
+ meta: snapshot.meta,
331
+ // enable network inteception
332
+ intercept: {
333
+ enableJavaScript: snapshot.enableJavaScript,
334
+ disableCache: snapshot.discovery.disableCache,
335
+ allowedHostnames: snapshot.discovery.allowedHostnames,
336
+ disallowedHostnames: snapshot.discovery.disallowedHostnames,
337
+ getResource: u => snapshot.resources.get(u) || cache.get(u),
338
+ saveResource: r => {
339
+ snapshot.resources.set(r.url, r);
340
+ if (!r.root) {
341
+ cache.set(r.url, r);
342
+ }
340
343
  }
341
344
  }
345
+ });
346
+ try {
347
+ yield* captureSnapshotResources(page, snapshot, {
348
+ captureWidths: !snapshot.domSnapshot && percy.deferUploads,
349
+ capture: callback
350
+ });
351
+ } finally {
352
+ // always close the page when done
353
+ await page.close();
354
+ }
355
+ }, {
356
+ count: retry ? 3 : 1,
357
+ onRetry: () => {
358
+ percy.log.debug(`Retrying snapshot: ${snapshot.name}`, snapshot.meta);
342
359
  }
343
360
  });
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
361
  }).handle('error', ({
354
362
  name,
355
363
  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/percy.js CHANGED
@@ -333,7 +333,7 @@ export class Percy {
333
333
  }
334
334
 
335
335
  // Uploads one or more snapshots directly to the current Percy build
336
- upload(options, callback = null) {
336
+ upload(options, callback = null, screenshotFlow = null) {
337
337
  if (this.readyState !== 1) {
338
338
  throw new Error('Not running');
339
339
  } else if (Array.isArray(options)) {
@@ -364,6 +364,7 @@ export class Percy {
364
364
  // add client & environment info
365
365
  this.client.addClientInfo(options.clientInfo);
366
366
  this.client.addEnvironmentInfo(options.environmentInfo);
367
+ this.client.screenshotFlow = screenshotFlow;
367
368
 
368
369
  // Sync CLI support, attached resolve, reject promise
369
370
  if (this.syncMode(options)) {
package/dist/snapshot.js CHANGED
@@ -344,6 +344,7 @@ export function createSnapshotsQueue(percy) {
344
344
  // on start, create a new Percy build
345
345
  .handle('start', async () => {
346
346
  try {
347
+ var _data$attributes;
347
348
  build = percy.build = {};
348
349
  let {
349
350
  data
@@ -352,6 +353,7 @@ export function createSnapshotsQueue(percy) {
352
353
  });
353
354
  let url = data.attributes['web-url'];
354
355
  let number = data.attributes['build-number'];
356
+ percy.client.buildType = (_data$attributes = data.attributes) === null || _data$attributes === void 0 ? void 0 : _data$attributes.type;
355
357
  Object.assign(build, {
356
358
  id: data.id,
357
359
  url,
@@ -420,7 +422,11 @@ export function createSnapshotsQueue(percy) {
420
422
  name,
421
423
  meta
422
424
  } = snapshot;
423
-
425
+ if (percy.client.screenshotFlow === 'automate' && percy.client.buildType !== 'automate') {
426
+ throw new Error(`Cannot run automate screenshots in ${percy.client.buildType} project. Please use automate project token`);
427
+ } else if (percy.client.screenshotFlow === 'app' && percy.client.buildType !== 'app') {
428
+ throw new Error(`Cannot run App Percy screenshots in ${percy.client.buildType} project. Please use App Percy project token`);
429
+ }
424
430
  // yield to evaluated snapshot resources
425
431
  snapshot.resources = typeof resources === 'function' ? yield* yieldTo(resources()) : resources;
426
432
 
package/dist/utils.js CHANGED
@@ -328,6 +328,25 @@ export function serializeFunction(fn) {
328
328
  }
329
329
  return fnbody;
330
330
  }
331
+ export async function withRetries(fn, {
332
+ count,
333
+ onRetry
334
+ }) {
335
+ count || (count = 1); // default a single try
336
+ let run = 0;
337
+ while (true) {
338
+ run += 1;
339
+ try {
340
+ return await generatePromise(fn);
341
+ } catch (e) {
342
+ if (run < count) {
343
+ await (onRetry === null || onRetry === void 0 ? void 0 : onRetry());
344
+ continue;
345
+ }
346
+ throw e;
347
+ }
348
+ }
349
+ }
331
350
 
332
351
  // DefaultMap, which returns a default value for an uninitialized key
333
352
  // Similar to defaultDict in python
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@percy/core",
3
- "version": "1.28.0",
3
+ "version": "1.28.1-alpha.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": "latest"
12
+ "tag": "alpha"
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.0",
47
- "@percy/config": "1.28.0",
48
- "@percy/dom": "1.28.0",
49
- "@percy/logger": "1.28.0",
50
- "@percy/webdriver-utils": "1.28.0",
46
+ "@percy/client": "1.28.1-alpha.2",
47
+ "@percy/config": "1.28.1-alpha.2",
48
+ "@percy/dom": "1.28.1-alpha.2",
49
+ "@percy/logger": "1.28.1-alpha.2",
50
+ "@percy/webdriver-utils": "1.28.1-alpha.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": "9d95f18e45e37aa3683e5b8276fd85cf07dba8cb"
61
+ "gitHead": "a3f2e709d0a6445e15a1128686578b1659243a95"
62
62
  }