@percy/sdk-utils
Advanced tools
Comparing version 1.1.0 to 1.1.1
@@ -9,426 +9,2 @@ (function() { | ||
const { | ||
assign, | ||
entries | ||
} = Object; // matches ansi escape sequences | ||
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 | ||
const ANSI_COLORS = { | ||
'91m': 'red', | ||
'32m': 'green', | ||
'93m': 'yellow', | ||
'34m': 'blue', | ||
'95m': 'magenta', | ||
'90m': 'grey' | ||
}; // colorize each line of a string using an ansi escape sequence | ||
const LINE_REG = /^.*$/gm; | ||
function colorize(code, str) { | ||
return str.replace(LINE_REG, line => `\u001b[${code}${line}\u001b[39m`); | ||
} // map ansi colors to bound colorize functions | ||
const colors = entries(ANSI_COLORS).reduce((colors, _ref) => { | ||
let [code, name] = _ref; | ||
return assign(colors, { | ||
[name]: colorize.bind(null, code) | ||
}); | ||
}, {}); | ||
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; | ||
} | ||
const URL_REGEXP = /\bhttps?:\/\/[^\s/$.?#].[^\s]*\b/i; | ||
const LOG_LEVELS = { | ||
debug: 0, | ||
info: 1, | ||
warn: 2, | ||
error: 3 | ||
}; // A PercyLogger instance retains logs in-memory for quick lookups while also writing log | ||
// messages to stdout and stderr depending on the log level and debug string. | ||
class PercyLogger { | ||
// default log level | ||
// namespace regular expressions used to determine which debug logs to write | ||
// in-memory store for logs and meta info | ||
// track deprecations to limit noisy logging | ||
// static vars can be overriden for testing | ||
// Handles setting env var values and returns a singleton | ||
constructor() { | ||
_defineProperty(this, "level", 'info'); | ||
_defineProperty(this, "namespaces", { | ||
include: [/^.*?$/], | ||
exclude: [] | ||
}); | ||
_defineProperty(this, "messages", new Set()); | ||
_defineProperty(this, "deprecations", new Set()); | ||
let { | ||
instance = this | ||
} = this.constructor; | ||
if (process.env.PERCY_DEBUG) { | ||
instance.debug(process.env.PERCY_DEBUG); | ||
} else if (process.env.PERCY_LOGLEVEL) { | ||
instance.loglevel(process.env.PERCY_LOGLEVEL); | ||
} | ||
this.constructor.instance = instance; | ||
return instance; | ||
} // Change log level at any time or return the current log level | ||
loglevel(level) { | ||
if (level) this.level = level; | ||
return this.level; | ||
} // Change namespaces by generating an array of namespace regular expressions from a | ||
// comma separated debug string | ||
debug(namespaces) { | ||
if (this.namespaces.string === namespaces) return; | ||
this.namespaces.string = namespaces; | ||
namespaces = namespaces.split(/[\s,]+/).filter(Boolean); | ||
if (!namespaces.length) return this.namespaces; | ||
this.loglevel('debug'); | ||
this.namespaces = namespaces.reduce((namespaces, ns) => { | ||
ns = ns.replace(/:?\*/g, m => m[0] === ':' ? ':?.*?' : '.*?'); | ||
if (ns[0] === '-') { | ||
namespaces.exclude.push(new RegExp('^' + ns.substr(1) + '$')); | ||
} else { | ||
namespaces.include.push(new RegExp('^' + ns + '$')); | ||
} | ||
return namespaces; | ||
}, { | ||
string: namespaces, | ||
include: [], | ||
exclude: [] | ||
}); | ||
} // Creates a new log group and returns level specific functions for logging | ||
group(name) { | ||
return Object.keys(LOG_LEVELS).reduce((group, level) => Object.assign(group, { | ||
[level]: this.log.bind(this, name, level) | ||
}), { | ||
deprecated: this.deprecated.bind(this, name), | ||
shouldLog: this.shouldLog.bind(this, name), | ||
progress: this.progress.bind(this, name), | ||
format: this.format.bind(this, name), | ||
loglevel: this.loglevel.bind(this), | ||
stdout: this.constructor.stdout, | ||
stderr: this.constructor.stderr | ||
}); | ||
} // Query for a set of logs by filtering the in-memory store | ||
query(filter) { | ||
return Array.from(this.messages).filter(filter); | ||
} // Formats messages before they are logged to stdio | ||
format(debug, level, message, elapsed) { | ||
let label = 'percy'; | ||
let suffix = ''; | ||
if (arguments.length === 1) { | ||
// format(message) | ||
[debug, message] = [null, debug]; | ||
} else if (arguments.length === 2) { | ||
// format(debug, message) | ||
[level, message] = [null, level]; | ||
} | ||
if (this.level === 'debug') { | ||
// include debug info in the label | ||
if (debug) label += `:${debug}`; // include elapsed time since last log | ||
if (elapsed != null) { | ||
suffix = ' ' + colors.grey(`(${elapsed}ms)`); | ||
} | ||
} | ||
label = colors.magenta(label); | ||
if (level === 'error') { | ||
// red errors | ||
message = colors.red(message); | ||
} else if (level === 'warn') { | ||
// yellow warnings | ||
message = colors.yellow(message); | ||
} else if (level === 'info' || level === 'debug') { | ||
// blue info and debug URLs | ||
message = message.replace(URL_REGEXP, colors.blue('$&')); | ||
} | ||
return `[${label}] ${message}${suffix}`; | ||
} // Replaces the current line with a log message | ||
progress(debug, message, persist) { | ||
if (!this.shouldLog(debug, 'info')) return; | ||
let { | ||
stdout | ||
} = this.constructor; | ||
if (stdout.isTTY || !this._progress) { | ||
message && (message = this.format(debug, message)); | ||
if (stdout.isTTY) stdout.cursorTo(0);else message && (message = message + '\n'); | ||
if (message) stdout.write(message); | ||
if (stdout.isTTY) stdout.clearLine(1); | ||
} | ||
this._progress = !!message && { | ||
message, | ||
persist | ||
}; | ||
} // Returns true or false if the level and debug group can write messages to stdio | ||
shouldLog(debug, level) { | ||
return LOG_LEVELS[level] != null && LOG_LEVELS[level] >= LOG_LEVELS[this.level] && !this.namespaces.exclude.some(ns => ns.test(debug)) && this.namespaces.include.some(ns => ns.test(debug)); | ||
} // Ensures that deprecation messages are not logged more than once | ||
deprecated(debug, message, meta) { | ||
if (this.deprecations.has(message)) return; | ||
this.deprecations.add(message); | ||
this.log(debug, 'warn', `Warning: ${message}`, meta); | ||
} // Returns true if a socket is present and ready | ||
get isRemote() { | ||
var _this$socket; | ||
return ((_this$socket = this.socket) === null || _this$socket === void 0 ? void 0 : _this$socket.readyState) === 1; | ||
} // Generic log method accepts a debug group, log level, log message, and optional meta | ||
// information to store with the message and other info | ||
log(debug, level, message) { | ||
let meta = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {}; | ||
// message might be an error object | ||
let isError = typeof message !== 'string' && (level === 'error' || level === 'debug'); | ||
let error = isError && message; // if remote, send logs there | ||
if (this.isRemote) { | ||
// serialize error messages | ||
message = isError && 'stack' in error ? { | ||
message: error.message, | ||
stack: error.stack | ||
} : message; | ||
return this.socket.send(JSON.stringify({ | ||
log: [debug, level, message, { | ||
remote: true, | ||
...meta | ||
}] | ||
})); | ||
} // ensure the message is a string | ||
message = isError && message.stack || message.message || message.toString(); // timestamp each log | ||
let timestamp = Date.now(); | ||
let entry = { | ||
debug, | ||
level, | ||
message, | ||
meta, | ||
timestamp | ||
}; | ||
this.messages.add(entry); // maybe write the message to stdio | ||
if (this.shouldLog(debug, level)) { | ||
let elapsed = timestamp - (this.lastlog || timestamp); | ||
if (isError && this.level !== 'debug') message = error.toString(); | ||
this.write(level, this.format(debug, error ? 'error' : level, message, elapsed)); | ||
this.lastlog = timestamp; | ||
} | ||
} // Writes a message to stdio based on the loglevel | ||
write(level, message) { | ||
var _this$_progress; | ||
let { | ||
stdout, | ||
stderr | ||
} = this.constructor; | ||
let progress = stdout.isTTY && this._progress; | ||
if (progress) { | ||
stdout.cursorTo(0); | ||
stdout.clearLine(); | ||
} | ||
(level === 'info' ? stdout : stderr).write(message + '\n'); | ||
if (!((_this$_progress = this._progress) !== null && _this$_progress !== void 0 && _this$_progress.persist)) delete this._progress;else if (progress) stdout.write(progress.message); | ||
} // Opens a socket logging connection | ||
connect(socket) { | ||
// send logging environment info | ||
let PERCY_DEBUG = process.env.PERCY_DEBUG; | ||
let PERCY_LOGLEVEL = process.env.PERCY_LOGLEVEL || this.loglevel(); | ||
socket.send(JSON.stringify({ | ||
env: { | ||
PERCY_DEBUG, | ||
PERCY_LOGLEVEL | ||
} | ||
})); // attach remote logging handler | ||
socket.onmessage = _ref => { | ||
let { | ||
data | ||
} = _ref; | ||
let { | ||
log, | ||
logAll | ||
} = JSON.parse(data); | ||
if (logAll) logAll.forEach(e => this.messages.add(e)); | ||
if (log) this.log(...log); | ||
}; // return a cleanup function | ||
return () => { | ||
socket.onmessage = null; | ||
}; | ||
} // Connects to a remote logger | ||
async remote(createSocket) { | ||
let timeout = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1000; | ||
if (this.isRemote) return; // if not already connected, wait until the timeout | ||
let err = await new Promise(resolve => { | ||
let done = event => { | ||
if (timeoutid == null) return; | ||
timeoutid = clearTimeout(timeoutid); | ||
if (this.socket) this.socket.onopen = this.socket.onerror = null; | ||
resolve((event === null || event === void 0 ? void 0 : event.error) || (event === null || event === void 0 ? void 0 : event.type) === 'error' && 'Error: Socket connection failed'); | ||
}; | ||
let timeoutid = setTimeout(done, timeout, { | ||
error: 'Error: Socket connection timed out' | ||
}); | ||
Promise.resolve().then(async () => { | ||
this.socket = await createSocket(); | ||
if (this.isRemote) return done(); | ||
this.socket.onopen = this.socket.onerror = done; | ||
}).catch(error => done({ | ||
error | ||
})); | ||
}); // there was an error connecting, will fallback to normal logging | ||
if (err) { | ||
this.log('logger', 'debug', 'Unable to connect to remote logger'); | ||
this.log('logger', 'debug', err); | ||
return; | ||
} // send any messages already logged in this environment | ||
if (this.messages.size) { | ||
this.socket.send(JSON.stringify({ | ||
logAll: Array.from(this.messages).map(entry => ({ ...entry, | ||
meta: { | ||
remote: true, | ||
...entry.meta | ||
} | ||
})) | ||
})); | ||
} // attach an incoming message handler | ||
this.socket.onmessage = _ref2 => { | ||
let { | ||
data | ||
} = _ref2; | ||
let { | ||
env | ||
} = JSON.parse(data); // update local environment info | ||
if (env) Object.assign(process.env, env); | ||
}; // return a cleanup function | ||
return () => { | ||
this.socket.onmessage = null; | ||
this.socket = null; | ||
}; | ||
} | ||
} | ||
_defineProperty(PercyLogger, "stdout", process.stdout); | ||
_defineProperty(PercyLogger, "stderr", process.stderr); | ||
class PercyBrowserLogger extends PercyLogger { | ||
write(level, message) { | ||
let out = ['warn', 'error'].includes(level) ? level : 'log'; | ||
let colors = []; | ||
message = message.replace(ANSI_REG, (_, ansi) => { | ||
colors.push(`color:${ANSI_COLORS[ansi] || 'inherit'}`); | ||
return '%c'; | ||
}); | ||
console[out](message, ...colors); | ||
} | ||
progress() { | ||
console.error('The log.progress() method is not supported in browsers'); | ||
} | ||
} | ||
function logger(name) { | ||
return new PercyBrowserLogger().group(name); | ||
} | ||
Object.assign(logger, { | ||
format: function () { | ||
return new PercyBrowserLogger().format(...arguments); | ||
}, | ||
query: function () { | ||
return new PercyBrowserLogger().query(...arguments); | ||
}, | ||
connect: function () { | ||
return new PercyBrowserLogger().connect(...arguments); | ||
}, | ||
remote: function () { | ||
return new PercyBrowserLogger().remote(...arguments); | ||
}, | ||
loglevel: function () { | ||
return new PercyBrowserLogger().loglevel(...arguments); | ||
} | ||
}); | ||
Object.defineProperties(logger, { | ||
Logger: { | ||
get: () => PercyBrowserLogger | ||
}, | ||
stdout: { | ||
get: () => PercyBrowserLogger.stdout | ||
}, | ||
stderr: { | ||
get: () => PercyBrowserLogger.stderr | ||
} | ||
}); | ||
// helper to create a version object from a string | ||
@@ -493,2 +69,123 @@ function toVersion(str) { | ||
const LOG_LEVELS = { | ||
debug: 0, | ||
info: 1, | ||
warn: 2, | ||
error: 3 | ||
}; // Create a small logger util using the specified namespace | ||
function logger(namespace) { | ||
return Object.keys(LOG_LEVELS).reduce((ns, lvl) => Object.assign(ns, { | ||
[lvl]: log.bind(null, namespace, lvl) | ||
}), {}); | ||
} // Set and/or return the local loglevel | ||
const loglevel = logger.loglevel = lvl => { | ||
return loglevel.lvl = lvl || loglevel.lvl || process.env.PERCY_LOGLEVEL || 'info'; | ||
}; // Track and send/write logs for the specified namespace and log level | ||
const log = logger.log = (ns, lvl, msg, meta) => { | ||
let err = typeof msg !== 'string' && (lvl === 'error' || lvl === 'debug'); | ||
meta = { | ||
remote: true, | ||
...meta | ||
}; | ||
if (remote.socket) { | ||
// prefer remote logging when available and serialize any errors | ||
if (err) msg = { | ||
name: msg.name, | ||
message: msg.message, | ||
stack: msg.stack | ||
}; | ||
return remote.socket.send(JSON.stringify({ | ||
log: [ns, lvl, msg, meta] | ||
})); | ||
} else { | ||
// keep log history when not remote | ||
let [debug, level, message, timestamp] = [ns, lvl, msg, Date.now()]; | ||
(log.history || (log.history = [])).push({ | ||
debug, | ||
level, | ||
message, | ||
meta, | ||
timestamp | ||
}); | ||
} // check if the specific level is within the local loglevel range | ||
if (LOG_LEVELS[lvl] != null && LOG_LEVELS[lvl] >= LOG_LEVELS[loglevel()]) { | ||
var _msg; | ||
let debug = loglevel() === 'debug'; | ||
let label = debug ? `percy:${ns}` : 'percy'; // colorize the label when possible for consistency with the CLI logger | ||
if (!process.env.__PERCY_BROWSERIFIED__) label = `\u001b[95m${label}\u001b[39m`; | ||
msg = `[${label}] ${err && debug && ((_msg = msg) === null || _msg === void 0 ? void 0 : _msg.stack) || msg}`; | ||
if (process.env.__PERCY_BROWSERIFIED__) { | ||
// use console[warn|error|log] in browsers | ||
console[['warn', 'error'].includes(lvl) ? lvl : 'log'](msg); | ||
} else { | ||
// use process[stdout|stderr].write in node | ||
process[lvl === 'info' ? 'stdout' : 'stderr'].write(msg + '\n'); | ||
} | ||
} | ||
}; // Create a new WebSocket and resolve with it once connected | ||
async function createWebSocket(address) { | ||
let timeout = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1000; | ||
// attempt to import `ws` in node environments | ||
let WebSocket = process.env.__PERCY_BROWSERIFIED__ | ||
/* eslint-disable-next-line import/no-extraneous-dependencies */ | ||
? window.WebSocket : (await ({})).default; | ||
let ws = new WebSocket(address.replace(/^http/, 'ws')); | ||
return new Promise((resolve, reject) => { | ||
let done = ws.onopen = ws.onerror = e => { | ||
var _ws$_socket; | ||
(_ws$_socket = ws._socket) === null || _ws$_socket === void 0 ? void 0 : _ws$_socket.unref(); | ||
clearTimeout(timeoutid); | ||
ws.onopen = ws.onerror = null; | ||
if (!e.error && e.type !== 'error') return resolve(ws);else reject(e.error || 'Error: Socket connection failed'); | ||
}; | ||
let timeoutid = setTimeout(done, timeout, { | ||
error: 'Error: Socket connection timed out' | ||
}); | ||
}); | ||
} // Connect to a remote logger at the specified address within the timeout | ||
const remote = logger.remote = async timeout => { | ||
try { | ||
var _remote$socket; | ||
// already connected | ||
if (((_remote$socket = remote.socket) === null || _remote$socket === void 0 ? void 0 : _remote$socket.readyState) === 1) return; // connect to namespaced logging address | ||
let address = new URL('/logger', info.address).href; // create and cache a websocket connection | ||
let ws = remote.socket = await createWebSocket(address, timeout); // accept loglevel updates | ||
/* istanbul ignore next: difficult to test currently */ | ||
ws.onmessage = e => loglevel(JSON.parse(e.data).loglevel); // cleanup message handler on close | ||
ws.onclose = () => remote.socket = ws.onmessage = ws.onclose = null; // send any messages already logged in this environment | ||
if (log.history) ws.send(JSON.stringify({ | ||
messages: log.history | ||
})); | ||
} catch (err) { | ||
// there was an error connecting, will fallback to minimal logging | ||
log('utils', 'debug', 'Unable to connect to remote logger'); | ||
log('utils', 'debug', err); | ||
} | ||
}; | ||
async function request(path) { | ||
@@ -541,3 +238,3 @@ let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; | ||
default: http | ||
} = await import('http'); | ||
} = await ({}); | ||
return new Promise((resolve, reject) => { | ||
@@ -558,21 +255,2 @@ http.request(url, options).on('response', response => { | ||
async function connectRemoteLogger() { | ||
await logger.remote(async () => { | ||
let url = info.address.replace('http', 'ws'); | ||
if (process.env.__PERCY_BROWSERIFIED__) { | ||
return new window.WebSocket(url); | ||
} else { | ||
/* eslint-disable-next-line import/no-extraneous-dependencies */ | ||
let { | ||
default: WebSocket | ||
} = await import('ws'); | ||
let ws = new WebSocket(url); // allow node to exit with an active connection | ||
return ws.once('open', () => ws._socket.unref()); | ||
} | ||
}); | ||
} // Check if Percy is enabled using the healthcheck endpoint | ||
async function isPercyEnabled() { | ||
@@ -603,3 +281,3 @@ if (info.enabled == null) { | ||
if (info.enabled) { | ||
await connectRemoteLogger(); | ||
await logger.remote(); | ||
} | ||
@@ -606,0 +284,0 @@ } |
@@ -1,10 +0,72 @@ | ||
import logger from '@percy/logger'; | ||
import percy from './percy-info.js'; | ||
import request from './request.js'; | ||
import isPercyEnabled from './percy-enabled.js'; | ||
import waitForPercyIdle from './percy-idle.js'; | ||
import fetchPercyDOM from './percy-dom.js'; | ||
import postSnapshot from './post-snapshot.js'; | ||
export { logger, percy, request, isPercyEnabled, waitForPercyIdle, fetchPercyDOM, postSnapshot }; // export the namespace by default | ||
"use strict"; | ||
export * as default from './index.js'; | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
}); | ||
exports.default = void 0; | ||
Object.defineProperty(exports, "fetchPercyDOM", { | ||
enumerable: true, | ||
get: function () { | ||
return _percyDom.default; | ||
} | ||
}); | ||
Object.defineProperty(exports, "isPercyEnabled", { | ||
enumerable: true, | ||
get: function () { | ||
return _percyEnabled.default; | ||
} | ||
}); | ||
Object.defineProperty(exports, "logger", { | ||
enumerable: true, | ||
get: function () { | ||
return _logger.default; | ||
} | ||
}); | ||
Object.defineProperty(exports, "percy", { | ||
enumerable: true, | ||
get: function () { | ||
return _percyInfo.default; | ||
} | ||
}); | ||
Object.defineProperty(exports, "postSnapshot", { | ||
enumerable: true, | ||
get: function () { | ||
return _postSnapshot.default; | ||
} | ||
}); | ||
Object.defineProperty(exports, "request", { | ||
enumerable: true, | ||
get: function () { | ||
return _request.default; | ||
} | ||
}); | ||
Object.defineProperty(exports, "waitForPercyIdle", { | ||
enumerable: true, | ||
get: function () { | ||
return _percyIdle.default; | ||
} | ||
}); | ||
var _logger = _interopRequireDefault(require("./logger.js")); | ||
var _percyInfo = _interopRequireDefault(require("./percy-info.js")); | ||
var _request = _interopRequireDefault(require("./request.js")); | ||
var _percyEnabled = _interopRequireDefault(require("./percy-enabled.js")); | ||
var _percyIdle = _interopRequireDefault(require("./percy-idle.js")); | ||
var _percyDom = _interopRequireDefault(require("./percy-dom.js")); | ||
var _postSnapshot = _interopRequireDefault(require("./post-snapshot.js")); | ||
var _default = _interopRequireWildcard(require("./index.js")); | ||
exports.default = _default; | ||
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); } | ||
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } |
@@ -1,12 +0,26 @@ | ||
import percy from './percy-info.js'; | ||
import request from './request.js'; // Fetch and cache the @percy/dom script | ||
"use strict"; | ||
export async function fetchPercyDOM() { | ||
if (percy.domScript == null) { | ||
let response = await request('/percy/dom.js'); | ||
percy.domScript = response.body; | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
}); | ||
exports.default = void 0; | ||
exports.fetchPercyDOM = fetchPercyDOM; | ||
var _percyInfo = _interopRequireDefault(require("./percy-info.js")); | ||
var _request = _interopRequireDefault(require("./request.js")); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
// Fetch and cache the @percy/dom script | ||
async function fetchPercyDOM() { | ||
if (_percyInfo.default.domScript == null) { | ||
let response = await (0, _request.default)('/percy/dom.js'); | ||
_percyInfo.default.domScript = response.body; | ||
} | ||
return percy.domScript; | ||
return _percyInfo.default.domScript; | ||
} | ||
export default fetchPercyDOM; | ||
var _default = fetchPercyDOM; | ||
exports.default = _default; |
@@ -1,44 +0,38 @@ | ||
import logger from '@percy/logger'; | ||
import percy from './percy-info.js'; | ||
import request from './request.js'; // Create a socket to connect to a remote logger | ||
"use strict"; | ||
async function connectRemoteLogger() { | ||
await logger.remote(async () => { | ||
let url = percy.address.replace('http', 'ws'); | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
}); | ||
exports.default = void 0; | ||
exports.isPercyEnabled = isPercyEnabled; | ||
if (process.env.__PERCY_BROWSERIFIED__) { | ||
return new window.WebSocket(url); | ||
} else { | ||
/* eslint-disable-next-line import/no-extraneous-dependencies */ | ||
let { | ||
default: WebSocket | ||
} = await import('ws'); | ||
let ws = new WebSocket(url); // allow node to exit with an active connection | ||
var _percyInfo = _interopRequireDefault(require("./percy-info.js")); | ||
return ws.once('open', () => ws._socket.unref()); | ||
} | ||
}); | ||
} // Check if Percy is enabled using the healthcheck endpoint | ||
var _request = _interopRequireDefault(require("./request.js")); | ||
var _logger = _interopRequireDefault(require("./logger.js")); | ||
export async function isPercyEnabled() { | ||
if (percy.enabled == null) { | ||
let log = logger('utils'); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
// Check if Percy is enabled using the healthcheck endpoint | ||
async function isPercyEnabled() { | ||
if (_percyInfo.default.enabled == null) { | ||
let log = (0, _logger.default)('utils'); | ||
let error; | ||
try { | ||
let response = await request('/percy/healthcheck'); | ||
percy.version = response.headers['x-percy-core-version']; | ||
percy.config = response.body.config; | ||
percy.enabled = true; | ||
let response = await (0, _request.default)('/percy/healthcheck'); | ||
_percyInfo.default.version = response.headers['x-percy-core-version']; | ||
_percyInfo.default.config = response.body.config; | ||
_percyInfo.default.enabled = true; | ||
} catch (e) { | ||
percy.enabled = false; | ||
_percyInfo.default.enabled = false; | ||
error = e; | ||
} | ||
if (percy.enabled && percy.version.major !== 1) { | ||
if (_percyInfo.default.enabled && _percyInfo.default.version.major !== 1) { | ||
log.info('Unsupported Percy CLI version, disabling snapshots'); | ||
log.debug(`Found version: ${percy.version}`); | ||
percy.enabled = false; | ||
} else if (!percy.enabled) { | ||
log.debug(`Found version: ${_percyInfo.default.version}`); | ||
_percyInfo.default.enabled = false; | ||
} else if (!_percyInfo.default.enabled) { | ||
log.info('Percy is not running, disabling snapshots'); | ||
@@ -48,9 +42,11 @@ log.debug(error); | ||
if (percy.enabled) { | ||
await connectRemoteLogger(); | ||
if (_percyInfo.default.enabled) { | ||
await _logger.default.remote(); | ||
} | ||
} | ||
return percy.enabled; | ||
return _percyInfo.default.enabled; | ||
} | ||
export default isPercyEnabled; | ||
var _default = isPercyEnabled; | ||
exports.default = _default; |
@@ -1,6 +0,18 @@ | ||
import request from './request.js'; | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
}); | ||
exports.default = void 0; | ||
exports.waitForPercyIdle = waitForPercyIdle; | ||
var _request = _interopRequireDefault(require("./request.js")); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
const RETRY_ERROR_CODES = ['ECONNRESET', 'ETIMEDOUT']; | ||
export async function waitForPercyIdle() { | ||
async function waitForPercyIdle() { | ||
try { | ||
return !!(await request('/percy/idle')); | ||
return !!(await (0, _request.default)('/percy/idle')); | ||
} catch (e) { | ||
@@ -10,2 +22,4 @@ return RETRY_ERROR_CODES.includes(e.code) && waitForPercyIdle(); | ||
} | ||
export default waitForPercyIdle; | ||
var _default = waitForPercyIdle; | ||
exports.default = _default; |
@@ -0,1 +1,8 @@ | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
}); | ||
exports.default = void 0; | ||
// helper to create a version object from a string | ||
@@ -59,2 +66,3 @@ function toVersion(str) { | ||
}; | ||
export default info; | ||
var _default = info; | ||
exports.default = _default; |
@@ -1,12 +0,24 @@ | ||
import percy from './percy-info.js'; | ||
import request from './request.js'; // Post snapshot data to the snapshot endpoint. If the snapshot endpoint responds with a closed | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
}); | ||
exports.default = void 0; | ||
exports.postSnapshot = postSnapshot; | ||
var _percyInfo = _interopRequireDefault(require("./percy-info.js")); | ||
var _request = _interopRequireDefault(require("./request.js")); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
// Post snapshot data to the snapshot endpoint. If the snapshot endpoint responds with a closed | ||
// error message, signal that Percy has been disabled. | ||
export async function postSnapshot(options, params) { | ||
async function postSnapshot(options, params) { | ||
let query = params ? `?${new URLSearchParams(params)}` : ''; | ||
await request.post(`/percy/snapshot${query}`, options).catch(err => { | ||
await _request.default.post(`/percy/snapshot${query}`, options).catch(err => { | ||
var _err$response, _err$response$body, _err$response$body$bu; | ||
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) { | ||
percy.enabled = false; | ||
_percyInfo.default.enabled = false; | ||
} else { | ||
@@ -17,2 +29,4 @@ throw err; | ||
} | ||
export default postSnapshot; | ||
var _default = postSnapshot; | ||
exports.default = _default; |
@@ -1,6 +0,21 @@ | ||
import percy from './percy-info.js'; // Helper to send a request to the local CLI API | ||
"use strict"; | ||
export async function request(path, options = {}) { | ||
let response = await request.fetch(`${percy.address}${path}`, options); // maybe parse response body as json | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
}); | ||
exports.default = void 0; | ||
exports.request = request; | ||
var _percyInfo = _interopRequireDefault(require("./percy-info.js")); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); } | ||
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } | ||
// Helper to send a request to the local CLI API | ||
async function request(path, options = {}) { | ||
let response = await request.fetch(`${_percyInfo.default.address}${path}`, options); // maybe parse response body as json | ||
if (typeof response.body === 'string' && response.headers['content-type'] === 'application/json') { | ||
@@ -49,3 +64,3 @@ try { | ||
default: http | ||
} = await import('http'); | ||
} = await Promise.resolve().then(() => _interopRequireWildcard(require('http'))); | ||
return new Promise((resolve, reject) => { | ||
@@ -66,2 +81,3 @@ http.request(url, options).on('response', response => { | ||
export default request; | ||
var _default = request; | ||
exports.default = _default; |
{ | ||
"name": "@percy/sdk-utils", | ||
"version": "1.1.0", | ||
"version": "1.1.1", | ||
"license": "MIT", | ||
@@ -24,3 +24,2 @@ "repository": { | ||
"browser": "./dist/bundle.js", | ||
"type": "module", | ||
"exports": { | ||
@@ -51,16 +50,7 @@ ".": "./dist/index.js", | ||
"external": [ | ||
"@percy/logger", | ||
"test/server(.js)?" | ||
], | ||
"output": { | ||
"globals": { | ||
"@percy/logger": "PercySDKUtils.logger" | ||
} | ||
} | ||
] | ||
} | ||
}, | ||
"dependencies": { | ||
"@percy/logger": "1.1.0" | ||
}, | ||
"gitHead": "bf551295a8a618502bb2db92ff302e19dc956b51" | ||
"gitHead": "d74af6a294f89fcb23c4ec598bb68a884ce47907" | ||
} |
(function() { | ||
this["null"] = this["null"] || {}; | ||
this.PercySDKUtils.TestHelpers = (function (logger, utils) { | ||
this.PercySDKUtils.TestHelpers = (function (require$$0) { | ||
'use strict'; | ||
@@ -14,57 +14,9 @@ | ||
var logger__default = /*#__PURE__*/_interopDefaultLegacy(logger); | ||
var utils__default = /*#__PURE__*/_interopDefaultLegacy(utils); | ||
var require$$0__default = /*#__PURE__*/_interopDefaultLegacy(require$$0); | ||
const { | ||
assign, | ||
entries | ||
} = Object; // matches ansi escape sequences | ||
const utils = require$$0__default["default"]; | ||
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 | ||
const ANSI_COLORS = { | ||
'91m': 'red', | ||
'32m': 'green', | ||
'93m': 'yellow', | ||
'34m': 'blue', | ||
'95m': 'magenta', | ||
'90m': 'grey' | ||
}; // colorize each line of a string using an ansi escape sequence | ||
const LINE_REG = /^.*$/gm; | ||
function colorize(code, str) { | ||
return str.replace(LINE_REG, line => `\u001b[${code}${line}\u001b[39m`); | ||
} // map ansi colors to bound colorize functions | ||
entries(ANSI_COLORS).reduce((colors, _ref) => { | ||
let [code, name] = _ref; | ||
return assign(colors, { | ||
[name]: colorize.bind(null, code) | ||
}); | ||
}, {}); | ||
const ELAPSED_REG = /\s\S*?\(\d+ms\)\S*/; | ||
const NEWLINE_REG = /\r\n/g; | ||
const LASTLINE_REG = /\n$/; | ||
function sanitizeLog(str) { | ||
let { | ||
ansi, | ||
elapsed | ||
} = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; | ||
// normalize line endings | ||
str = str.replace(NEWLINE_REG, '\n'); // strip ansi colors | ||
if (!ansi) str = str.replace(ANSI_REG, ''); // strip elapsed time | ||
if (!elapsed) str = str.replace(ELAPSED_REG, ''); // strip trailing line endings | ||
return str.replace(LASTLINE_REG, ''); | ||
} | ||
function spy(object, method, func) { | ||
function stub(object, method, func) { | ||
if (object[method].restore) object[method].restore(); | ||
let spy = Object.assign(function spy() { | ||
let stub = object[method] = Object.assign(function stub() { | ||
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { | ||
@@ -74,117 +26,54 @@ args[_key] = arguments[_key]; | ||
spy.calls.push(args); | ||
stub.calls.push(args); | ||
if (func) return func.apply(this, args); | ||
}, { | ||
restore: () => object[method] = spy.originalValue, | ||
reset: () => (spy.calls.length = 0) || spy, | ||
restore: () => object[method] = stub.originalValue, | ||
reset: () => (stub.calls.length = 0) || stub, | ||
originalValue: object[method], | ||
calls: [] | ||
}); | ||
object[method] = spy; | ||
return spy; | ||
} | ||
return stub; | ||
} // matches ansi escape sequences | ||
const { | ||
Logger, | ||
loglevel | ||
} = logger__default["default"]; | ||
const helpers$1 = { | ||
stdout: [], | ||
stderr: [], | ||
loglevel, | ||
async mock() { | ||
let options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; | ||
helpers$1.reset(); | ||
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'); // strips a log message of excessive newlines and asni escape sequences | ||
if (options.level) { | ||
loglevel(options.level); | ||
} | ||
function sanitizeLog(str) { | ||
return str.replace(/\r\n/g, '\n').replace(ANSI_REG, '').replace(/\n$/, ''); | ||
} | ||
const helpers = { | ||
async setup() { | ||
utils.percy.version = ''; | ||
delete utils.percy.config; | ||
delete utils.percy.enabled; | ||
delete utils.percy.domScript; | ||
delete process.env.PERCY_SERVER_ADDRESS; | ||
await helpers.call('server.mock'); | ||
await helpers.logger.mock(); | ||
}, | ||
async teardown() { | ||
if (process.env.__PERCY_BROWSERIFIED__) { | ||
spy(Logger.prototype, 'write', function (lvl, msg) { | ||
let stdio = lvl === 'info' ? 'stdout' : 'stderr'; | ||
helpers$1[stdio].push(sanitizeLog(msg, options)); | ||
return this.write.originalValue.call(this, lvl, msg); | ||
}); | ||
spy(console, 'log'); | ||
spy(console, 'warn'); | ||
spy(console, 'error'); | ||
for (let m of ['warn', 'error', 'log']) { | ||
var _console$m$restore, _console$m; | ||
(_console$m$restore = (_console$m = console[m]).restore) === null || _console$m$restore === void 0 ? void 0 : _console$m$restore.call(_console$m); | ||
} | ||
} else { | ||
let { | ||
Writable | ||
} = await import('stream'); | ||
for (let io of ['stdout', 'stderr']) { | ||
var _process$io$write$res, _process$io$write; | ||
for (let stdio of ['stdout', 'stderr']) { | ||
Logger[stdio] = Object.assign(new Writable(), { | ||
columns: options.isTTY ? 100 : null, | ||
isTTY: options.isTTY, | ||
cursorTo() {}, | ||
clearLine() {}, | ||
_write(chunk, encoding, callback) { | ||
helpers$1[stdio].push(sanitizeLog(chunk.toString(), options)); | ||
callback(); | ||
} | ||
}); | ||
(_process$io$write$res = (_process$io$write = process[io].write).restore) === null || _process$io$write$res === void 0 ? void 0 : _process$io$write$res.call(_process$io$write); | ||
} | ||
} | ||
}, | ||
reset(soft) { | ||
if (soft) loglevel('info');else delete Logger.instance; | ||
helpers$1.stdout.length = 0; | ||
helpers$1.stderr.length = 0; | ||
if (console.log.reset) { | ||
console.log.reset(); | ||
console.warn.reset(); | ||
console.error.reset(); | ||
} | ||
return helpers.call('server.close'); | ||
}, | ||
dump() { | ||
let msgs = Array.from(Logger.instance && Logger.instance.messages || []); | ||
if (!msgs.length) return; | ||
let log = m => process.env.__PERCY_BROWSERIFIED__ ? console.log.and ? console.log.and.originalFn(m) : console.log(m) : process.stderr.write(`${m}\n`); | ||
logger__default["default"].loglevel('debug'); | ||
log(logger__default["default"].format('testing', 'warn', '--- DUMPING LOGS ---')); | ||
msgs.reduce((last, _ref) => { | ||
let { | ||
debug, | ||
level, | ||
message, | ||
timestamp | ||
} = _ref; | ||
log(logger__default["default"].format(debug, level, message, timestamp - last)); | ||
return timestamp; | ||
}, msgs[0].timestamp); | ||
} | ||
}; | ||
const helpers = { | ||
logger: helpers$1, | ||
async setup() { | ||
utils__default["default"].percy.version = ''; | ||
delete utils__default["default"].percy.config; | ||
delete utils__default["default"].percy.enabled; | ||
delete utils__default["default"].percy.domScript; | ||
delete process.env.PERCY_SERVER_ADDRESS; | ||
await helpers.call('server.mock'); | ||
await helpers$1.mock(); | ||
}, | ||
teardown: () => helpers.call('server.close'), | ||
getRequests: () => helpers.call('server.requests'), | ||
testReply: (path, reply) => helpers.call('server.reply', path, reply), | ||
testFailure: function () { | ||
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { | ||
args[_key] = arguments[_key]; | ||
for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { | ||
args[_key2] = arguments[_key2]; | ||
} | ||
@@ -199,3 +88,53 @@ | ||
mockSite: () => helpers.call('site.mock'), | ||
closeSite: () => helpers.call('site.close') | ||
closeSite: () => helpers.call('site.close'), | ||
logger: { | ||
stdout: [], | ||
stderr: [], | ||
loglevel: utils.logger.loglevel, | ||
async mock() { | ||
helpers.logger.reset(); | ||
let capture = err => msg => { | ||
helpers.logger[err ? 'stderr' : 'stdout'].push(sanitizeLog(msg)); | ||
}; | ||
if (process.env.__PERCY_BROWSERIFIED__) { | ||
// use console[warn|error|log] in browsers | ||
for (let m of ['warn', 'error', 'log']) { | ||
stub(console, m, capture(m !== 'log')); | ||
} | ||
} else { | ||
// use process[stdout|stderr].write in node | ||
for (let io of ['stdout', 'stderr']) { | ||
stub(process[io], 'write', capture(io === 'stderr')); | ||
} | ||
} | ||
}, | ||
reset() { | ||
var _utils$logger$remote$; | ||
(_utils$logger$remote$ = utils.logger.remote.socket) === null || _utils$logger$remote$ === void 0 ? void 0 : _utils$logger$remote$.close(); | ||
delete utils.logger.loglevel.lvl; | ||
delete utils.logger.log.history; | ||
helpers.logger.stdout.length = 0; | ||
helpers.logger.stderr.length = 0; | ||
if (process.env.__PERCY_BROWSERIFIED__) { | ||
for (let m of ['warn', 'error', 'log']) { | ||
var _console$m$reset, _console$m2; | ||
(_console$m$reset = (_console$m2 = console[m]).reset) === null || _console$m$reset === void 0 ? void 0 : _console$m$reset.call(_console$m2); | ||
} | ||
} else { | ||
for (let io of ['stdout', 'stderr']) { | ||
var _process$io$write$res2, _process$io$write2; | ||
(_process$io$write$res2 = (_process$io$write2 = process[io].write).reset) === null || _process$io$write$res2 === void 0 ? void 0 : _process$io$write$res2.call(_process$io$write2); | ||
} | ||
} | ||
} | ||
} | ||
}; | ||
@@ -205,4 +144,4 @@ | ||
helpers.call = async function call(event) { | ||
for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) { | ||
args[_key2 - 1] = arguments[_key2]; | ||
for (var _len3 = arguments.length, args = new Array(_len3 > 1 ? _len3 - 1 : 0), _key3 = 1; _key3 < _len3; _key3++) { | ||
args[_key3 - 1] = arguments[_key3]; | ||
} | ||
@@ -271,3 +210,3 @@ | ||
context | ||
} = await import('./server.js'); | ||
} = await ({}); | ||
helpers.context = helpers.context || (await context()); | ||
@@ -278,5 +217,7 @@ return helpers.context.call(...arguments); | ||
return helpers; | ||
var helpers_1 = helpers; | ||
})(PercySDKUtils.logger, PercySDKUtils); | ||
return helpers_1; | ||
})(PercySDKUtils); | ||
}).call(window); | ||
@@ -283,0 +224,0 @@ |
@@ -1,7 +0,33 @@ | ||
import logger from '@percy/logger/test/helpers'; | ||
import utils from '@percy/sdk-utils'; | ||
const utils = require('@percy/sdk-utils'); | ||
export const helpers = { | ||
logger, | ||
function stub(object, method, func) { | ||
if (object[method].restore) object[method].restore(); | ||
let stub = object[method] = Object.assign(function stub(...args) { | ||
stub.calls.push(args); | ||
if (func) return func.apply(this, args); | ||
}, { | ||
restore: () => (object[method] = stub.originalValue), | ||
reset: () => (stub.calls.length = 0) || stub, | ||
originalValue: object[method], | ||
calls: [] | ||
}); | ||
return stub; | ||
} | ||
// matches ansi escape sequences | ||
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'); | ||
// strips a log message of excessive newlines and asni escape sequences | ||
function sanitizeLog(str) { | ||
return str.replace(/\r\n/g, '\n') | ||
.replace(ANSI_REG, '') | ||
.replace(/\n$/, ''); | ||
} | ||
const helpers = { | ||
async setup() { | ||
@@ -14,6 +40,15 @@ utils.percy.version = ''; | ||
await helpers.call('server.mock'); | ||
await logger.mock(); | ||
await helpers.logger.mock(); | ||
}, | ||
teardown: () => helpers.call('server.close'), | ||
async teardown() { | ||
if (process.env.__PERCY_BROWSERIFIED__) { | ||
for (let m of ['warn', 'error', 'log']) console[m].restore?.(); | ||
} else { | ||
for (let io of ['stdout', 'stderr']) process[io].write.restore?.(); | ||
} | ||
return helpers.call('server.close'); | ||
}, | ||
getRequests: () => helpers.call('server.requests'), | ||
@@ -27,3 +62,45 @@ testReply: (path, reply) => helpers.call('server.reply', path, reply), | ||
mockSite: () => helpers.call('site.mock'), | ||
closeSite: () => helpers.call('site.close') | ||
closeSite: () => helpers.call('site.close'), | ||
logger: { | ||
stdout: [], | ||
stderr: [], | ||
loglevel: utils.logger.loglevel, | ||
async mock() { | ||
helpers.logger.reset(); | ||
let capture = err => msg => { | ||
helpers.logger[err ? 'stderr' : 'stdout'] | ||
.push(sanitizeLog(msg)); | ||
}; | ||
if (process.env.__PERCY_BROWSERIFIED__) { | ||
// use console[warn|error|log] in browsers | ||
for (let m of ['warn', 'error', 'log']) { | ||
stub(console, m, capture(m !== 'log')); | ||
} | ||
} else { | ||
// use process[stdout|stderr].write in node | ||
for (let io of ['stdout', 'stderr']) { | ||
stub(process[io], 'write', capture(io === 'stderr')); | ||
} | ||
} | ||
}, | ||
reset() { | ||
utils.logger.remote.socket?.close(); | ||
delete utils.logger.loglevel.lvl; | ||
delete utils.logger.log.history; | ||
helpers.logger.stdout.length = 0; | ||
helpers.logger.stderr.length = 0; | ||
if (process.env.__PERCY_BROWSERIFIED__) { | ||
for (let m of ['warn', 'error', 'log']) console[m].reset?.(); | ||
} else { | ||
for (let io of ['stdout', 'stderr']) process[io].write.reset?.(); | ||
} | ||
} | ||
} | ||
}; | ||
@@ -82,2 +159,2 @@ | ||
export default helpers; | ||
module.exports = helpers; |
@@ -1,7 +0,6 @@ | ||
import fs from 'fs'; | ||
import url from 'url'; | ||
import path from 'path'; | ||
const fs = require('fs'); | ||
const path = require('path'); | ||
// create a testing context for mocking the local percy server and a local testing site | ||
export async function context() { | ||
async function context() { | ||
let { createTestServer } = await import('@percy/core/test/helpers/server'); | ||
@@ -68,3 +67,3 @@ | ||
ctx.server.websocket(ws => { | ||
ctx.server.websocket('/(logger)?', ws => { | ||
if (!allowSocketConnections) return ws.terminate(); | ||
@@ -113,3 +112,3 @@ ws.onmessage = ({ data }) => ctx.server.messages.push(data); | ||
// start a testing server to control a context remotely | ||
export async function start(args) { | ||
async function start(args) { | ||
let { logger } = await import('@percy/logger'); | ||
@@ -163,3 +162,3 @@ let { WebSocketServer } = await import('ws'); | ||
// stop any existing testing server | ||
export async function stop() { | ||
async function stop() { | ||
let { default: WS } = await import('ws'); | ||
@@ -175,3 +174,3 @@ | ||
// start & stop a testing server around a command | ||
export async function exec(args) { | ||
async function exec(args) { | ||
let argsep = args.indexOf('--'); | ||
@@ -194,6 +193,4 @@ if (argsep < 0) throw new Error('Must supply a command after `--`'); | ||
// allow invoking start/stop/exec as CLI commands | ||
const filename = url.fileURLToPath(import.meta.url); | ||
const [program, ...args] = process.argv.slice(1); | ||
if (program === filename || `${program}.js` === filename) { | ||
if (require.main === module) { | ||
const args = process.argv.slice(2); | ||
const run = { start, stop, exec }[args[0]]; | ||
@@ -203,8 +200,8 @@ | ||
process.stderr.write('usage: node test/server <start|stop|exec>\n'); | ||
} else if (!process.send && fs.existsSync(path.join(filename, '../../src'))) { | ||
await import('child_process').then(cp => cp.fork(filename, args, { | ||
} else if (!process.send && fs.existsSync(path.join(__filename, '../../src'))) { | ||
import('child_process').then(cp => cp.fork(__filename, args, { | ||
execArgv: ['--no-warnings', '--loader=../../scripts/loader.js'] | ||
})); | ||
} else { | ||
await run(args.slice(1)).catch(console.error); | ||
run(args.slice(1)).catch(console.error); | ||
} | ||
@@ -214,2 +211,2 @@ } | ||
// export the namespace by default | ||
export * as default from './server.js'; | ||
module.exports = { context, start, stop, exec }; |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
53297
0
15
1153
11
1
No
- Removed@percy/logger@1.1.0
- Removed@percy/logger@1.1.0(transitive)