@percy/core 1.31.14-beta.3 → 1.31.14-beta.5
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/config.js +93 -0
- package/dist/page.js +26 -2
- package/dist/snapshot.js +21 -0
- package/package.json +9 -9
package/dist/config.js
CHANGED
|
@@ -151,6 +151,91 @@ export const configSchema = {
|
|
|
151
151
|
sync: {
|
|
152
152
|
type: 'boolean'
|
|
153
153
|
},
|
|
154
|
+
readiness: {
|
|
155
|
+
type: 'object',
|
|
156
|
+
additionalProperties: false,
|
|
157
|
+
properties: {
|
|
158
|
+
preset: {
|
|
159
|
+
type: 'string',
|
|
160
|
+
enum: ['balanced', 'strict', 'fast', 'disabled']
|
|
161
|
+
},
|
|
162
|
+
stabilityWindowMs: {
|
|
163
|
+
type: 'integer',
|
|
164
|
+
minimum: 50,
|
|
165
|
+
maximum: 30000
|
|
166
|
+
},
|
|
167
|
+
jsIdleWindowMs: {
|
|
168
|
+
type: 'integer',
|
|
169
|
+
minimum: 50,
|
|
170
|
+
maximum: 30000
|
|
171
|
+
},
|
|
172
|
+
networkIdleWindowMs: {
|
|
173
|
+
type: 'integer',
|
|
174
|
+
minimum: 50,
|
|
175
|
+
maximum: 10000
|
|
176
|
+
},
|
|
177
|
+
timeoutMs: {
|
|
178
|
+
type: 'integer',
|
|
179
|
+
minimum: 1000,
|
|
180
|
+
maximum: 60000
|
|
181
|
+
},
|
|
182
|
+
domStability: {
|
|
183
|
+
type: 'boolean'
|
|
184
|
+
},
|
|
185
|
+
imageReady: {
|
|
186
|
+
type: 'boolean'
|
|
187
|
+
},
|
|
188
|
+
fontReady: {
|
|
189
|
+
type: 'boolean'
|
|
190
|
+
},
|
|
191
|
+
jsIdle: {
|
|
192
|
+
type: 'boolean'
|
|
193
|
+
},
|
|
194
|
+
readySelectors: {
|
|
195
|
+
type: 'array',
|
|
196
|
+
items: {
|
|
197
|
+
oneOf: [{
|
|
198
|
+
type: 'string'
|
|
199
|
+
}, {
|
|
200
|
+
type: 'object',
|
|
201
|
+
additionalProperties: false,
|
|
202
|
+
properties: {
|
|
203
|
+
css: {
|
|
204
|
+
type: 'string'
|
|
205
|
+
},
|
|
206
|
+
xpath: {
|
|
207
|
+
type: 'string'
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
}]
|
|
211
|
+
}
|
|
212
|
+
},
|
|
213
|
+
notPresentSelectors: {
|
|
214
|
+
type: 'array',
|
|
215
|
+
items: {
|
|
216
|
+
oneOf: [{
|
|
217
|
+
type: 'string'
|
|
218
|
+
}, {
|
|
219
|
+
type: 'object',
|
|
220
|
+
additionalProperties: false,
|
|
221
|
+
properties: {
|
|
222
|
+
css: {
|
|
223
|
+
type: 'string'
|
|
224
|
+
},
|
|
225
|
+
xpath: {
|
|
226
|
+
type: 'string'
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
}]
|
|
230
|
+
}
|
|
231
|
+
},
|
|
232
|
+
maxTimeoutMs: {
|
|
233
|
+
type: 'integer',
|
|
234
|
+
minimum: 1000,
|
|
235
|
+
maximum: 60000
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
},
|
|
154
239
|
responsiveSnapshotCapture: {
|
|
155
240
|
type: 'boolean',
|
|
156
241
|
default: false
|
|
@@ -612,6 +697,9 @@ export const snapshotSchema = {
|
|
|
612
697
|
sync: {
|
|
613
698
|
$ref: '/config/snapshot#/properties/sync'
|
|
614
699
|
},
|
|
700
|
+
readiness: {
|
|
701
|
+
$ref: '/config/snapshot#/properties/readiness'
|
|
702
|
+
},
|
|
615
703
|
responsiveSnapshotCapture: {
|
|
616
704
|
$ref: '/config/snapshot#/properties/responsiveSnapshotCapture'
|
|
617
705
|
},
|
|
@@ -945,6 +1033,11 @@ export const snapshotSchema = {
|
|
|
945
1033
|
type: 'string'
|
|
946
1034
|
}
|
|
947
1035
|
},
|
|
1036
|
+
readiness_diagnostics: {
|
|
1037
|
+
type: 'object',
|
|
1038
|
+
normalize: false,
|
|
1039
|
+
description: 'Diagnostics from readiness checks run before serialization. ' + 'normalize: false preserves the snake_case wire format the SDKs send (timed_out, ' + 'total_duration_ms, etc.) instead of camelCasing inner keys at validate time.'
|
|
1040
|
+
},
|
|
948
1041
|
corsIframes: {
|
|
949
1042
|
type: 'array',
|
|
950
1043
|
items: {
|
package/dist/page.js
CHANGED
|
@@ -232,6 +232,7 @@ export class Page {
|
|
|
232
232
|
execute,
|
|
233
233
|
...snapshot
|
|
234
234
|
}) {
|
|
235
|
+
var _this$browser;
|
|
235
236
|
let {
|
|
236
237
|
name,
|
|
237
238
|
width,
|
|
@@ -291,8 +292,24 @@ export class Page {
|
|
|
291
292
|
}
|
|
292
293
|
await this.insertPercyDom();
|
|
293
294
|
|
|
294
|
-
//
|
|
295
|
-
this.
|
|
295
|
+
// Run readiness checks before serializing — wait for page stability
|
|
296
|
+
let readiness = snapshot.readiness || ((_this$browser = this.browser) === null || _this$browser === void 0 || (_this$browser = _this$browser.percy) === null || _this$browser === void 0 || (_this$browser = _this$browser.config) === null || _this$browser === void 0 || (_this$browser = _this$browser.snapshot) === null || _this$browser === void 0 ? void 0 : _this$browser.readiness);
|
|
297
|
+
let readinessDiagnostics;
|
|
298
|
+
if (readiness && readiness.preset !== 'disabled') {
|
|
299
|
+
var _readinessDiagnostics;
|
|
300
|
+
this.log.debug('Waiting for readiness', this.meta);
|
|
301
|
+
readinessDiagnostics = await this.eval(/* istanbul ignore next: no instrumenting injected code */
|
|
302
|
+
async (_, config) => {
|
|
303
|
+
var _PercyDOM;
|
|
304
|
+
// eslint-disable-next-line no-undef
|
|
305
|
+
if (typeof ((_PercyDOM = PercyDOM) === null || _PercyDOM === void 0 ? void 0 : _PercyDOM.waitForReady) === 'function') return PercyDOM.waitForReady(config);
|
|
306
|
+
}, readiness).catch(e => {
|
|
307
|
+
this.log.debug(`Readiness check failed: ${e}`, this.meta);
|
|
308
|
+
});
|
|
309
|
+
if ((_readinessDiagnostics = readinessDiagnostics) !== null && _readinessDiagnostics !== void 0 && _readinessDiagnostics.timed_out) {
|
|
310
|
+
this.log.debug('Readiness timed out, capturing anyway', this.meta);
|
|
311
|
+
}
|
|
312
|
+
}
|
|
296
313
|
let capture = await this.eval(serializeDomCapture, {
|
|
297
314
|
enableJavaScript,
|
|
298
315
|
disableShadowDOM,
|
|
@@ -304,6 +321,13 @@ export class Page {
|
|
|
304
321
|
ignoreIframeSelectors,
|
|
305
322
|
pseudoClassEnabledElements
|
|
306
323
|
});
|
|
324
|
+
|
|
325
|
+
// Attach readiness diagnostics onto the captured DOM snapshot so the backend/UI can surface
|
|
326
|
+
// readiness metrics. Only valid when domSnapshot is the structured object form — the legacy
|
|
327
|
+
// string form (HTML only) has no place to embed diagnostics.
|
|
328
|
+
if (readinessDiagnostics && capture !== null && capture !== void 0 && capture.domSnapshot && typeof capture.domSnapshot === 'object') {
|
|
329
|
+
capture.domSnapshot.readiness_diagnostics = readinessDiagnostics;
|
|
330
|
+
}
|
|
307
331
|
return {
|
|
308
332
|
...snapshot,
|
|
309
333
|
...capture
|
package/dist/snapshot.js
CHANGED
|
@@ -231,6 +231,27 @@ export function validateSnapshotOptions(options) {
|
|
|
231
231
|
log.warn('Encountered snapshot serialization warnings:');
|
|
232
232
|
for (let w of domWarnings) log.warn(`- ${w}`);
|
|
233
233
|
}
|
|
234
|
+
|
|
235
|
+
// log readiness diagnostics when present.
|
|
236
|
+
// domSnapshot is a union of `string` (legacy SDK payload — HTML only) and `object`
|
|
237
|
+
// ({ html, warnings, readiness_diagnostics, ... }). Diagnostics only exist on the object form;
|
|
238
|
+
// gate explicitly on typeof so the intent is obvious to readers.
|
|
239
|
+
// The schema marks readiness_diagnostics with normalize: false to preserve the snake_case wire
|
|
240
|
+
// format. The dual-read fallback below is defensive — it keeps the log working even if a future
|
|
241
|
+
// SDK sends camelCase keys, or if a path in PercyConfig.migrate skips the normalize: false hint.
|
|
242
|
+
let domSnapshotObj = migrated.domSnapshot && typeof migrated.domSnapshot === 'object' ? migrated.domSnapshot : null;
|
|
243
|
+
let readinessDiag = (domSnapshotObj === null || domSnapshotObj === void 0 ? void 0 : domSnapshotObj.readiness_diagnostics) ?? (domSnapshotObj === null || domSnapshotObj === void 0 ? void 0 : domSnapshotObj.readinessDiagnostics);
|
|
244
|
+
if (readinessDiag) {
|
|
245
|
+
let timedOut = readinessDiag.timed_out ?? readinessDiag.timedOut;
|
|
246
|
+
let durationMs = readinessDiag.total_duration_ms ?? readinessDiag.totalDurationMs;
|
|
247
|
+
let presetName = readinessDiag.preset || 'custom';
|
|
248
|
+
if (timedOut) {
|
|
249
|
+
log.warn(`Readiness timed out after ${durationMs}ms (preset: ${presetName})`);
|
|
250
|
+
} else {
|
|
251
|
+
log.debug(`Readiness passed in ${durationMs}ms (preset: ${presetName})`);
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
|
|
234
255
|
// warn on validation errors
|
|
235
256
|
let errors = PercyConfig.validate(migrated, schema);
|
|
236
257
|
if ((errors === null || errors === void 0 ? void 0 : errors.length) > 0) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@percy/core",
|
|
3
|
-
"version": "1.31.14-beta.
|
|
3
|
+
"version": "1.31.14-beta.5",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -44,12 +44,12 @@
|
|
|
44
44
|
"test:types": "tsd"
|
|
45
45
|
},
|
|
46
46
|
"dependencies": {
|
|
47
|
-
"@percy/client": "1.31.14-beta.
|
|
48
|
-
"@percy/config": "1.31.14-beta.
|
|
49
|
-
"@percy/dom": "1.31.14-beta.
|
|
50
|
-
"@percy/logger": "1.31.14-beta.
|
|
51
|
-
"@percy/monitoring": "1.31.14-beta.
|
|
52
|
-
"@percy/webdriver-utils": "1.31.14-beta.
|
|
47
|
+
"@percy/client": "1.31.14-beta.5",
|
|
48
|
+
"@percy/config": "1.31.14-beta.5",
|
|
49
|
+
"@percy/dom": "1.31.14-beta.5",
|
|
50
|
+
"@percy/logger": "1.31.14-beta.5",
|
|
51
|
+
"@percy/monitoring": "1.31.14-beta.5",
|
|
52
|
+
"@percy/webdriver-utils": "1.31.14-beta.5",
|
|
53
53
|
"content-disposition": "^0.5.4",
|
|
54
54
|
"cross-spawn": "^7.0.3",
|
|
55
55
|
"extract-zip": "^2.0.1",
|
|
@@ -63,7 +63,7 @@
|
|
|
63
63
|
"yaml": "^2.4.1"
|
|
64
64
|
},
|
|
65
65
|
"optionalDependencies": {
|
|
66
|
-
"@percy/cli-doctor": "1.31.14-beta.
|
|
66
|
+
"@percy/cli-doctor": "1.31.14-beta.5"
|
|
67
67
|
},
|
|
68
|
-
"gitHead": "
|
|
68
|
+
"gitHead": "5a92d9e34d219d2c9a46d74a020de81814973370"
|
|
69
69
|
}
|