@percy/core 1.5.0 → 1.6.1

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
@@ -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
- return Server.createServer({
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
- res.setHeader('X-Percy-Core-Version', pkg.version); // return json errors
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,12 +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
- // font responses from the browser may not be properly encoded, so request them directly
92
+ var _network$authorizatio;
93
+
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
+
92
101
  body = await makeRequest(response.url, {
93
- buffer: true
102
+ buffer: true,
103
+ headers
94
104
  });
95
105
  }
96
106
 
package/dist/percy.js CHANGED
@@ -31,6 +31,8 @@ export class Percy {
31
31
  skipUploads,
32
32
  // implies `skipUploads` and also skips asset discovery
33
33
  dryRun,
34
+ // implies `dryRun`, silent logs, and adds extra api endpoints
35
+ testing,
34
36
  // configuration filepath
35
37
  config,
36
38
  // provided to @percy/client
@@ -44,8 +46,10 @@ export class Percy {
44
46
  // options which will become accessible via the `.config` property
45
47
  ...options
46
48
  } = {}) {
49
+ if (testing) loglevel = 'silent';
47
50
  if (loglevel) this.loglevel(loglevel);
48
- this.dryRun = !!dryRun;
51
+ this.testing = testing ? {} : null;
52
+ this.dryRun = !!testing || !!dryRun;
49
53
  this.skipUploads = this.dryRun || !!skipUploads;
50
54
  this.deferUploads = this.skipUploads || !!deferUploads;
51
55
  if (this.deferUploads) this.#uploads.stop();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@percy/core",
3
- "version": "1.5.0",
3
+ "version": "1.6.1",
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.5.0",
43
- "@percy/config": "1.5.0",
44
- "@percy/dom": "1.5.0",
45
- "@percy/logger": "1.5.0",
42
+ "@percy/client": "1.6.1",
43
+ "@percy/config": "1.6.1",
44
+ "@percy/dom": "1.6.1",
45
+ "@percy/logger": "1.6.1",
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": "813db57980acd418a03d5bf39174ee840feb6229"
56
+ "gitHead": "87e8afc35605110fa7c7bde2100be18e6e74826b"
57
57
  }
@@ -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
  }