@percy/core 1.29.0-beta.0 → 1.29.0

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 CHANGED
@@ -64,10 +64,11 @@ function debugSnapshotOptions(snapshot) {
64
64
  function waitForDiscoveryNetworkIdle(page, options) {
65
65
  let {
66
66
  allowedHostnames,
67
- networkIdleTimeout
67
+ networkIdleTimeout,
68
+ captureResponsiveAssetsEnabled
68
69
  } = options;
69
70
  let filter = r => hostnameMatches(allowedHostnames, r.url);
70
- return page.network.idle(filter, networkIdleTimeout);
71
+ return page.network.idle(filter, networkIdleTimeout, captureResponsiveAssetsEnabled);
71
72
  }
72
73
 
73
74
  // Creates an initial resource map for a snapshot containing serialized DOM
@@ -174,18 +175,55 @@ async function* captureSnapshotResources(page, snapshot, options) {
174
175
  mobile,
175
176
  captureForDevices
176
177
  } = options;
178
+ let cookies;
179
+ if (process.env.PERCY_DO_NOT_USE_CAPTURED_COOKIES !== 'true') {
180
+ var _snapshot$domSnapshot;
181
+ cookies = snapshot === null || snapshot === void 0 ? void 0 : (_snapshot$domSnapshot = snapshot.domSnapshot) === null || _snapshot$domSnapshot === void 0 ? void 0 : _snapshot$domSnapshot.cookies;
182
+ }
183
+ if (typeof cookies === 'string' && cookies !== '') {
184
+ cookies = cookies.split('; ').map(c => c.split('='));
185
+ cookies = cookies.map(([key, value]) => {
186
+ return {
187
+ name: key,
188
+ value: value
189
+ };
190
+ });
191
+ }
192
+
193
+ // iterate over device to trigger reqeusts and capture other dpr width
194
+ async function* captureResponsiveAssets() {
195
+ for (const device of captureForDevices) {
196
+ discovery = {
197
+ ...discovery,
198
+ captureResponsiveAssetsEnabled: true
199
+ };
200
+
201
+ // We are not adding these widths and pixels ratios in loop below because we want to explicitly reload the page after resize which we dont do below
202
+ yield* captureSnapshotResources(page, {
203
+ ...snapshot,
204
+ discovery,
205
+ widths: [device.width]
206
+ }, {
207
+ deviceScaleFactor: device.deviceScaleFactor,
208
+ mobile: true
209
+ });
210
+ yield waitForDiscoveryNetworkIdle(page, discovery);
211
+ }
212
+ }
177
213
 
178
214
  // used to take snapshots and remove any discovered root resource
179
- let takeSnapshot = async (options, width) => {
215
+ async function* takeSnapshot(options, width) {
180
216
  if (captureWidths) options = {
181
217
  ...options,
182
218
  width
183
219
  };
184
220
  let captured = await page.snapshot(options);
221
+ yield* captureResponsiveAssets();
185
222
  captured.resources.delete(normalizeURL(captured.url));
186
223
  capture(processSnapshotResources(captured));
187
224
  return captured;
188
- };
225
+ }
226
+ ;
189
227
 
190
228
  // used to resize the using capture options
191
229
  let resizePage = width => page.resize({
@@ -197,7 +235,9 @@ async function* captureSnapshotResources(page, snapshot, options) {
197
235
 
198
236
  // navigate to the url
199
237
  yield resizePage(snapshot.widths[0]);
200
- yield page.goto(snapshot.url);
238
+ yield page.goto(snapshot.url, {
239
+ cookies
240
+ });
201
241
  if (snapshot.execute) {
202
242
  // when any execute options are provided, inject snapshot options
203
243
  /* istanbul ignore next: cannot detect coverage of injected code */
@@ -226,25 +266,10 @@ async function* captureSnapshotResources(page, snapshot, options) {
226
266
  } = snap;
227
267
  let [width] = widths;
228
268
 
229
- // iterate over device to trigger reqeusts and capture other dpr width
230
- if (captureForDevices) {
231
- for (const device of captureForDevices) {
232
- yield waitForDiscoveryNetworkIdle(page, discovery);
233
- // We are not adding these widths and pixels ratios in loop below because we want to explicitly reload the page after resize which we dont do below
234
- yield* captureSnapshotResources(page, {
235
- ...snapshot,
236
- widths: [device.width]
237
- }, {
238
- deviceScaleFactor: device.deviceScaleFactor,
239
- mobile: true
240
- });
241
- }
242
- }
243
-
244
269
  // iterate over widths to trigger reqeusts and capture other widths
245
270
  if (isBaseSnapshot || captureWidths) {
246
271
  for (let i = 0; i < widths.length - 1; i++) {
247
- if (captureWidths) yield takeSnapshot(snap, width);
272
+ if (captureWidths) yield* takeSnapshot(snap, width);
248
273
  yield page.evaluate(execute === null || execute === void 0 ? void 0 : execute.beforeResize);
249
274
  yield waitForDiscoveryNetworkIdle(page, discovery);
250
275
  yield resizePage(width = widths[i + 1]);
@@ -253,7 +278,7 @@ async function* captureSnapshotResources(page, snapshot, options) {
253
278
  }
254
279
  if (capture && !snapshot.domSnapshot) {
255
280
  // capture this snapshot and update the base snapshot after capture
256
- let captured = yield takeSnapshot(snap, width);
281
+ let captured = yield* takeSnapshot(snap, width);
257
282
  if (isBaseSnapshot) baseSnapshot = captured;
258
283
 
259
284
  // resize back to the initial width when capturing additional snapshot widths
@@ -272,6 +297,7 @@ async function* captureSnapshotResources(page, snapshot, options) {
272
297
  // wait for final network idle when not capturing DOM
273
298
  if (capture && snapshot.domSnapshot) {
274
299
  yield waitForDiscoveryNetworkIdle(page, discovery);
300
+ yield* captureResponsiveAssets();
275
301
  capture(processSnapshotResources(snapshot));
276
302
  }
277
303
  }
package/dist/network.js CHANGED
@@ -71,7 +71,7 @@ export class Network {
71
71
  }
72
72
 
73
73
  // Resolves after the timeout when there are no more in-flight requests.
74
- async idle(filter = () => true, timeout = this.timeout) {
74
+ async idle(filter = () => true, timeout = this.timeout, captureResponsiveAssetsEnabled = false) {
75
75
  let requests = [];
76
76
  this.log.debug(`Wait for ${timeout}ms idle`, this.meta);
77
77
  await waitFor(() => {
@@ -91,11 +91,25 @@ export class Network {
91
91
  idle: timeout
92
92
  }).catch(error => {
93
93
  if (error.message.startsWith('Timeout')) {
94
- this._throwTimeoutError('Timed out waiting for network requests to idle.', filter);
94
+ let message = 'Timed out waiting for network requests to idle.';
95
+ if (captureResponsiveAssetsEnabled) message += '\nWhile capturing responsive assets try setting PERCY_DO_NOT_CAPTURE_RESPONSIVE_ASSETS to true.';
96
+ this._throwTimeoutError(message, filter);
95
97
  } else {
96
98
  throw error;
97
99
  }
98
100
  });
101
+
102
+ // After waiting for network to idle check if there are still some request
103
+ const activeRequests = this.getActiveRequests(filter);
104
+ /* istanbul ignore if: race condition, very hard to mock this */
105
+ if (activeRequests.length > 0) {
106
+ this.log.debug(`There are ${activeRequests.length} active requests pending during asset discovery. Try increasing the networkIdleTimeout to resolve this issue. \n ${activeRequests}`);
107
+ }
108
+ }
109
+ getActiveRequests(filter) {
110
+ let requests = Array.from(this.#requests.values()).filter(filter);
111
+ requests = requests.filter(req => !this.#finishedUrls.has(req.url));
112
+ return requests;
99
113
  }
100
114
 
101
115
  // Validates that requestId is still valid as sometimes request gets cancelled and we have already executed
package/dist/page.js CHANGED
@@ -41,19 +41,38 @@ export class Page {
41
41
  width
42
42
  });
43
43
  }
44
+ mergeCookies(userPassedCookie, autoCapturedCookie) {
45
+ if (!autoCapturedCookie) return userPassedCookie;
46
+ if (userPassedCookie.length === 0) return autoCapturedCookie;
47
+
48
+ // User passed cookie will be prioritized over auto captured cookie
49
+ const mergedCookies = [...userPassedCookie, ...autoCapturedCookie];
50
+ const uniqueCookies = [];
51
+ const names = new Set();
52
+ for (const cookie of mergedCookies) {
53
+ if (!names.has(cookie.name)) {
54
+ uniqueCookies.push(cookie);
55
+ names.add(cookie.name);
56
+ }
57
+ }
58
+ return uniqueCookies;
59
+ }
44
60
 
45
61
  // Go to a URL and wait for navigation to occur
46
62
  async goto(url, {
47
- waitUntil = 'load'
63
+ waitUntil = 'load',
64
+ cookies
48
65
  } = {}) {
49
66
  this.log.debug(`Navigate to: ${url}`, this.meta);
50
67
  let navigate = async () => {
68
+ const userPassedCookie = this.session.browser.cookies;
51
69
  // set cookies before navigation so we can default the domain to this hostname
52
- if (this.session.browser.cookies.length) {
70
+ if (userPassedCookie.length || cookies) {
53
71
  let defaultDomain = hostname(url);
72
+ cookies = this.mergeCookies(userPassedCookie, cookies);
54
73
  await this.session.send('Network.setCookies', {
55
74
  // spread is used to make a shallow copy of the cookie
56
- cookies: this.session.browser.cookies.map(({
75
+ cookies: cookies.map(({
57
76
  ...cookie
58
77
  }) => {
59
78
  if (!cookie.url) cookie.domain || (cookie.domain = defaultDomain);
package/dist/timing.js CHANGED
@@ -15,7 +15,7 @@ export default class TimeIt {
15
15
  return await callback();
16
16
  } finally {
17
17
  const duration = Date.now() - startTime;
18
- this.log.info(`${name} - ${identifier} - ${duration / 1000}s`);
18
+ this.log.debug(`${name} - ${identifier} - ${duration / 1000}s`);
19
19
  }
20
20
  }
21
21
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@percy/core",
3
- "version": "1.29.0-beta.0",
3
+ "version": "1.29.0",
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": "beta"
12
+ "tag": "latest"
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.29.0-beta.0",
47
- "@percy/config": "1.29.0-beta.0",
48
- "@percy/dom": "1.29.0-beta.0",
49
- "@percy/logger": "1.29.0-beta.0",
50
- "@percy/webdriver-utils": "1.29.0-beta.0",
46
+ "@percy/client": "1.29.0",
47
+ "@percy/config": "1.29.0",
48
+ "@percy/dom": "1.29.0",
49
+ "@percy/logger": "1.29.0",
50
+ "@percy/webdriver-utils": "1.29.0",
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": "2d62f6ce1e9b7aa1430d186da00a2302884d92b2"
63
+ "gitHead": "5fed3bcc30798d4447b70ee57ea6331e8ec9b501"
64
64
  }