@percy/sdk-utils 1.0.0 → 1.0.3
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/bundle.js +669 -0
- package/dist/index.js +10 -0
- package/dist/percy-dom.js +12 -0
- package/dist/percy-enabled.js +55 -0
- package/dist/percy-idle.js +10 -0
- package/dist/percy-info.js +59 -0
- package/dist/post-snapshot.js +17 -0
- package/dist/request.js +65 -0
- package/package.json +7 -7
- package/test/client.js +278 -0
- package/test/helpers.js +80 -0
- package/test/server.js +208 -0
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import logger from '@percy/logger';
|
|
2
|
+
import percy from './percy-info.js';
|
|
3
|
+
import request from './request.js'; // Create a socket to connect to a remote logger
|
|
4
|
+
|
|
5
|
+
async function connectRemoteLogger() {
|
|
6
|
+
await logger.remote(async () => {
|
|
7
|
+
let url = percy.address.replace('http', 'ws');
|
|
8
|
+
|
|
9
|
+
if (process.env.__PERCY_BROWSERIFIED__) {
|
|
10
|
+
return new window.WebSocket(url);
|
|
11
|
+
} else {
|
|
12
|
+
/* eslint-disable-next-line import/no-extraneous-dependencies */
|
|
13
|
+
let {
|
|
14
|
+
default: WebSocket
|
|
15
|
+
} = await import('ws');
|
|
16
|
+
let ws = new WebSocket(url); // allow node to exit with an active connection
|
|
17
|
+
|
|
18
|
+
return ws.once('open', () => ws._socket.unref());
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
} // Check if Percy is enabled using the healthcheck endpoint
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
export async function isPercyEnabled() {
|
|
25
|
+
if (percy.enabled == null) {
|
|
26
|
+
let log = logger('utils');
|
|
27
|
+
let error;
|
|
28
|
+
|
|
29
|
+
try {
|
|
30
|
+
let response = await request('/percy/healthcheck');
|
|
31
|
+
percy.version = response.headers['x-percy-core-version'];
|
|
32
|
+
percy.config = response.body.config;
|
|
33
|
+
percy.enabled = true;
|
|
34
|
+
} catch (e) {
|
|
35
|
+
percy.enabled = false;
|
|
36
|
+
error = e;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if (percy.enabled && percy.version.major !== 1) {
|
|
40
|
+
log.info('Unsupported Percy CLI version, disabling snapshots');
|
|
41
|
+
log.debug(`Found version: ${percy.version}`);
|
|
42
|
+
percy.enabled = false;
|
|
43
|
+
} else if (!percy.enabled) {
|
|
44
|
+
log.info('Percy is not running, disabling snapshots');
|
|
45
|
+
log.debug(error);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
if (percy.enabled) {
|
|
49
|
+
await connectRemoteLogger();
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return percy.enabled;
|
|
54
|
+
}
|
|
55
|
+
export default isPercyEnabled;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import request from './request.js';
|
|
2
|
+
const RETRY_ERROR_CODES = ['ECONNRESET', 'ETIMEDOUT'];
|
|
3
|
+
export async function waitForPercyIdle() {
|
|
4
|
+
try {
|
|
5
|
+
return !!(await request('/percy/idle'));
|
|
6
|
+
} catch (e) {
|
|
7
|
+
return RETRY_ERROR_CODES.includes(e.code) && waitForPercyIdle();
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
export default waitForPercyIdle;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
// helper to create a version object from a string
|
|
2
|
+
function toVersion(str) {
|
|
3
|
+
str || (str = '0.0.0');
|
|
4
|
+
return str.split(/\.|-/).reduce((version, part, i) => {
|
|
5
|
+
let v = parseInt(part, 10);
|
|
6
|
+
version[i] = isNaN(v) ? part : v;
|
|
7
|
+
return version;
|
|
8
|
+
}, {
|
|
9
|
+
get major() {
|
|
10
|
+
return this[0] || 0;
|
|
11
|
+
},
|
|
12
|
+
|
|
13
|
+
get minor() {
|
|
14
|
+
return this[1] || 0;
|
|
15
|
+
},
|
|
16
|
+
|
|
17
|
+
get patch() {
|
|
18
|
+
return this[2] || 0;
|
|
19
|
+
},
|
|
20
|
+
|
|
21
|
+
get prerelease() {
|
|
22
|
+
return this[3];
|
|
23
|
+
},
|
|
24
|
+
|
|
25
|
+
get build() {
|
|
26
|
+
return this[4];
|
|
27
|
+
},
|
|
28
|
+
|
|
29
|
+
toString() {
|
|
30
|
+
return str;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
});
|
|
34
|
+
} // private version cache
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
let version = toVersion(); // contains local percy info
|
|
38
|
+
|
|
39
|
+
const info = {
|
|
40
|
+
// get or set the CLI API address via the environment
|
|
41
|
+
get address() {
|
|
42
|
+
return process.env.PERCY_SERVER_ADDRESS || 'http://localhost:5338';
|
|
43
|
+
},
|
|
44
|
+
|
|
45
|
+
set address(addr) {
|
|
46
|
+
return process.env.PERCY_SERVER_ADDRESS = addr;
|
|
47
|
+
},
|
|
48
|
+
|
|
49
|
+
// version information
|
|
50
|
+
get version() {
|
|
51
|
+
return version;
|
|
52
|
+
},
|
|
53
|
+
|
|
54
|
+
set version(v) {
|
|
55
|
+
return version = toVersion(v);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
};
|
|
59
|
+
export default info;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import percy from './percy-info.js';
|
|
2
|
+
import request from './request.js'; // Post snapshot data to the snapshot endpoint. If the snapshot endpoint responds with a closed
|
|
3
|
+
// error message, signal that Percy has been disabled.
|
|
4
|
+
|
|
5
|
+
export async function postSnapshot(options, params) {
|
|
6
|
+
let query = params ? `?${new URLSearchParams(params)}` : '';
|
|
7
|
+
await request.post(`/percy/snapshot${query}`, options).catch(err => {
|
|
8
|
+
var _err$response, _err$response$body, _err$response$body$bu;
|
|
9
|
+
|
|
10
|
+
if ((_err$response = err.response) !== null && _err$response !== void 0 && (_err$response$body = _err$response.body) !== null && _err$response$body !== void 0 && (_err$response$body$bu = _err$response$body.build) !== null && _err$response$body$bu !== void 0 && _err$response$body$bu.error) {
|
|
11
|
+
percy.enabled = false;
|
|
12
|
+
} else {
|
|
13
|
+
throw err;
|
|
14
|
+
}
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
export default postSnapshot;
|
package/dist/request.js
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import percy from './percy-info.js'; // Helper to send a request to the local CLI API
|
|
2
|
+
|
|
3
|
+
export async function request(path, options = {}) {
|
|
4
|
+
let response = await request.fetch(`${percy.address}${path}`, options); // maybe parse response body as json
|
|
5
|
+
|
|
6
|
+
if (typeof response.body === 'string' && response.headers['content-type'] === 'application/json') {
|
|
7
|
+
try {
|
|
8
|
+
response.body = JSON.parse(response.body);
|
|
9
|
+
} catch (e) {}
|
|
10
|
+
} // throw an error if status is not ok
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
if (!(response.status >= 200 && response.status < 300)) {
|
|
14
|
+
throw Object.assign(new Error(), {
|
|
15
|
+
message: response.body.error || `${response.status} ${response.statusText}`,
|
|
16
|
+
response
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
return response;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
request.post = function post(url, json) {
|
|
24
|
+
return request(url, {
|
|
25
|
+
method: 'POST',
|
|
26
|
+
body: JSON.stringify(json)
|
|
27
|
+
});
|
|
28
|
+
}; // environment specific implementation
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
if (process.env.__PERCY_BROWSERIFIED__) {
|
|
32
|
+
// use window.fetch in browsers
|
|
33
|
+
const winFetch = window.fetch;
|
|
34
|
+
|
|
35
|
+
request.fetch = async function fetch(url, options) {
|
|
36
|
+
let response = await winFetch(url, options);
|
|
37
|
+
return {
|
|
38
|
+
status: response.status,
|
|
39
|
+
statusText: response.statusText,
|
|
40
|
+
headers: Object.fromEntries(response.headers.entries()),
|
|
41
|
+
body: await response.text()
|
|
42
|
+
};
|
|
43
|
+
};
|
|
44
|
+
} else {
|
|
45
|
+
// use http.request in node
|
|
46
|
+
request.fetch = async function fetch(url, options) {
|
|
47
|
+
let {
|
|
48
|
+
default: http
|
|
49
|
+
} = await import('http');
|
|
50
|
+
return new Promise((resolve, reject) => {
|
|
51
|
+
http.request(url, options).on('response', response => {
|
|
52
|
+
let body = '';
|
|
53
|
+
response.on('data', chunk => body += chunk.toString());
|
|
54
|
+
response.on('end', () => resolve({
|
|
55
|
+
status: response.statusCode,
|
|
56
|
+
statusText: response.statusMessage,
|
|
57
|
+
headers: response.headers,
|
|
58
|
+
body
|
|
59
|
+
}));
|
|
60
|
+
}).on('error', reject).end(options.body);
|
|
61
|
+
});
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export default request;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@percy/sdk-utils",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.3",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -14,10 +14,10 @@
|
|
|
14
14
|
"node": ">=14"
|
|
15
15
|
},
|
|
16
16
|
"files": [
|
|
17
|
-
"
|
|
18
|
-
"
|
|
19
|
-
"
|
|
20
|
-
"
|
|
17
|
+
"dist",
|
|
18
|
+
"test/server.js",
|
|
19
|
+
"test/client.js",
|
|
20
|
+
"test/helpers.js"
|
|
21
21
|
],
|
|
22
22
|
"main": "./dist/index.js",
|
|
23
23
|
"browser": "./dist/bundle.js",
|
|
@@ -58,7 +58,7 @@
|
|
|
58
58
|
}
|
|
59
59
|
},
|
|
60
60
|
"dependencies": {
|
|
61
|
-
"@percy/logger": "1.0.
|
|
61
|
+
"@percy/logger": "1.0.3"
|
|
62
62
|
},
|
|
63
|
-
"gitHead": "
|
|
63
|
+
"gitHead": "a259d5cff0933711bced21a979c577e70765d318"
|
|
64
64
|
}
|
package/test/client.js
ADDED
|
@@ -0,0 +1,278 @@
|
|
|
1
|
+
(function() {
|
|
2
|
+
this["null"] = this["null"] || {};
|
|
3
|
+
this.PercySDKUtils.TestHelpers = (function (logger, utils) {
|
|
4
|
+
'use strict';
|
|
5
|
+
|
|
6
|
+
const process = (typeof globalThis !== "undefined" && globalThis.process) || {};
|
|
7
|
+
process.env = process.env || {};
|
|
8
|
+
process.env.__PERCY_BROWSERIFIED__ = true;
|
|
9
|
+
|
|
10
|
+
globalThis.process = globalThis.process || process;
|
|
11
|
+
|
|
12
|
+
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
13
|
+
|
|
14
|
+
var logger__default = /*#__PURE__*/_interopDefaultLegacy(logger);
|
|
15
|
+
var utils__default = /*#__PURE__*/_interopDefaultLegacy(utils);
|
|
16
|
+
|
|
17
|
+
const {
|
|
18
|
+
assign,
|
|
19
|
+
entries
|
|
20
|
+
} = Object; // matches ansi escape sequences
|
|
21
|
+
|
|
22
|
+
const ANSI_REG = new RegExp('[\\u001B\\u009B][[\\]()#;?]*((?:(?:[a-zA-Z\\d]*(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?\\u0007)' + '|(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-ntqry=><~]))', 'g'); // color names by ansi escape code
|
|
23
|
+
|
|
24
|
+
const ANSI_COLORS = {
|
|
25
|
+
'91m': 'red',
|
|
26
|
+
'32m': 'green',
|
|
27
|
+
'93m': 'yellow',
|
|
28
|
+
'34m': 'blue',
|
|
29
|
+
'95m': 'magenta',
|
|
30
|
+
'90m': 'grey'
|
|
31
|
+
}; // colorize each line of a string using an ansi escape sequence
|
|
32
|
+
|
|
33
|
+
const LINE_REG = /^.*$/gm;
|
|
34
|
+
|
|
35
|
+
function colorize(code, str) {
|
|
36
|
+
return str.replace(LINE_REG, line => `\u001b[${code}${line}\u001b[39m`);
|
|
37
|
+
} // map ansi colors to bound colorize functions
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
entries(ANSI_COLORS).reduce((colors, _ref) => {
|
|
41
|
+
let [code, name] = _ref;
|
|
42
|
+
return assign(colors, {
|
|
43
|
+
[name]: colorize.bind(null, code)
|
|
44
|
+
});
|
|
45
|
+
}, {});
|
|
46
|
+
|
|
47
|
+
const ELAPSED_REG = /\s\S*?\(\d+ms\)\S*/;
|
|
48
|
+
const NEWLINE_REG = /\r\n/g;
|
|
49
|
+
const LASTLINE_REG = /\n$/;
|
|
50
|
+
|
|
51
|
+
function sanitizeLog(str) {
|
|
52
|
+
let {
|
|
53
|
+
ansi,
|
|
54
|
+
elapsed
|
|
55
|
+
} = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
56
|
+
// normalize line endings
|
|
57
|
+
str = str.replace(NEWLINE_REG, '\n'); // strip ansi colors
|
|
58
|
+
|
|
59
|
+
if (!ansi) str = str.replace(ANSI_REG, ''); // strip elapsed time
|
|
60
|
+
|
|
61
|
+
if (!elapsed) str = str.replace(ELAPSED_REG, ''); // strip trailing line endings
|
|
62
|
+
|
|
63
|
+
return str.replace(LASTLINE_REG, '');
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function spy(object, method, func) {
|
|
67
|
+
if (object[method].restore) object[method].restore();
|
|
68
|
+
let spy = Object.assign(function spy() {
|
|
69
|
+
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
|
|
70
|
+
args[_key] = arguments[_key];
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
spy.calls.push(args);
|
|
74
|
+
if (func) return func.apply(this, args);
|
|
75
|
+
}, {
|
|
76
|
+
restore: () => object[method] = spy.originalValue,
|
|
77
|
+
reset: () => (spy.calls.length = 0) || spy,
|
|
78
|
+
originalValue: object[method],
|
|
79
|
+
calls: []
|
|
80
|
+
});
|
|
81
|
+
object[method] = spy;
|
|
82
|
+
return spy;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const {
|
|
86
|
+
Logger,
|
|
87
|
+
loglevel
|
|
88
|
+
} = logger__default["default"];
|
|
89
|
+
const helpers$1 = {
|
|
90
|
+
stdout: [],
|
|
91
|
+
stderr: [],
|
|
92
|
+
loglevel,
|
|
93
|
+
|
|
94
|
+
async mock() {
|
|
95
|
+
let options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
96
|
+
helpers$1.reset();
|
|
97
|
+
|
|
98
|
+
if (process.env.__PERCY_BROWSERIFIED__) {
|
|
99
|
+
spy(Logger.prototype, 'write', function (lvl, msg) {
|
|
100
|
+
let stdio = lvl === 'info' ? 'stdout' : 'stderr';
|
|
101
|
+
helpers$1[stdio].push(sanitizeLog(msg, options));
|
|
102
|
+
return this.write.originalValue.call(this, lvl, msg);
|
|
103
|
+
});
|
|
104
|
+
spy(console, 'log');
|
|
105
|
+
spy(console, 'warn');
|
|
106
|
+
spy(console, 'error');
|
|
107
|
+
} else {
|
|
108
|
+
let {
|
|
109
|
+
Writable
|
|
110
|
+
} = await import('stream');
|
|
111
|
+
|
|
112
|
+
for (let stdio of ['stdout', 'stderr']) {
|
|
113
|
+
Logger[stdio] = Object.assign(new Writable(), {
|
|
114
|
+
columns: options.isTTY ? 100 : null,
|
|
115
|
+
isTTY: options.isTTY,
|
|
116
|
+
|
|
117
|
+
cursorTo() {},
|
|
118
|
+
|
|
119
|
+
clearLine() {},
|
|
120
|
+
|
|
121
|
+
_write(chunk, encoding, callback) {
|
|
122
|
+
helpers$1[stdio].push(sanitizeLog(chunk.toString(), options));
|
|
123
|
+
callback();
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
},
|
|
130
|
+
|
|
131
|
+
reset(soft) {
|
|
132
|
+
if (soft) loglevel('info');else delete Logger.instance;
|
|
133
|
+
helpers$1.stdout.length = 0;
|
|
134
|
+
helpers$1.stderr.length = 0;
|
|
135
|
+
|
|
136
|
+
if (console.log.reset) {
|
|
137
|
+
console.log.reset();
|
|
138
|
+
console.warn.reset();
|
|
139
|
+
console.error.reset();
|
|
140
|
+
}
|
|
141
|
+
},
|
|
142
|
+
|
|
143
|
+
dump() {
|
|
144
|
+
let msgs = Array.from(Logger.instance && Logger.instance.messages || []);
|
|
145
|
+
if (!msgs.length) return;
|
|
146
|
+
|
|
147
|
+
let log = m => process.env.__PERCY_BROWSERIFIED__ ? console.log.and ? console.log.and.originalFn(m) : console.log(m) : process.stderr.write(`${m}\n`);
|
|
148
|
+
|
|
149
|
+
logger__default["default"].loglevel('debug');
|
|
150
|
+
log(logger__default["default"].format('testing', 'warn', '--- DUMPING LOGS ---'));
|
|
151
|
+
msgs.reduce((last, _ref) => {
|
|
152
|
+
let {
|
|
153
|
+
debug,
|
|
154
|
+
level,
|
|
155
|
+
message,
|
|
156
|
+
timestamp
|
|
157
|
+
} = _ref;
|
|
158
|
+
log(logger__default["default"].format(debug, level, message, timestamp - last));
|
|
159
|
+
return timestamp;
|
|
160
|
+
}, msgs[0].timestamp);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
const helpers = {
|
|
166
|
+
logger: helpers$1,
|
|
167
|
+
|
|
168
|
+
async setup() {
|
|
169
|
+
utils__default["default"].percy.version = '';
|
|
170
|
+
delete utils__default["default"].percy.config;
|
|
171
|
+
delete utils__default["default"].percy.enabled;
|
|
172
|
+
delete utils__default["default"].percy.domScript;
|
|
173
|
+
delete process.env.PERCY_SERVER_ADDRESS;
|
|
174
|
+
await helpers.call('server.mock');
|
|
175
|
+
await helpers$1.mock();
|
|
176
|
+
},
|
|
177
|
+
|
|
178
|
+
teardown: () => helpers.call('server.close'),
|
|
179
|
+
getRequests: () => helpers.call('server.requests'),
|
|
180
|
+
testReply: (path, reply) => helpers.call('server.reply', path, reply),
|
|
181
|
+
testFailure: function () {
|
|
182
|
+
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
|
|
183
|
+
args[_key] = arguments[_key];
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
return helpers.call('server.test.failure', ...args);
|
|
187
|
+
},
|
|
188
|
+
testError: path => helpers.call('server.test.error', path),
|
|
189
|
+
testSerialize: fn => !fn ? helpers.call('server.test.serialize') // get
|
|
190
|
+
: helpers.call('server.test.serialize', fn),
|
|
191
|
+
// set
|
|
192
|
+
mockSite: () => helpers.call('site.mock'),
|
|
193
|
+
closeSite: () => helpers.call('site.close')
|
|
194
|
+
};
|
|
195
|
+
|
|
196
|
+
if (process.env.__PERCY_BROWSERIFIED__) {
|
|
197
|
+
helpers.call = async function call(event) {
|
|
198
|
+
for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
|
|
199
|
+
args[_key2 - 1] = arguments[_key2];
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
let {
|
|
203
|
+
socket,
|
|
204
|
+
pending = {}
|
|
205
|
+
} = helpers.call;
|
|
206
|
+
|
|
207
|
+
if (!socket) {
|
|
208
|
+
socket = new window.WebSocket('ws://localhost:5339');
|
|
209
|
+
await new Promise((resolve, reject) => {
|
|
210
|
+
let done = event => {
|
|
211
|
+
clearTimeout(timeoutid);
|
|
212
|
+
socket.onopen = socket.onerror = null;
|
|
213
|
+
|
|
214
|
+
if (event && (event.error || event.type === 'error')) {
|
|
215
|
+
reject(event.error || new Error('Test client connection failed'));
|
|
216
|
+
} else resolve(socket);
|
|
217
|
+
};
|
|
218
|
+
|
|
219
|
+
let timeoutid = setTimeout(done, 1000, {
|
|
220
|
+
error: new Error('Test client connection timed out')
|
|
221
|
+
});
|
|
222
|
+
socket.onopen = socket.onerror = done;
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
socket.onmessage = _ref => {
|
|
226
|
+
let {
|
|
227
|
+
data
|
|
228
|
+
} = _ref;
|
|
229
|
+
let {
|
|
230
|
+
id,
|
|
231
|
+
resolve,
|
|
232
|
+
reject
|
|
233
|
+
} = JSON.parse(data);
|
|
234
|
+
if (!pending[id]) return;
|
|
235
|
+
if (resolve) pending[id].resolve(resolve.result);
|
|
236
|
+
if (reject) pending[id].reject(reject.error);
|
|
237
|
+
};
|
|
238
|
+
|
|
239
|
+
Object.assign(helpers.call, {
|
|
240
|
+
socket,
|
|
241
|
+
pending
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
let id = helpers.call.uid = (helpers.call.uid || 0) + 1;
|
|
246
|
+
args = args.map(a => typeof a === 'function' ? a.toString() : a);
|
|
247
|
+
socket.send(JSON.stringify({
|
|
248
|
+
id,
|
|
249
|
+
event,
|
|
250
|
+
args
|
|
251
|
+
}));
|
|
252
|
+
return (pending[id] = {}).promise = new Promise((resolve, reject) => {
|
|
253
|
+
Object.assign(pending[id], {
|
|
254
|
+
resolve,
|
|
255
|
+
reject
|
|
256
|
+
});
|
|
257
|
+
});
|
|
258
|
+
};
|
|
259
|
+
} else {
|
|
260
|
+
helpers.call = async function call() {
|
|
261
|
+
let {
|
|
262
|
+
context
|
|
263
|
+
} = await import('./server.js');
|
|
264
|
+
helpers.context = helpers.context || (await context());
|
|
265
|
+
return helpers.context.call(...arguments);
|
|
266
|
+
};
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
return helpers;
|
|
270
|
+
|
|
271
|
+
})(PercySDKUtils.logger, PercySDKUtils);
|
|
272
|
+
}).call(window);
|
|
273
|
+
|
|
274
|
+
if (typeof define === "function" && define.amd) {
|
|
275
|
+
define([], () => window.PercySDKUtils.TestHelpers);
|
|
276
|
+
} else if (typeof module === "object" && module.exports) {
|
|
277
|
+
module.exports = window.PercySDKUtils.TestHelpers;
|
|
278
|
+
}
|
package/test/helpers.js
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import logger from '@percy/logger/test/helpers';
|
|
2
|
+
import utils from '@percy/sdk-utils';
|
|
3
|
+
|
|
4
|
+
export const helpers = {
|
|
5
|
+
logger,
|
|
6
|
+
|
|
7
|
+
async setup() {
|
|
8
|
+
utils.percy.version = '';
|
|
9
|
+
delete utils.percy.config;
|
|
10
|
+
delete utils.percy.enabled;
|
|
11
|
+
delete utils.percy.domScript;
|
|
12
|
+
delete process.env.PERCY_SERVER_ADDRESS;
|
|
13
|
+
await helpers.call('server.mock');
|
|
14
|
+
await logger.mock();
|
|
15
|
+
},
|
|
16
|
+
|
|
17
|
+
teardown: () => helpers.call('server.close'),
|
|
18
|
+
getRequests: () => helpers.call('server.requests'),
|
|
19
|
+
testReply: (path, reply) => helpers.call('server.reply', path, reply),
|
|
20
|
+
testFailure: (...args) => helpers.call('server.test.failure', ...args),
|
|
21
|
+
testError: path => helpers.call('server.test.error', path),
|
|
22
|
+
testSerialize: fn => !fn
|
|
23
|
+
? helpers.call('server.test.serialize') // get
|
|
24
|
+
: helpers.call('server.test.serialize', fn), // set
|
|
25
|
+
mockSite: () => helpers.call('site.mock'),
|
|
26
|
+
closeSite: () => helpers.call('site.close')
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
if (process.env.__PERCY_BROWSERIFIED__) {
|
|
30
|
+
helpers.call = async function call(event, ...args) {
|
|
31
|
+
let { socket, pending = {} } = helpers.call;
|
|
32
|
+
|
|
33
|
+
if (!socket) {
|
|
34
|
+
socket = new window.WebSocket('ws://localhost:5339');
|
|
35
|
+
|
|
36
|
+
await new Promise((resolve, reject) => {
|
|
37
|
+
let done = event => {
|
|
38
|
+
clearTimeout(timeoutid);
|
|
39
|
+
socket.onopen = socket.onerror = null;
|
|
40
|
+
if (event && (event.error || event.type === 'error')) {
|
|
41
|
+
reject(event.error || new Error('Test client connection failed'));
|
|
42
|
+
} else resolve(socket);
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
let timeoutid = setTimeout(done, 1000, {
|
|
46
|
+
error: new Error('Test client connection timed out')
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
socket.onopen = socket.onerror = done;
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
socket.onmessage = ({ data }) => {
|
|
53
|
+
let { id, resolve, reject } = JSON.parse(data);
|
|
54
|
+
if (!pending[id]) return;
|
|
55
|
+
if (resolve) pending[id].resolve(resolve.result);
|
|
56
|
+
if (reject) pending[id].reject(reject.error);
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
Object.assign(helpers.call, { socket, pending });
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
let id = helpers.call.uid = (helpers.call.uid || 0) + 1;
|
|
63
|
+
args = args.map(a => typeof a === 'function' ? a.toString() : a);
|
|
64
|
+
socket.send(JSON.stringify({ id, event, args }));
|
|
65
|
+
|
|
66
|
+
return ((pending[id] = {}).promise = (
|
|
67
|
+
new Promise((resolve, reject) => {
|
|
68
|
+
Object.assign(pending[id], { resolve, reject });
|
|
69
|
+
})
|
|
70
|
+
));
|
|
71
|
+
};
|
|
72
|
+
} else {
|
|
73
|
+
helpers.call = async function call() {
|
|
74
|
+
let { context } = await import('./server.js');
|
|
75
|
+
helpers.context = (helpers.context || await context());
|
|
76
|
+
return helpers.context.call(...arguments);
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export default helpers;
|