@percy/core 1.0.0-beta.69 → 1.0.0-beta.72
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/browser.js +38 -25
- package/dist/config.js +5 -4
- package/dist/index.js +8 -6
- package/dist/network.js +14 -7
- package/dist/page.js +16 -6
- package/dist/percy.js +224 -174
- package/dist/queue.js +67 -25
- package/dist/server.js +12 -5
- package/dist/session.js +9 -3
- package/dist/snapshot.js +48 -41
- package/dist/utils.js +90 -28
- package/package.json +14 -14
- package/test/helpers/server.js +5 -1
package/dist/browser.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
exports.default = void 0;
|
|
6
|
+
exports.default = exports.Browser = void 0;
|
|
7
7
|
|
|
8
8
|
var _os = _interopRequireDefault(require("os"));
|
|
9
9
|
|
|
@@ -29,6 +29,10 @@ var _page = _interopRequireDefault(require("./page"));
|
|
|
29
29
|
|
|
30
30
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
31
31
|
|
|
32
|
+
function _classPrivateFieldInitSpec(obj, privateMap, value) { _checkPrivateRedeclaration(obj, privateMap); privateMap.set(obj, value); }
|
|
33
|
+
|
|
34
|
+
function _checkPrivateRedeclaration(obj, privateCollection) { if (privateCollection.has(obj)) { throw new TypeError("Cannot initialize the same private elements twice on an object"); } }
|
|
35
|
+
|
|
32
36
|
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
33
37
|
|
|
34
38
|
function _classPrivateFieldSet(receiver, privateMap, value) { var descriptor = _classExtractFieldDescriptor(receiver, privateMap, "set"); _classApplyDescriptorSet(receiver, descriptor, value); return value; }
|
|
@@ -59,14 +63,16 @@ class Browser extends _events.default {
|
|
|
59
63
|
|
|
60
64
|
_defineProperty(this, "sessions", new Map());
|
|
61
65
|
|
|
66
|
+
_defineProperty(this, "readyState", null);
|
|
67
|
+
|
|
62
68
|
_defineProperty(this, "closed", false);
|
|
63
69
|
|
|
64
|
-
|
|
70
|
+
_classPrivateFieldInitSpec(this, _callbacks, {
|
|
65
71
|
writable: true,
|
|
66
72
|
value: new Map()
|
|
67
73
|
});
|
|
68
74
|
|
|
69
|
-
|
|
75
|
+
_classPrivateFieldInitSpec(this, _lastid, {
|
|
70
76
|
writable: true,
|
|
71
77
|
value: 0
|
|
72
78
|
});
|
|
@@ -74,7 +80,8 @@ class Browser extends _events.default {
|
|
|
74
80
|
_defineProperty(this, "args", [// disable the translate popup
|
|
75
81
|
'--disable-features=Translate', // disable several subsystems which run network requests in the background
|
|
76
82
|
'--disable-background-networking', // disable task throttling of timer tasks from background pages
|
|
77
|
-
'--disable-background-timer-throttling', // disable backgrounding
|
|
83
|
+
'--disable-background-timer-throttling', // disable backgrounding renderer processes
|
|
84
|
+
'--disable-renderer-backgrounding', // disable backgrounding renderers for occluded windows (reduce nondeterminism)
|
|
78
85
|
'--disable-backgrounding-occluded-windows', // disable crash reporting
|
|
79
86
|
'--disable-breakpad', // disable client side phishing detection
|
|
80
87
|
'--disable-client-side-phishing-detection', // disable default component extensions with background pages for performance
|
|
@@ -112,7 +119,9 @@ class Browser extends _events.default {
|
|
|
112
119
|
}
|
|
113
120
|
|
|
114
121
|
async launch() {
|
|
115
|
-
|
|
122
|
+
// already launching or launched
|
|
123
|
+
if (this.readyState != null) return;
|
|
124
|
+
this.readyState = 0; // check if any provided executable exists
|
|
116
125
|
|
|
117
126
|
if (this.executable && !(0, _fs.existsSync)(this.executable)) {
|
|
118
127
|
this.log.error(`Browser executable not found: ${this.executable}`);
|
|
@@ -122,10 +131,10 @@ class Browser extends _events.default {
|
|
|
122
131
|
|
|
123
132
|
this.executable || (this.executable = await _install.default.chromium()); // create a temporary profile directory
|
|
124
133
|
|
|
125
|
-
this.profile = await _fs.promises.mkdtemp(_path.default.join(_os.default.tmpdir(), 'percy-browser-')); //
|
|
126
|
-
|
|
127
|
-
let args = [...this.args, `--user-data-dir=${this.profile}`]; // spawn the browser process detached in its own group and session
|
|
134
|
+
this.profile = await _fs.promises.mkdtemp(_path.default.join(_os.default.tmpdir(), 'percy-browser-')); // spawn the browser process detached in its own group and session
|
|
128
135
|
|
|
136
|
+
let args = this.args.concat(`--user-data-dir=${this.profile}`);
|
|
137
|
+
this.log.debug('Launching browser');
|
|
129
138
|
this.process = (0, _crossSpawn.default)(this.executable, args, {
|
|
130
139
|
detached: process.platform !== 'win32'
|
|
131
140
|
}); // connect a websocket to the devtools address
|
|
@@ -139,6 +148,8 @@ class Browser extends _events.default {
|
|
|
139
148
|
this.ws.on('message', data => this._handleMessage(data)); // get version information
|
|
140
149
|
|
|
141
150
|
this.version = await this.send('Browser.getVersion');
|
|
151
|
+
this.log.debug(`Browser connected [${this.process.pid}]: ${this.version.product}`);
|
|
152
|
+
this.readyState = 1;
|
|
142
153
|
}
|
|
143
154
|
|
|
144
155
|
isConnected() {
|
|
@@ -150,7 +161,10 @@ class Browser extends _events.default {
|
|
|
150
161
|
async close() {
|
|
151
162
|
var _this$process4, _this$ws2;
|
|
152
163
|
|
|
153
|
-
|
|
164
|
+
// not running, already closed, or closing
|
|
165
|
+
if (this._closed) return this._closed;
|
|
166
|
+
this.readyState = 2;
|
|
167
|
+
this.log.debug('Closing browser'); // resolves when the browser has closed
|
|
154
168
|
|
|
155
169
|
this._closed = Promise.all([new Promise(resolve => {
|
|
156
170
|
/* istanbul ignore next: race condition paranoia */
|
|
@@ -177,6 +191,9 @@ class Browser extends _events.default {
|
|
|
177
191
|
this.log.debug(error);
|
|
178
192
|
});
|
|
179
193
|
}
|
|
194
|
+
}).then(() => {
|
|
195
|
+
this.log.debug('Browser closed');
|
|
196
|
+
this.readyState = 3;
|
|
180
197
|
}); // reject any pending callbacks
|
|
181
198
|
|
|
182
199
|
for (let callback of _classPrivateFieldGet(this, _callbacks).values()) {
|
|
@@ -273,34 +290,28 @@ class Browser extends _events.default {
|
|
|
273
290
|
let match = chunk.match(/^DevTools listening on (ws:\/\/.*)$/m);
|
|
274
291
|
if (match) cleanup(() => resolve(match[1]));
|
|
275
292
|
};
|
|
276
|
-
/* istanbul ignore next: for sanity */
|
|
277
|
-
|
|
278
293
|
|
|
279
|
-
let
|
|
294
|
+
let handleExitClose = () => handleError();
|
|
280
295
|
|
|
281
|
-
let
|
|
296
|
+
let handleError = error => cleanup(() => {
|
|
297
|
+
var _error$message;
|
|
282
298
|
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
var _error$message;
|
|
286
|
-
|
|
287
|
-
return reject(new Error(`Failed to launch browser. ${(_error$message = error === null || error === void 0 ? void 0 : error.message) !== null && _error$message !== void 0 ? _error$message : ''}\n${stderr}'\n\n`));
|
|
288
|
-
});
|
|
289
|
-
};
|
|
299
|
+
return reject(new Error(`Failed to launch browser. ${(_error$message = error === null || error === void 0 ? void 0 : error.message) !== null && _error$message !== void 0 ? _error$message : ''}\n${stderr}'\n\n`));
|
|
300
|
+
});
|
|
290
301
|
|
|
291
302
|
let cleanup = callback => {
|
|
292
303
|
clearTimeout(timeoutId);
|
|
293
304
|
this.process.stderr.off('data', handleData);
|
|
294
|
-
this.process.stderr.off('close',
|
|
295
|
-
this.process.off('exit',
|
|
305
|
+
this.process.stderr.off('close', handleExitClose);
|
|
306
|
+
this.process.off('exit', handleExitClose);
|
|
296
307
|
this.process.off('error', handleError);
|
|
297
308
|
callback();
|
|
298
309
|
};
|
|
299
310
|
|
|
300
311
|
let timeoutId = setTimeout(() => handleError(new Error(`Timed out after ${timeout}ms`)), timeout);
|
|
301
312
|
this.process.stderr.on('data', handleData);
|
|
302
|
-
this.process.stderr.on('close',
|
|
303
|
-
this.process.on('exit',
|
|
313
|
+
this.process.stderr.on('close', handleExitClose);
|
|
314
|
+
this.process.on('exit', handleExitClose);
|
|
304
315
|
this.process.on('error', handleError);
|
|
305
316
|
}));
|
|
306
317
|
return this._address;
|
|
@@ -347,4 +358,6 @@ class Browser extends _events.default {
|
|
|
347
358
|
|
|
348
359
|
}
|
|
349
360
|
|
|
350
|
-
exports.
|
|
361
|
+
exports.Browser = Browser;
|
|
362
|
+
var _default = Browser;
|
|
363
|
+
exports.default = _default;
|
package/dist/config.js
CHANGED
|
@@ -296,9 +296,12 @@ const snapshotDOMSchema = {
|
|
|
296
296
|
// schemas have no concept of inheritance, but we can leverage JS for brevity
|
|
297
297
|
...snapshotSchema.properties
|
|
298
298
|
}
|
|
299
|
-
}; //
|
|
299
|
+
}; // Grouped schemas for easier registration
|
|
300
300
|
|
|
301
301
|
exports.snapshotDOMSchema = snapshotDOMSchema;
|
|
302
|
+
const schemas = [configSchema, snapshotSchema, snapshotDOMSchema]; // Config migrate function
|
|
303
|
+
|
|
304
|
+
exports.schemas = schemas;
|
|
302
305
|
|
|
303
306
|
function configMigration(config, util) {
|
|
304
307
|
/* eslint-disable curly */
|
|
@@ -348,10 +351,8 @@ function snapshotMigration(config, util) {
|
|
|
348
351
|
map: 'additionalSnapshots',
|
|
349
352
|
...notice
|
|
350
353
|
});
|
|
351
|
-
} //
|
|
354
|
+
} // Grouped migrations for easier registration
|
|
352
355
|
|
|
353
356
|
|
|
354
|
-
const schemas = [configSchema, snapshotSchema, snapshotDOMSchema];
|
|
355
|
-
exports.schemas = schemas;
|
|
356
357
|
const migrations = [['/config', configMigration], ['/snapshot', snapshotMigration]];
|
|
357
358
|
exports.migrations = migrations;
|
package/dist/index.js
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
const {
|
|
5
|
-
default: PercyConfig
|
|
6
|
-
} = require('@percy/config');
|
|
3
|
+
const PercyConfig = require('@percy/config');
|
|
7
4
|
|
|
8
5
|
const CoreConfig = require('./config');
|
|
9
6
|
|
|
7
|
+
const {
|
|
8
|
+
Percy
|
|
9
|
+
} = require('./percy');
|
|
10
|
+
|
|
10
11
|
PercyConfig.addSchema(CoreConfig.schemas);
|
|
11
|
-
PercyConfig.addMigration(CoreConfig.migrations); //
|
|
12
|
+
PercyConfig.addMigration(CoreConfig.migrations); // export the Percy class with commonjs compatibility
|
|
12
13
|
|
|
13
|
-
module.exports =
|
|
14
|
+
module.exports = Percy;
|
|
15
|
+
module.exports.Percy = Percy;
|
package/dist/network.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
exports.default = void 0;
|
|
6
|
+
exports.default = exports.Network = void 0;
|
|
7
7
|
|
|
8
8
|
var _logger = _interopRequireDefault(require("@percy/logger"));
|
|
9
9
|
|
|
@@ -13,6 +13,10 @@ var _discovery = require("./discovery");
|
|
|
13
13
|
|
|
14
14
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
15
15
|
|
|
16
|
+
function _classPrivateFieldInitSpec(obj, privateMap, value) { _checkPrivateRedeclaration(obj, privateMap); privateMap.set(obj, value); }
|
|
17
|
+
|
|
18
|
+
function _checkPrivateRedeclaration(obj, privateCollection) { if (privateCollection.has(obj)) { throw new TypeError("Cannot initialize the same private elements twice on an object"); } }
|
|
19
|
+
|
|
16
20
|
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
17
21
|
|
|
18
22
|
function _classPrivateFieldGet(receiver, privateMap) { var descriptor = _classExtractFieldDescriptor(receiver, privateMap, "get"); return _classApplyDescriptorGet(receiver, descriptor); }
|
|
@@ -37,22 +41,22 @@ class Network {
|
|
|
37
41
|
|
|
38
42
|
_defineProperty(this, "log", (0, _logger.default)('core:network'));
|
|
39
43
|
|
|
40
|
-
|
|
44
|
+
_classPrivateFieldInitSpec(this, _pending, {
|
|
41
45
|
writable: true,
|
|
42
46
|
value: new Map()
|
|
43
47
|
});
|
|
44
48
|
|
|
45
|
-
|
|
49
|
+
_classPrivateFieldInitSpec(this, _requests, {
|
|
46
50
|
writable: true,
|
|
47
51
|
value: new Map()
|
|
48
52
|
});
|
|
49
53
|
|
|
50
|
-
|
|
54
|
+
_classPrivateFieldInitSpec(this, _intercepts, {
|
|
51
55
|
writable: true,
|
|
52
56
|
value: new Map()
|
|
53
57
|
});
|
|
54
58
|
|
|
55
|
-
|
|
59
|
+
_classPrivateFieldInitSpec(this, _authentications, {
|
|
56
60
|
writable: true,
|
|
57
61
|
value: new Set()
|
|
58
62
|
});
|
|
@@ -353,6 +357,9 @@ class Network {
|
|
|
353
357
|
|
|
354
358
|
}
|
|
355
359
|
|
|
356
|
-
exports.
|
|
360
|
+
exports.Network = Network;
|
|
361
|
+
|
|
362
|
+
_defineProperty(Network, "TIMEOUT", 30000);
|
|
357
363
|
|
|
358
|
-
|
|
364
|
+
var _default = Network;
|
|
365
|
+
exports.default = _default;
|
package/dist/page.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
exports.default = void 0;
|
|
6
|
+
exports.default = exports.Page = void 0;
|
|
7
7
|
|
|
8
8
|
var _fs = require("fs");
|
|
9
9
|
|
|
@@ -179,7 +179,14 @@ class Page {
|
|
|
179
179
|
} // wrap the function body with percy helpers
|
|
180
180
|
|
|
181
181
|
|
|
182
|
-
fnbody = 'function withPercyHelpers() {' +
|
|
182
|
+
fnbody = 'function withPercyHelpers() {\n' + [`return (${fnbody})({ generatePromise, waitFor }, ...arguments);`, `${_utils.generatePromise}`, `${_utils.waitFor}`].join('\n\n') + '}';
|
|
183
|
+
/* istanbul ignore else: ironic. */
|
|
184
|
+
|
|
185
|
+
if (fnbody.includes('cov_')) {
|
|
186
|
+
// remove coverage statements during testing
|
|
187
|
+
fnbody = fnbody.replace(/cov_.*?(;\n?|,)\s*/g, '');
|
|
188
|
+
} // send the call function command
|
|
189
|
+
|
|
183
190
|
|
|
184
191
|
let {
|
|
185
192
|
result,
|
|
@@ -214,7 +221,7 @@ class Page {
|
|
|
214
221
|
|
|
215
222
|
for (let script of scripts) {
|
|
216
223
|
if (typeof script === 'string') {
|
|
217
|
-
script = `async eval(
|
|
224
|
+
script = `async eval() {\n${script}\n}`;
|
|
218
225
|
}
|
|
219
226
|
|
|
220
227
|
await this.eval(script);
|
|
@@ -250,7 +257,7 @@ class Page {
|
|
|
250
257
|
} // execute any javascript
|
|
251
258
|
|
|
252
259
|
|
|
253
|
-
await this.evaluate(typeof execute === '
|
|
260
|
+
await this.evaluate(typeof execute === 'object' && !Array.isArray(execute) ? execute.beforeSnapshot : execute); // wait for any final network activity before capturing the dom snapshot
|
|
254
261
|
|
|
255
262
|
await this.network.idle(); // inject @percy/dom for serialization by evaluating the file contents which adds a global
|
|
256
263
|
// PercyDOM object that we can later check against
|
|
@@ -278,6 +285,9 @@ class Page {
|
|
|
278
285
|
|
|
279
286
|
}
|
|
280
287
|
|
|
281
|
-
exports.
|
|
288
|
+
exports.Page = Page;
|
|
289
|
+
|
|
290
|
+
_defineProperty(Page, "TIMEOUT", 30000);
|
|
282
291
|
|
|
283
|
-
|
|
292
|
+
var _default = Page;
|
|
293
|
+
exports.default = _default;
|