@percy/core 1.5.1 → 1.6.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 +58 -3
- package/dist/discovery.js +11 -3
- package/dist/percy.js +21 -5
- package/package.json +6 -6
- package/test/helpers/request.js +1 -1
package/dist/api.js
CHANGED
|
@@ -8,7 +8,7 @@ export const PERCY_DOM = createRequire(import.meta.url).resolve('@percy/dom'); /
|
|
|
8
8
|
|
|
9
9
|
export function createPercyServer(percy, port) {
|
|
10
10
|
let pkg = getPackageJSON(import.meta.url);
|
|
11
|
-
|
|
11
|
+
let server = Server.createServer({
|
|
12
12
|
port
|
|
13
13
|
}) // facilitate logger websocket connections
|
|
14
14
|
.websocket('/(logger)?', ws => {
|
|
@@ -29,13 +29,31 @@ export function createPercyServer(percy, port) {
|
|
|
29
29
|
}));
|
|
30
30
|
}) // general middleware
|
|
31
31
|
.route((req, res, next) => {
|
|
32
|
+
var _percy$testing, _percy$testing3, _percy$testing3$api, _percy$testing4, _percy$testing4$api;
|
|
33
|
+
|
|
32
34
|
// treat all request bodies as json
|
|
33
35
|
if (req.body) try {
|
|
34
36
|
req.body = JSON.parse(req.body);
|
|
35
37
|
} catch {} // add version header
|
|
36
38
|
|
|
37
|
-
res.setHeader('Access-Control-Expose-Headers', '*, X-Percy-Core-Version');
|
|
38
|
-
|
|
39
|
+
res.setHeader('Access-Control-Expose-Headers', '*, X-Percy-Core-Version'); // skip or change api version header in testing mode
|
|
40
|
+
|
|
41
|
+
if (((_percy$testing = percy.testing) === null || _percy$testing === void 0 ? void 0 : _percy$testing.version) !== false) {
|
|
42
|
+
var _percy$testing2;
|
|
43
|
+
|
|
44
|
+
res.setHeader('X-Percy-Core-Version', ((_percy$testing2 = percy.testing) === null || _percy$testing2 === void 0 ? void 0 : _percy$testing2.version) ?? pkg.version);
|
|
45
|
+
} // support sabotaging requests in testing mode
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
if (((_percy$testing3 = percy.testing) === null || _percy$testing3 === void 0 ? void 0 : (_percy$testing3$api = _percy$testing3.api) === null || _percy$testing3$api === void 0 ? void 0 : _percy$testing3$api[req.url.pathname]) === 'error') {
|
|
49
|
+
return res.json(500, {
|
|
50
|
+
success: false,
|
|
51
|
+
error: 'Error: testing'
|
|
52
|
+
});
|
|
53
|
+
} else if (((_percy$testing4 = percy.testing) === null || _percy$testing4 === void 0 ? void 0 : (_percy$testing4$api = _percy$testing4.api) === null || _percy$testing4$api === void 0 ? void 0 : _percy$testing4$api[req.url.pathname]) === 'disconnect') {
|
|
54
|
+
return req.connection.destroy();
|
|
55
|
+
} // return json errors
|
|
56
|
+
|
|
39
57
|
|
|
40
58
|
return next().catch(e => res.json(e.status ?? 500, {
|
|
41
59
|
build: percy.build,
|
|
@@ -77,6 +95,43 @@ export function createPercyServer(percy, port) {
|
|
|
77
95
|
return res.json(200, {
|
|
78
96
|
success: true
|
|
79
97
|
});
|
|
98
|
+
}); // add test endpoints only in testing mode
|
|
99
|
+
|
|
100
|
+
return !percy.testing ? server : server // manipulates testing mode configuration to trigger specific scenarios
|
|
101
|
+
.route('/test/api/:cmd', ({
|
|
102
|
+
body,
|
|
103
|
+
params: {
|
|
104
|
+
cmd
|
|
105
|
+
}
|
|
106
|
+
}, res) => {
|
|
107
|
+
body = Buffer.isBuffer(body) ? body.toString() : body;
|
|
108
|
+
|
|
109
|
+
if (cmd === 'reset') {
|
|
110
|
+
// the reset command will reset testing mode and clear any logs
|
|
111
|
+
percy.testing = {};
|
|
112
|
+
logger.instance.messages.clear();
|
|
113
|
+
} else if (cmd === 'version') {
|
|
114
|
+
// the version command will update the api version header for testing
|
|
115
|
+
percy.testing.version = body;
|
|
116
|
+
} else if (cmd === 'error' || cmd === 'disconnect') {
|
|
117
|
+
// the error or disconnect commands will cause specific endpoints to fail
|
|
118
|
+
percy.testing.api = { ...percy.testing.api,
|
|
119
|
+
[body]: cmd
|
|
120
|
+
};
|
|
121
|
+
} else {
|
|
122
|
+
// 404 for unknown commands
|
|
123
|
+
return res.send(404);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
return res.json(200, {
|
|
127
|
+
testing: percy.testing
|
|
128
|
+
});
|
|
129
|
+
}) // returns an array of raw logs from the logger
|
|
130
|
+
.route('get', '/test/logs', (req, res) => res.json(200, {
|
|
131
|
+
logs: Array.from(logger.instance.messages)
|
|
132
|
+
})) // serves a very basic html page for testing snapshots
|
|
133
|
+
.route('get', '/test/snapshot', (req, res) => {
|
|
134
|
+
return res.send(200, 'text/html', '<p>Snapshot Me!</p>');
|
|
80
135
|
});
|
|
81
136
|
} // Create a static server instance with an automatic sitemap
|
|
82
137
|
|
package/dist/discovery.js
CHANGED
|
@@ -64,6 +64,7 @@ export function createRequestFinishedHandler(network, {
|
|
|
64
64
|
let resource = getResource(url); // process and cache the response and resource
|
|
65
65
|
|
|
66
66
|
if (!((_resource = resource) !== null && _resource !== void 0 && _resource.root) && (!resource || disableCache)) {
|
|
67
|
+
let headers = request.headers;
|
|
67
68
|
let response = request.response;
|
|
68
69
|
let capture = response && hostnameMatches(allowedHostnames, url);
|
|
69
70
|
let body = capture && (await response.buffer());
|
|
@@ -85,14 +86,21 @@ export function createRequestFinishedHandler(network, {
|
|
|
85
86
|
} // Try to get the proper mimetype if the server or asset discovery browser is sending `text/plain`
|
|
86
87
|
|
|
87
88
|
|
|
88
|
-
let mimeType = response.mimeType === 'text/plain' && mime.lookup(response.url) || response.mimeType;
|
|
89
|
+
let mimeType = response.mimeType === 'text/plain' && mime.lookup(response.url) || response.mimeType; // font responses from the browser may not be properly encoded, so request them directly
|
|
89
90
|
|
|
90
91
|
if (mimeType !== null && mimeType !== void 0 && mimeType.includes('font')) {
|
|
91
|
-
|
|
92
|
+
var _network$authorizatio;
|
|
93
|
+
|
|
92
94
|
log.debug('- Requesting asset directly');
|
|
95
|
+
|
|
96
|
+
if (!headers.Authorization && (_network$authorizatio = network.authorization) !== null && _network$authorizatio !== void 0 && _network$authorizatio.username) {
|
|
97
|
+
let token = Buffer.from([network.authorization.username, network.authorization.password || ''].join(':')).toString('base64');
|
|
98
|
+
headers.Authorization = `Basic ${token}`;
|
|
99
|
+
}
|
|
100
|
+
|
|
93
101
|
body = await makeRequest(response.url, {
|
|
94
102
|
buffer: true,
|
|
95
|
-
headers
|
|
103
|
+
headers
|
|
96
104
|
});
|
|
97
105
|
}
|
|
98
106
|
|
package/dist/percy.js
CHANGED
|
@@ -25,12 +25,16 @@ export class Percy {
|
|
|
25
25
|
constructor({
|
|
26
26
|
// initial log level
|
|
27
27
|
loglevel,
|
|
28
|
-
//
|
|
28
|
+
// process uploads before the next snapshot
|
|
29
|
+
delayUploads,
|
|
30
|
+
// process uploads after all snapshots
|
|
29
31
|
deferUploads,
|
|
30
32
|
// run without uploading anything
|
|
31
33
|
skipUploads,
|
|
32
34
|
// implies `skipUploads` and also skips asset discovery
|
|
33
35
|
dryRun,
|
|
36
|
+
// implies `dryRun`, silent logs, and adds extra api endpoints
|
|
37
|
+
testing,
|
|
34
38
|
// configuration filepath
|
|
35
39
|
config,
|
|
36
40
|
// provided to @percy/client
|
|
@@ -44,10 +48,13 @@ export class Percy {
|
|
|
44
48
|
// options which will become accessible via the `.config` property
|
|
45
49
|
...options
|
|
46
50
|
} = {}) {
|
|
51
|
+
if (testing) loglevel = 'silent';
|
|
47
52
|
if (loglevel) this.loglevel(loglevel);
|
|
48
|
-
this.
|
|
53
|
+
this.testing = testing ? {} : null;
|
|
54
|
+
this.dryRun = !!testing || !!dryRun;
|
|
49
55
|
this.skipUploads = this.dryRun || !!skipUploads;
|
|
50
|
-
this.
|
|
56
|
+
this.delayUploads = this.skipUploads || !!delayUploads;
|
|
57
|
+
this.deferUploads = this.delayUploads || !!deferUploads;
|
|
51
58
|
if (this.deferUploads) this.#uploads.stop();
|
|
52
59
|
this.config = PercyConfig.load({
|
|
53
60
|
overrides: options,
|
|
@@ -62,6 +69,10 @@ export class Percy {
|
|
|
62
69
|
this.#snapshots.concurrency = concurrency;
|
|
63
70
|
}
|
|
64
71
|
|
|
72
|
+
if (this.delayUploads) {
|
|
73
|
+
this.#uploads.concurrency = 1;
|
|
74
|
+
}
|
|
75
|
+
|
|
65
76
|
this.client = new PercyClient({
|
|
66
77
|
token,
|
|
67
78
|
clientInfo,
|
|
@@ -162,7 +173,7 @@ export class Percy {
|
|
|
162
173
|
};
|
|
163
174
|
this.build.number = attributes['build-number'];
|
|
164
175
|
this.build.url = attributes['web-url'];
|
|
165
|
-
this.#uploads.run();
|
|
176
|
+
if (!this.delayUploads) this.#uploads.run();
|
|
166
177
|
});
|
|
167
178
|
}, 0); // handle deferred build errors
|
|
168
179
|
|
|
@@ -447,9 +458,14 @@ export class Percy {
|
|
|
447
458
|
|
|
448
459
|
if ((_this$build4 = this.build) !== null && _this$build4 !== void 0 && _this$build4.error) {
|
|
449
460
|
throw new Error(this.build.error);
|
|
450
|
-
}
|
|
461
|
+
} // when not dry-running, process any existing delayed uploads
|
|
451
462
|
|
|
463
|
+
|
|
464
|
+
if (!this.dryRun && this.delayUploads) this.#uploads.run();
|
|
452
465
|
return this.#uploads.push(`upload/${name}`, async () => {
|
|
466
|
+
// when delayed, stop the queue before other uploads are processed
|
|
467
|
+
if (this.delayUploads) this.#uploads.stop();
|
|
468
|
+
|
|
453
469
|
try {
|
|
454
470
|
/* istanbul ignore if: useful for other internal packages */
|
|
455
471
|
if (typeof options === 'function') options = await options();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@percy/core",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.6.2",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -39,10 +39,10 @@
|
|
|
39
39
|
"test:types": "tsd"
|
|
40
40
|
},
|
|
41
41
|
"dependencies": {
|
|
42
|
-
"@percy/client": "1.
|
|
43
|
-
"@percy/config": "1.
|
|
44
|
-
"@percy/dom": "1.
|
|
45
|
-
"@percy/logger": "1.
|
|
42
|
+
"@percy/client": "1.6.2",
|
|
43
|
+
"@percy/config": "1.6.2",
|
|
44
|
+
"@percy/dom": "1.6.2",
|
|
45
|
+
"@percy/logger": "1.6.2",
|
|
46
46
|
"content-disposition": "^0.5.4",
|
|
47
47
|
"cross-spawn": "^7.0.3",
|
|
48
48
|
"extract-zip": "^2.0.1",
|
|
@@ -53,5 +53,5 @@
|
|
|
53
53
|
"rimraf": "^3.0.2",
|
|
54
54
|
"ws": "^8.0.0"
|
|
55
55
|
},
|
|
56
|
-
"gitHead": "
|
|
56
|
+
"gitHead": "c033d52167cdd5873027d9de2676f3fc9f55ef2d"
|
|
57
57
|
}
|
package/test/helpers/request.js
CHANGED
|
@@ -7,7 +7,7 @@ export async function request(url, method = 'GET', handle) {
|
|
|
7
7
|
try {
|
|
8
8
|
return await request(url, options, cb);
|
|
9
9
|
} catch (error) {
|
|
10
|
-
if (typeof handle !== 'boolean') throw error;
|
|
10
|
+
if (!error.response || typeof handle !== 'boolean') throw error;
|
|
11
11
|
return handle ? [error.response.body, error.response] : error.response;
|
|
12
12
|
}
|
|
13
13
|
}
|