@percy/core 1.30.8 → 1.30.9-alpha-1.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/config.js +127 -0
- package/dist/network.js +6 -1
- package/dist/queue.js +8 -0
- package/dist/snapshot.js +2 -3
- package/dist/utils.js +30 -0
- package/package.json +9 -9
- package/test/helpers/server.js +10 -3
package/dist/config.js
CHANGED
|
@@ -26,6 +26,33 @@ export const configSchema = {
|
|
|
26
26
|
snapshot: {
|
|
27
27
|
type: 'object',
|
|
28
28
|
additionalProperties: false,
|
|
29
|
+
definitions: {
|
|
30
|
+
configurationProperties: {
|
|
31
|
+
type: 'object',
|
|
32
|
+
additionalProperties: false,
|
|
33
|
+
properties: {
|
|
34
|
+
diffSensitivity: {
|
|
35
|
+
type: 'integer',
|
|
36
|
+
minimum: 0,
|
|
37
|
+
maximum: 4
|
|
38
|
+
},
|
|
39
|
+
imageIgnoreThreshold: {
|
|
40
|
+
type: 'number',
|
|
41
|
+
minimum: 0,
|
|
42
|
+
maximum: 1
|
|
43
|
+
},
|
|
44
|
+
carouselsEnabled: {
|
|
45
|
+
type: 'boolean'
|
|
46
|
+
},
|
|
47
|
+
bannersEnabled: {
|
|
48
|
+
type: 'boolean'
|
|
49
|
+
},
|
|
50
|
+
adsEnabled: {
|
|
51
|
+
type: 'boolean'
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
},
|
|
29
56
|
properties: {
|
|
30
57
|
widths: {
|
|
31
58
|
type: 'array',
|
|
@@ -164,6 +191,88 @@ export const configSchema = {
|
|
|
164
191
|
}
|
|
165
192
|
}
|
|
166
193
|
}
|
|
194
|
+
},
|
|
195
|
+
regions: {
|
|
196
|
+
type: 'array',
|
|
197
|
+
items: {
|
|
198
|
+
type: 'object',
|
|
199
|
+
properties: {
|
|
200
|
+
elementSelector: {
|
|
201
|
+
type: 'object',
|
|
202
|
+
additionalProperties: false,
|
|
203
|
+
properties: {
|
|
204
|
+
boundingBox: {
|
|
205
|
+
type: 'object',
|
|
206
|
+
additionalProperties: false,
|
|
207
|
+
properties: {
|
|
208
|
+
x: {
|
|
209
|
+
type: 'integer'
|
|
210
|
+
},
|
|
211
|
+
y: {
|
|
212
|
+
type: 'integer'
|
|
213
|
+
},
|
|
214
|
+
width: {
|
|
215
|
+
type: 'integer'
|
|
216
|
+
},
|
|
217
|
+
height: {
|
|
218
|
+
type: 'integer'
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
},
|
|
222
|
+
elementXpath: {
|
|
223
|
+
type: 'string'
|
|
224
|
+
},
|
|
225
|
+
elementCSS: {
|
|
226
|
+
type: 'string'
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
},
|
|
230
|
+
padding: {
|
|
231
|
+
type: 'object',
|
|
232
|
+
additionalProperties: false,
|
|
233
|
+
properties: {
|
|
234
|
+
top: {
|
|
235
|
+
type: 'integer'
|
|
236
|
+
},
|
|
237
|
+
bottom: {
|
|
238
|
+
type: 'integer'
|
|
239
|
+
},
|
|
240
|
+
left: {
|
|
241
|
+
type: 'integer'
|
|
242
|
+
},
|
|
243
|
+
right: {
|
|
244
|
+
type: 'integer'
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
},
|
|
248
|
+
algorithm: {
|
|
249
|
+
type: 'string',
|
|
250
|
+
enum: ['standard', 'layout', 'ignore', 'intelliignore']
|
|
251
|
+
},
|
|
252
|
+
configuration: {
|
|
253
|
+
$ref: '#/definitions/configurationProperties'
|
|
254
|
+
},
|
|
255
|
+
assertion: {
|
|
256
|
+
type: 'object',
|
|
257
|
+
additionalProperties: false,
|
|
258
|
+
properties: {
|
|
259
|
+
diffIgnoreThreshold: {
|
|
260
|
+
type: 'number',
|
|
261
|
+
minimum: 0,
|
|
262
|
+
maximum: 1
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
},
|
|
267
|
+
required: ['algorithm']
|
|
268
|
+
}
|
|
269
|
+
},
|
|
270
|
+
algorithm: {
|
|
271
|
+
type: 'string',
|
|
272
|
+
enum: ['standard', 'layout', 'intelliignore']
|
|
273
|
+
},
|
|
274
|
+
algorithmConfiguration: {
|
|
275
|
+
$ref: '#/definitions/configurationProperties'
|
|
167
276
|
}
|
|
168
277
|
}
|
|
169
278
|
},
|
|
@@ -370,6 +479,15 @@ export const snapshotSchema = {
|
|
|
370
479
|
reshuffleInvalidTags: {
|
|
371
480
|
$ref: '/config/snapshot#/properties/reshuffleInvalidTags'
|
|
372
481
|
},
|
|
482
|
+
regions: {
|
|
483
|
+
$ref: '/config/snapshot#/properties/regions'
|
|
484
|
+
},
|
|
485
|
+
algorithm: {
|
|
486
|
+
$ref: '/config/snapshot#/properties/algorithm'
|
|
487
|
+
},
|
|
488
|
+
algorithmConfiguration: {
|
|
489
|
+
$ref: '/config/snapshot#/properties/algorithmConfiguration'
|
|
490
|
+
},
|
|
373
491
|
scopeOptions: {
|
|
374
492
|
$ref: '/config/snapshot#/properties/scopeOptions'
|
|
375
493
|
},
|
|
@@ -913,6 +1031,15 @@ export const comparisonSchema = {
|
|
|
913
1031
|
ignoreElementsData: regionsSchema
|
|
914
1032
|
}
|
|
915
1033
|
},
|
|
1034
|
+
regions: {
|
|
1035
|
+
$ref: '/config/snapshot#/properties/regions'
|
|
1036
|
+
},
|
|
1037
|
+
algorithm: {
|
|
1038
|
+
$ref: '/config/snapshot#/properties/algorithm'
|
|
1039
|
+
},
|
|
1040
|
+
algorithmConfiguration: {
|
|
1041
|
+
$ref: '/config/snapshot#/properties/algorithmConfiguration'
|
|
1042
|
+
},
|
|
916
1043
|
consideredElementsData: {
|
|
917
1044
|
type: 'object',
|
|
918
1045
|
additionalProperties: false,
|
package/dist/network.js
CHANGED
|
@@ -491,6 +491,7 @@ async function makeDirectRequest(network, request, session) {
|
|
|
491
491
|
|
|
492
492
|
// Save a resource from a request, skipping it if specific paramters are not met
|
|
493
493
|
async function saveResponseResource(network, request, session) {
|
|
494
|
+
var _response$headers;
|
|
494
495
|
let {
|
|
495
496
|
disableCache,
|
|
496
497
|
allowedHostnames,
|
|
@@ -507,7 +508,8 @@ async function saveResponseResource(network, request, session) {
|
|
|
507
508
|
// Checing for content length more than 100MB, to prevent websocket error which is governed by
|
|
508
509
|
// maxPayload option of websocket defaulted to 100MB.
|
|
509
510
|
// If content-length is more than our allowed 25MB, no need to process that resouce we can return log.
|
|
510
|
-
let contentLength =
|
|
511
|
+
let contentLength = (_response$headers = response.headers) === null || _response$headers === void 0 ? void 0 : _response$headers[Object.keys(response.headers).find(key => key.toLowerCase() === 'content-length')];
|
|
512
|
+
contentLength = parseInt(contentLength);
|
|
511
513
|
if (contentLength > MAX_RESOURCE_SIZE) {
|
|
512
514
|
return log.debug('- Skipping resource larger than 25MB', meta);
|
|
513
515
|
}
|
|
@@ -527,6 +529,9 @@ async function saveResponseResource(network, request, session) {
|
|
|
527
529
|
return log.debug('- Skipping remote resource', meta);
|
|
528
530
|
} else if (!body.length) {
|
|
529
531
|
return log.debug('- Skipping empty response', meta);
|
|
532
|
+
} else if (body.length > MAX_RESOURCE_SIZE) {
|
|
533
|
+
log.debug('- Missing headers for the requested resource.', meta);
|
|
534
|
+
return log.debug('- Skipping resource larger than 25MB', meta);
|
|
530
535
|
} else if (!ALLOWED_STATUSES.includes(response.status)) {
|
|
531
536
|
return log.debug(`- Skipping disallowed status [${response.status}]`, meta);
|
|
532
537
|
} else if (!enableJavaScript && !ALLOWED_RESOURCES.includes(request.type)) {
|
package/dist/queue.js
CHANGED
|
@@ -115,6 +115,13 @@ export class Queue {
|
|
|
115
115
|
// return the deferred task promise
|
|
116
116
|
return task.deferred;
|
|
117
117
|
}
|
|
118
|
+
logQueueSize() {
|
|
119
|
+
this.log.debug(`${this.name} queueInfo: ${JSON.stringify({
|
|
120
|
+
queued: _classPrivateFieldGet(_queued, this).size,
|
|
121
|
+
pending: _classPrivateFieldGet(_pending, this).size,
|
|
122
|
+
total: _classPrivateFieldGet(_pending, this).size + _classPrivateFieldGet(_queued, this).size
|
|
123
|
+
})}`);
|
|
124
|
+
}
|
|
118
125
|
// Cancels and aborts a specific item task.
|
|
119
126
|
cancel(item) {
|
|
120
127
|
let task = _assertClassBrand(_Queue_brand, this, _find).call(this, item);
|
|
@@ -243,6 +250,7 @@ export class Queue {
|
|
|
243
250
|
// Repeatedly yields, calling the callback with the position of the task within the queue
|
|
244
251
|
}
|
|
245
252
|
function _dequeue() {
|
|
253
|
+
this.logQueueSize();
|
|
246
254
|
if (!_classPrivateFieldGet(_queued, this).size || this.readyState < 2) return;
|
|
247
255
|
if (_classPrivateFieldGet(_pending, this).size >= this.concurrency) return;
|
|
248
256
|
let [task] = _classPrivateFieldGet(_queued, this);
|
package/dist/snapshot.js
CHANGED
|
@@ -3,7 +3,7 @@ import PercyConfig from '@percy/config';
|
|
|
3
3
|
import micromatch from 'micromatch';
|
|
4
4
|
import { configSchema } from './config.js';
|
|
5
5
|
import Queue from './queue.js';
|
|
6
|
-
import { request, hostnameMatches, yieldTo, snapshotLogName, decodeAndEncodeURLWithLogging, compareObjectTypes } from './utils.js';
|
|
6
|
+
import { request, hostnameMatches, yieldTo, snapshotLogName, decodeAndEncodeURLWithLogging, compareObjectTypes, normalizeOptions } from './utils.js';
|
|
7
7
|
import { JobData } from './wait-for-job.js';
|
|
8
8
|
|
|
9
9
|
// Throw a better error message for missing or invalid urls
|
|
@@ -192,9 +192,9 @@ function getSnapshotOptions(options, {
|
|
|
192
192
|
export function validateSnapshotOptions(options) {
|
|
193
193
|
var _migrated$baseUrl, _migrated$domSnapshot;
|
|
194
194
|
let log = logger('core:snapshot');
|
|
195
|
-
|
|
196
195
|
// decide which schema to validate against
|
|
197
196
|
let schema = ['domSnapshot', 'dom-snapshot', 'dom_snapshot'].some(k => k in options) && '/snapshot/dom' || 'url' in options && '/snapshot' || 'sitemap' in options && '/snapshot/sitemap' || 'serve' in options && '/snapshot/server' || 'snapshots' in options && '/snapshot/list' || '/snapshot';
|
|
197
|
+
options = normalizeOptions(options);
|
|
198
198
|
let {
|
|
199
199
|
// normalize, migrate, and remove certain properties from validating
|
|
200
200
|
clientInfo,
|
|
@@ -226,7 +226,6 @@ export function validateSnapshotOptions(options) {
|
|
|
226
226
|
log.warn('Encountered snapshot serialization warnings:');
|
|
227
227
|
for (let w of domWarnings) log.warn(`- ${w}`);
|
|
228
228
|
}
|
|
229
|
-
|
|
230
229
|
// warn on validation errors
|
|
231
230
|
let errors = PercyConfig.validate(migrated, schema);
|
|
232
231
|
if ((errors === null || errors === void 0 ? void 0 : errors.length) > 0) {
|
package/dist/utils.js
CHANGED
|
@@ -52,6 +52,9 @@ export function percyAutomateRequestHandler(req, percy) {
|
|
|
52
52
|
ignoreRegionXpaths: (_percy$config$snapsho4 = percy.config.snapshot.ignoreRegions) === null || _percy$config$snapsho4 === void 0 ? void 0 : _percy$config$snapsho4.ignoreRegionXpaths,
|
|
53
53
|
considerRegionSelectors: (_percy$config$snapsho5 = percy.config.snapshot.considerRegions) === null || _percy$config$snapsho5 === void 0 ? void 0 : _percy$config$snapsho5.considerRegionSelectors,
|
|
54
54
|
considerRegionXpaths: (_percy$config$snapsho6 = percy.config.snapshot.considerRegions) === null || _percy$config$snapsho6 === void 0 ? void 0 : _percy$config$snapsho6.considerRegionXpaths,
|
|
55
|
+
regions: percy.config.snapshot.regions,
|
|
56
|
+
algorithm: percy.config.snapshot.algorithm,
|
|
57
|
+
algorithmConfiguration: percy.config.snapshot.algorithmConfiguration,
|
|
55
58
|
sync: percy.config.snapshot.sync,
|
|
56
59
|
version: 'v2'
|
|
57
60
|
}, camelCasedOptions], (path, prev, next) => {
|
|
@@ -540,4 +543,31 @@ export function compareObjectTypes(obj1, obj2) {
|
|
|
540
543
|
if (!keys2.includes(key) || !compareObjectTypes(obj1[key], obj2[key])) return false;
|
|
541
544
|
}
|
|
542
545
|
return true;
|
|
546
|
+
}
|
|
547
|
+
const OPTION_MAPPINGS = {
|
|
548
|
+
name: 'name',
|
|
549
|
+
widths: 'widths',
|
|
550
|
+
scope: 'scope',
|
|
551
|
+
scopeoptions: 'scopeOptions',
|
|
552
|
+
minheight: 'minHeight',
|
|
553
|
+
enablejavascript: 'enableJavaScript',
|
|
554
|
+
enablelayout: 'enableLayout',
|
|
555
|
+
clientinfo: 'clientInfo',
|
|
556
|
+
environmentinfo: 'environmentInfo',
|
|
557
|
+
sync: 'sync',
|
|
558
|
+
testcase: 'testCase',
|
|
559
|
+
labels: 'labels',
|
|
560
|
+
thtestcaseexecutionid: 'thTestCaseExecutionId',
|
|
561
|
+
resources: 'resources',
|
|
562
|
+
meta: 'meta',
|
|
563
|
+
snapshot: 'snapshot'
|
|
564
|
+
};
|
|
565
|
+
export function normalizeOptions(options) {
|
|
566
|
+
const normalizedOptions = {};
|
|
567
|
+
for (const key in options) {
|
|
568
|
+
const lowerCaseKey = key.toLowerCase().replace(/[-_]/g, '');
|
|
569
|
+
const normalizedKey = OPTION_MAPPINGS[lowerCaseKey] ? OPTION_MAPPINGS[lowerCaseKey] : key;
|
|
570
|
+
normalizedOptions[normalizedKey] = options[key];
|
|
571
|
+
}
|
|
572
|
+
return normalizedOptions;
|
|
543
573
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@percy/core",
|
|
3
|
-
"version": "1.30.
|
|
3
|
+
"version": "1.30.9-alpha-1.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": "
|
|
12
|
+
"tag": "alpha"
|
|
13
13
|
},
|
|
14
14
|
"engines": {
|
|
15
15
|
"node": ">=14"
|
|
@@ -43,12 +43,12 @@
|
|
|
43
43
|
"test:types": "tsd"
|
|
44
44
|
},
|
|
45
45
|
"dependencies": {
|
|
46
|
-
"@percy/client": "1.30.
|
|
47
|
-
"@percy/config": "1.30.
|
|
48
|
-
"@percy/dom": "1.30.
|
|
49
|
-
"@percy/logger": "1.30.
|
|
50
|
-
"@percy/monitoring": "1.30.
|
|
51
|
-
"@percy/webdriver-utils": "1.30.
|
|
46
|
+
"@percy/client": "1.30.9-alpha-1.0",
|
|
47
|
+
"@percy/config": "1.30.9-alpha-1.0",
|
|
48
|
+
"@percy/dom": "1.30.9-alpha-1.0",
|
|
49
|
+
"@percy/logger": "1.30.9-alpha-1.0",
|
|
50
|
+
"@percy/monitoring": "1.30.9-alpha-1.0",
|
|
51
|
+
"@percy/webdriver-utils": "1.30.9-alpha-1.0",
|
|
52
52
|
"content-disposition": "^0.5.4",
|
|
53
53
|
"cross-spawn": "^7.0.3",
|
|
54
54
|
"extract-zip": "^2.0.1",
|
|
@@ -61,5 +61,5 @@
|
|
|
61
61
|
"ws": "^8.17.1",
|
|
62
62
|
"yaml": "^2.4.1"
|
|
63
63
|
},
|
|
64
|
-
"gitHead": "
|
|
64
|
+
"gitHead": "c9741e74fdbd7d2c152bcdcb619e9b5c1da13be6"
|
|
65
65
|
}
|
package/test/helpers/server.js
CHANGED
|
@@ -1,18 +1,25 @@
|
|
|
1
1
|
// aliased to src during tests
|
|
2
2
|
import Server from '../../dist/server.js';
|
|
3
3
|
|
|
4
|
-
export function createTestServer({ default: defaultReply, ...replies }, port = 8000) {
|
|
4
|
+
export function createTestServer({ default: defaultReply, ...replies }, port = 8000, options = {}) {
|
|
5
5
|
let server = new Server();
|
|
6
6
|
|
|
7
7
|
// alternate route handling
|
|
8
|
-
let handleReply = reply => async (req, res) => {
|
|
8
|
+
let handleReply = (reply, options = {}) => async (req, res) => {
|
|
9
9
|
let [status, headers, body] = typeof reply === 'function' ? await reply(req) : reply;
|
|
10
10
|
if (!Buffer.isBuffer(body) && typeof body !== 'string') body = JSON.stringify(body);
|
|
11
|
+
|
|
12
|
+
if (options.noHeaders) {
|
|
13
|
+
return res.writeHead(status).end(body);
|
|
14
|
+
}
|
|
15
|
+
if (options.headersOverride) {
|
|
16
|
+
headers = { ...headers, ...options.headersOverride };
|
|
17
|
+
}
|
|
11
18
|
return res.send(status, headers, body);
|
|
12
19
|
};
|
|
13
20
|
|
|
14
21
|
// map replies to alternate route handlers
|
|
15
|
-
server.reply = (p, reply) => (replies[p] = handleReply(reply), null);
|
|
22
|
+
server.reply = (p, reply, options = {}) => (replies[p] = handleReply(reply, options), null);
|
|
16
23
|
for (let [p, reply] of Object.entries(replies)) server.reply(p, reply);
|
|
17
24
|
if (defaultReply) defaultReply = handleReply(defaultReply);
|
|
18
25
|
|