testcafe
Version:
Automated browser testing for the modern web development stack.
117 lines • 20.1 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const testcafe_hammerhead_1 = require("testcafe-hammerhead");
const hook_1 = __importDefault(require("./hook"));
const parse_user_agent_1 = require("../../utils/parse-user-agent");
const test_run_tracker_1 = __importDefault(require("../test-run-tracker"));
const re_executable_promise_1 = __importDefault(require("../../utils/re-executable-promise"));
const runtime_1 = require("../../errors/runtime");
const types_1 = require("../../errors/types");
const DEFAULT_OPTIONS = {
logRequestHeaders: false,
logRequestBody: false,
stringifyRequestBody: false,
logResponseHeaders: false,
logResponseBody: false,
stringifyResponseBody: false,
};
const REQUEST_LOGGER_CLASS_NAME = 'RequestLogger';
class RequestLoggerImplementation extends hook_1.default {
constructor(requestFilterRuleInit, options) {
const effectiveOptions = Object.assign({}, DEFAULT_OPTIONS, options);
RequestLoggerImplementation._assertLogOptions(effectiveOptions);
const configureResponseEventOptions = new testcafe_hammerhead_1.ConfigureResponseEventOptions(effectiveOptions.logResponseHeaders, effectiveOptions.logResponseBody);
super(requestFilterRuleInit, configureResponseEventOptions);
this._className = REQUEST_LOGGER_CLASS_NAME;
this._options = effectiveOptions;
this._internalRequests = {};
}
static _assertLogOptions(logOptions) {
if (!logOptions.logRequestBody && logOptions.stringifyRequestBody)
throw new runtime_1.APIError('RequestLogger', types_1.RUNTIME_ERRORS.requestHookConfigureAPIError, 'RequestLogger', 'Cannot stringify the request body because it is not logged. Specify { logRequestBody: true } in log options.');
if (!logOptions.logResponseBody && logOptions.stringifyResponseBody)
throw new runtime_1.APIError('RequestLogger', types_1.RUNTIME_ERRORS.requestHookConfigureAPIError, 'RequestLogger', 'Cannot stringify the response body because it is not logged. Specify { logResponseBody: true } in log options.');
}
static _getInternalRequestKey({ requestId, sessionId }) {
return `${sessionId}:${requestId}`;
}
async onRequest(event) {
const loggedReq = {
id: event._requestInfo.requestId,
testRunId: event._requestInfo.sessionId,
userAgent: (0, parse_user_agent_1.parseUserAgent)(event._requestInfo.userAgent).prettyUserAgent,
request: {
timestamp: Date.now(),
url: event._requestInfo.url,
method: event._requestInfo.method,
},
};
if (this._options.logRequestHeaders)
loggedReq.request.headers = Object.assign({}, event._requestInfo.headers);
if (this._options.logRequestBody)
loggedReq.request.body = this._options.stringifyRequestBody ? event._requestInfo.body.toString() : event._requestInfo.body;
this._internalRequests[RequestLoggerImplementation._getInternalRequestKey(event._requestInfo)] = loggedReq;
}
async onResponse(event) {
const loggedReq = this._internalRequests[RequestLoggerImplementation._getInternalRequestKey(event)];
// NOTE: If the 'clear' method is called during a long running request,
// we should not save a response part - request part has been already removed.
if (!loggedReq)
return;
loggedReq.response = {
statusCode: event.statusCode,
timestamp: Date.now(),
};
if (this._options.logResponseHeaders)
loggedReq.response.headers = Object.assign({}, event.headers);
if (this._options.logResponseBody) {
loggedReq.response.body = this._options.stringifyResponseBody && event.body
? event.body.toString()
: event.body;
}
}
_prepareInternalRequestInfo() {
const testRun = test_run_tracker_1.default.resolveContextTestRun();
let preparedRequests = Object.values(this._internalRequests);
if (testRun)
preparedRequests = preparedRequests.filter(r => r.testRunId === testRun.id);
return preparedRequests;
}
_getCompletedRequests() {
return this._prepareInternalRequestInfo().filter(r => r.response);
}
// API
contains(predicate) {
return re_executable_promise_1.default.fromFn(async () => {
return !!this._getCompletedRequests().find(predicate);
});
}
count(predicate) {
return re_executable_promise_1.default.fromFn(async () => {
return this._getCompletedRequests().filter(predicate).length;
});
}
clear() {
const testRun = test_run_tracker_1.default.resolveContextTestRun();
if (testRun) {
Object.keys(this._internalRequests).forEach(id => {
if (this._internalRequests[id].testRunId === testRun.id)
delete this._internalRequests[id];
});
}
else
this._internalRequests = {};
}
get requests() {
return this._prepareInternalRequestInfo();
}
}
function createRequestLogger(requestFilterRuleInit, logOptions) {
return new RequestLoggerImplementation(requestFilterRuleInit, logOptions);
}
exports.default = createRequestLogger;
module.exports = exports.default;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVxdWVzdC1sb2dnZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvYXBpL3JlcXVlc3QtaG9va3MvcmVxdWVzdC1sb2dnZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFBQSw2REFLNkI7QUFFN0Isa0RBQWlDO0FBQ2pDLG1FQUE4RDtBQUM5RCwyRUFBaUQ7QUFDakQsOEZBQW9FO0FBQ3BFLGtEQUFnRDtBQUNoRCw4Q0FBb0Q7QUFVcEQsTUFBTSxlQUFlLEdBQTBCO0lBQzNDLGlCQUFpQixFQUFNLEtBQUs7SUFDNUIsY0FBYyxFQUFTLEtBQUs7SUFDNUIsb0JBQW9CLEVBQUcsS0FBSztJQUM1QixrQkFBa0IsRUFBSyxLQUFLO0lBQzVCLGVBQWUsRUFBUSxLQUFLO0lBQzVCLHFCQUFxQixFQUFFLEtBQUs7Q0FDL0IsQ0FBQztBQXlCRixNQUFNLHlCQUF5QixHQUFHLGVBQWUsQ0FBQztBQUVsRCxNQUFNLDJCQUE0QixTQUFRLGNBQVc7SUFJakQsWUFBb0IscUJBQXVFLEVBQUUsT0FBbUM7UUFDNUgsTUFBTSxnQkFBZ0IsR0FBRyxNQUFNLENBQUMsTUFBTSxDQUFDLEVBQUUsRUFBRSxlQUFlLEVBQUUsT0FBTyxDQUEwQixDQUFDO1FBRTlGLDJCQUEyQixDQUFDLGlCQUFpQixDQUFDLGdCQUFnQixDQUFDLENBQUM7UUFFaEUsTUFBTSw2QkFBNkIsR0FBRyxJQUFJLG1EQUE2QixDQUFDLGdCQUFnQixDQUFDLGtCQUFrQixFQUFFLGdCQUFnQixDQUFDLGVBQWUsQ0FBQyxDQUFDO1FBRS9JLEtBQUssQ0FBQyxxQkFBcUIsRUFBRSw2QkFBNkIsQ0FBQyxDQUFDO1FBRTVELElBQUksQ0FBQyxVQUFVLEdBQVUseUJBQXlCLENBQUM7UUFDbkQsSUFBSSxDQUFDLFFBQVEsR0FBWSxnQkFBZ0IsQ0FBQztRQUMxQyxJQUFJLENBQUMsaUJBQWlCLEdBQUcsRUFBRSxDQUFDO0lBQ2hDLENBQUM7SUFFTyxNQUFNLENBQUMsaUJB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SUFBSSxDQUFDLGlCQUFpQixDQUFDLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQyxFQUFFO2dCQUM3QyxJQUFJLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxFQUFFLENBQUMsQ0FBQyxTQUFTLEtBQUssT0FBTyxDQUFDLEVBQUU7b0JBQ25ELE9BQU8sSUFBSSxDQUFDLGlCQUFpQixDQUFDLEVBQUUsQ0FBQyxDQUFDO1lBQzFDLENBQUMsQ0FBQyxDQUFDO1NBQ047O1lBRUcsSUFBSSxDQUFDLGlCQUFpQixHQUFHLEVBQUUsQ0FBQztJQUNwQyxDQUFDO0lBRUQsSUFBVyxRQUFRO1FBQ2YsT0FBTyxJQUFJLENBQUMsMkJBQTJCLEVBQUUsQ0FBQztJQUM5QyxDQUFDO0NBQ0o7QUFFRCxTQUF3QixtQkFBbUIsQ0FBRSxxQkFBa0YsRUFBRSxVQUFxQztJQUNsSyxPQUFPLElBQUksMkJBQTJCLENBQUMscUJBQXFCLEVBQUUsVUFBVSxDQUFDLENBQUM7QUFDOUUsQ0FBQztBQUZELHNDQUVDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgICBDb25maWd1cmVSZXNwb25zZUV2ZW50T3B0aW9ucyxcbiAgICBSZXF1ZXN0RXZlbnQsXG4gICAgUmVzcG9uc2VFdmVudCxcbiAgICBSZXF1ZXN0RmlsdGVyUnVsZUluaXQsXG59IGZyb20gJ3Rlc3RjYWZlLWhhbW1lcmhlYWQnO1xuXG5pbXBvcnQgUmVxdWVzdEhvb2sgZnJvbSAnLi9ob29rJztcbmltcG9ydCB7IHBhcnNlVXNlckFnZW50IH0gZnJvbSAnLi4vLi4vdXRpbHMvcGFyc2UtdXNlci1hZ2VudCc7XG5pbXBvcnQgdGVzdFJ1blRyYWNrZXIgZnJvbSAnLi4vdGVzdC1ydW4tdHJhY2tlcic7XG5pbXBvcnQgUmVFeGVjdXRhYmxlUHJvbWlzZSBmcm9tICcuLi8uLi91dGlscy9yZS1leGVjdXRhYmxlLXByb21pc2UnO1xuaW1wb3J0IHsgQVBJRXJyb3IgfSBmcm9tICcuLi8uLi9lcnJvcnMvcnVudGltZSc7XG5pbXBvcnQgeyBSVU5USU1FX0VSUk9SUyB9IGZyb20gJy4uLy4uL2Vycm9ycy90eXBlcyc7XG5cbmltcG9ydCB7XG4gICAgUmVxdWVzdEhvb2tMb2dPcHRpb25zSW5pdCxcbiAgICBSZXF1ZXN0SG9va0xvZ09wdGlvbnMsXG59IGZyb20gJy4vaW50ZXJmYWNlcyc7XG5cbmltcG9ydCB7IERpY3Rpb25hcnkgfSBmcm9tICcuLi8uLi9jb25maWd1cmF0aW9uL2ludGVyZmFjZXMnO1xuXG5cbmNvbnN0IERFRkFVTFRfT1BUSU9OUzogUmVxdWVzdEhvb2tMb2dPcHRpb25zID0ge1xuICAgIGxvZ1JlcXVlc3RIZWFkZXJzOiAgICAgZmFsc2UsXG4gICAgbG9nUmVxdWVzdEJvZHk6ICAgICAgICBmYWxzZSxcbiAgICBzdHJpbmdpZnlSZXF1ZXN0Qm9keTogIGZhbHNlLFxuICAgIGxvZ1Jlc3BvbnNlSGVhZGVyczogICAgZmFsc2UsXG4gICAgbG9nUmVzcG9uc2VCb2R5OiAgICAgICBmYWxzZSxcbiAgICBzdHJpbmdpZnlSZXNwb25zZUJvZHk6IGZhbHNlLFxufTtcblxuaW50ZXJmYWNlIE9wdGlvbmFsbHlMb2dnZWRQYXJ0IHtcbiAgICBoZWFkZXJzPzogYW55O1xuICAgIGJvZHk/OiBCdWZmZXIgfCBzdHJpbmc7XG59XG5cbmludGVyZmFjZSBMb2dnZWRSZXF1ZXN0UGFydCBleHRlbmRzIE9wdGlvbmFsbHlMb2dnZWRQYXJ0IHtcbiAgICB0aW1lc3RhbXA6IG51bWJlcjtcbiAgICB1cmw6IHN0cmluZztcbiAgICBtZXRob2Q6IHN0cmluZztcbn1cbmludGVyZmFjZSBMb2dnZWRSZXNwb25zZVBhcnQgZXh0ZW5kcyBPcHRpb25hbGx5TG9nZ2VkUGFydCB7XG4gICAgc3RhdHVzQ29kZTogbnVtYmVyO1xuICAgIHRpbWVzdGFtcDogbnVtYmVyO1xufVxuXG5pbnRlcmZhY2UgTG9nZ2VkUmVxdWVzdCB7XG4gICAgaWQ6IHN0cmluZztcbiAgICB0ZXN0UnVuSWQ6IHN0cmluZztcbiAgICB1c2VyQWdlbnQ6IHN0cmluZztcbiAgICByZXF1ZXN0OiBMb2dnZWRSZXF1ZXN0UGFydDtcbiAgICByZXNwb25zZT86IExvZ2dlZFJlc3BvbnNlUGFydDtcbn1cblxuY29uc3QgUkVRVUVTVF9MT0dHRVJfQ0xBU1NfTkFNRSA9ICdSZXF1ZXN0TG9nZ2VyJztcblxuY2xhc3MgUmVxdWVzdExvZ2dlckltcGxlbWVudGF0aW9uIGV4dGVuZHMgUmVxdWVzdEhvb2sge1xuICAgIHByaXZhdGUgcmVhZG9ubHkgX29wdGlvbnM6IFJlcXVlc3RIb29rTG9nT3B0aW9ucztcbiAgICBwcml2YXRlIF9pbnRlcm5hbFJlcXVlc3RzOiBEaWN0aW9uYXJ5PExvZ2dlZFJlcXVlc3Q+O1xuXG4gICAgcHVibGljIGNvbnN0cnVjdG9yIChyZXF1ZXN0RmlsdGVyUnVsZUluaXQ/OiBSZXF1ZXN0RmlsdGVyUnVsZUluaXQgfCBSZXF1ZXN0RmlsdGVyUnVsZUluaXRbXSwgb3B0aW9ucz86IFJlcXVlc3RIb29rTG9nT3B0aW9uc0luaXQpIHtcbiAgICAgICAgY29uc3QgZWZmZWN0aXZlT3B0aW9ucyA9IE9iamVjdC5hc3NpZ24oe30sIERFRkFVTFRfT1BUSU9OUywgb3B0aW9ucykgYXMgUmVxdWVzdEhvb2tMb2dPcHRpb25zO1xuXG4gICAgICAgIFJlcXVlc3RMb2dnZXJJbXBsZW1lbnRhdGlvbi5fYXNzZXJ0TG9nT3B0aW9ucyhlZmZlY3RpdmVPcHRpb25zKTtcblxuICAgICAgICBjb25zdCBjb25maWd1cmVSZXNwb25zZUV2ZW50T3B0aW9ucyA9IG5ldyBDb25maWd1cmVSZXNwb25zZUV2ZW50T3B0aW9ucyhlZmZlY3RpdmVPcHRpb25zLmxvZ1Jlc3BvbnNlSGVhZGVycywgZWZmZWN0aXZlT3B0aW9ucy5sb2dSZXNwb25zZUJvZHkpO1xuXG4gICAgICAgIHN1cGVyKHJlcXVlc3RGaWx0ZXJSdWxlSW5pdCwgY29uZmlndXJlUmVzcG9uc2VFdmVudE9wdGlvbnMpO1xuXG4gICAgICAgIHRoaXMuX2NsYXNzTmFtZSAgICAgICAgPSBSRVFVRVNUX0xPR0dFUl9DTEFTU19OQU1FO1xuICAgICAgICB0aGlzLl9vcHRpb25zICAgICAgICAgID0gZWZmZWN0aXZlT3B0aW9ucztcbiAgICAgICAgdGhpcy5faW50ZXJuYWxSZXF1ZXN0cyA9IHt9O1xuICAgIH1cblxuICAgIHByaXZhdGUgc3RhdGljIF9hc3NlcnRMb2dPcHRpb25zIChsb2dPcHRpb25zOiBSZXF1ZXN0SG9va0xvZ09wdGlvbnMpOiB2b2lkIHtcbiAgICAgICAgaWYgKCFsb2dPcHRpb25zLmxvZ1JlcXVlc3RCb2R5ICYmIGxvZ09wdGlvbnMuc3RyaW5naWZ5UmVxdWVzdEJvZHkpXG4gICAgICAgICAgICB0aHJvdyBuZXcgQVBJRXJyb3IoJ1JlcXVlc3RMb2dnZXInLCBSVU5USU1FX0VSUk9SUy5yZXF1ZXN0SG9va0NvbmZpZ3VyZUFQSUVycm9yLCAnUmVxdWVzdExvZ2dlcicsICdDYW5ub3Qgc3RyaW5naWZ5IHRoZSByZXF1ZXN0IGJvZHkgYmVjYXVzZSBpdCBpcyBub3QgbG9nZ2VkLiBTcGVjaWZ5IHsgbG9nUmVxdWVzdEJvZHk6IHRydWUgfSBpbiBsb2cgb3B0aW9ucy4nKTtcblxuICAgICAgICBpZiAoIWxvZ09wdGlvbnMubG9nUmVzcG9uc2VCb2R5ICYmIGxvZ09wdGlvbnMuc3RyaW5naWZ5UmVzcG9uc2VCb2R5KVxuICAgICAgICAgICAgdGhyb3cgbmV3IEFQSUVycm9yKCdSZXF1ZXN0TG9nZ2VyJywgUlVOVElNRV9FUlJPUlMucmVxdWVzdEhvb2tDb25maWd1cmVBUElFcnJvciwgJ1JlcXVlc3RMb2dnZXInLCAnQ2Fubm90IHN0cmluZ2lmeSB0aGUgcmVzcG9uc2UgYm9keSBiZWNhdXNlIGl0IGlzIG5vdCBsb2dnZWQuIFNwZWNpZnkgeyBsb2dSZXNwb25zZUJvZHk6IHRydWUgfSBpbiBsb2cgb3B0aW9ucy4nKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHN0YXRpYyBfZ2V0SW50ZXJuYWxSZXF1ZXN0S2V5ICh7IHJlcXVlc3RJZCwgc2Vzc2lvbklkIH06IGFueSk6IHN0cmluZyB7XG4gICAgICAgIHJldHVybiBgJHtzZXNzaW9uSWR9OiR7cmVxdWVzdElkfWA7XG4gICAgfVxuXG4gICAgcHVibGljIGFzeW5jIG9uUmVxdWVzdCAoZXZlbnQ6IFJlcXVlc3RFdmVudCk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICBjb25zdCBsb2dnZWRSZXE6IExvZ2dlZFJlcXVlc3QgPSB7XG4gICAgICAgICAgICBpZDogICAgICAgIGV2ZW50Ll9yZXF1ZXN0SW5mby5yZXF1ZXN0SWQsXG4gICAgICAgICAgICB0ZXN0UnVuSWQ6IGV2ZW50Ll9yZXF1ZXN0SW5mby5zZXNzaW9uSWQsXG4gICAgICAgICAgICB1c2VyQWdlbnQ6IHBhcnNlVXNlckFnZW50KGV2ZW50Ll9yZXF1ZXN0SW5mby51c2VyQWdlbnQpLnByZXR0eVVzZXJBZ2VudCxcbiAgICAgICAgICAgIHJlcXVlc3Q6ICAge1xuICAgICAgICAgICAgICAgIHRpbWVzdGFtcDogRGF0ZS5ub3coKSxcbiAgICAgICAgICAgICAgICB1cmw6ICAgICAgIGV2ZW50Ll9yZXF1ZXN0SW5mby51cmwsXG4gICAgICAgICAgICAgICAgbWV0aG9kOiAgICBldmVudC5fcmVxdWVzdEluZm8ubWV0aG9kLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgfTtcblxuICAgICAgICBpZiAodGhpcy5fb3B0aW9ucy5sb2dSZXF1ZXN0SGVhZGVycylcbiAgICAgICAgICAgIGxvZ2dlZFJlcS5yZXF1ZXN0LmhlYWRlcnMgPSBPYmplY3QuYXNzaWduKHt9LCBldmVudC5fcmVxdWVzdEluZm8uaGVhZGVycyk7XG5cbiAgICAgICAgaWYgKHRoaXMuX29wdGlvbnMubG9nUmVxdWVzdEJvZHkpXG4gICAgICAgICAgICBsb2dnZWRSZXEucmVxdWVzdC5ib2R5ID0gdGhpcy5fb3B0aW9ucy5zdHJpbmdpZnlSZXF1ZXN0Qm9keSA/IGV2ZW50Ll9yZXF1ZXN0SW5mby5ib2R5LnRvU3RyaW5nKCkgOiBldmVudC5fcmVxdWVzdEluZm8uYm9keTtcblxuICAgICAgICB0aGlzLl9pbnRlcm5hbFJlcXVlc3RzW1JlcXVlc3RMb2dnZXJJbXBsZW1lbnRhdGlvbi5fZ2V0SW50ZXJuYWxSZXF1ZXN0S2V5KGV2ZW50Ll9yZXF1ZXN0SW5mbyldID0gbG9nZ2VkUmVxO1xuICAgIH1cblxuICAgIHB1YmxpYyBhc3luYyBvblJlc3BvbnNlIChldmVudDogUmVzcG9uc2VFdmVudCk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICBjb25zdCBsb2dnZWRSZXEgPSB0aGlzLl9pbnRlcm5hbFJlcXVlc3RzW1JlcXVlc3RMb2dnZXJJbXBsZW1lbnRhdGlvbi5fZ2V0SW50ZXJuYWxSZXF1ZXN0S2V5KGV2ZW50KV07XG5cbiAgICAgICAgLy8gTk9URTogSWYgdGhlICdjbGVhcicgbWV0aG9kIGlzIGNhbGxlZCBkdXJpbmcgYSBsb25nIHJ1bm5pbmcgcmVxdWVzdCxcbiAgICAgICAgLy8gd2Ugc2hvdWxkIG5vdCBzYXZlIGEgcmVzcG9uc2UgcGFydCAtIHJlcXVlc3QgcGFydCBoYXMgYmVlbiBhbHJlYWR5IHJlbW92ZWQuXG4gICAgICAgIGlmICghbG9nZ2VkUmVxKVxuICAgICAgICAgICAgcmV0dXJuO1xuXG4gICAgICAgIGxvZ2dlZFJlcS5yZXNwb25zZSA9IHtcbiAgICAgICAgICAgIHN0YXR1c0NvZGU6IGV2ZW50LnN0YXR1c0NvZGUsXG4gICAgICAgICAgICB0aW1lc3RhbXA6ICBEYXRlLm5vdygpLFxuICAgICAgICB9O1xuXG4gICAgICAgIGlmICh0aGlzLl9vcHRpb25zLmxvZ1Jlc3BvbnNlSGVhZGVycylcbiAgICAgICAgICAgIGxvZ2dlZFJlcS5yZXNwb25zZS5oZWFkZXJzID0gT2JqZWN0LmFzc2lnbih7fSwgZXZlbnQuaGVhZGVycyk7XG5cbiAgICAgICAgaWYgKHRoaXMuX29wdGlvbnMubG9nUmVzcG9uc2VCb2R5KSB7XG4gICAgICAgICAgICBsb2dnZWRSZXEucmVzcG9uc2UuYm9keSA9IHRoaXMuX29wdGlvbnMuc3RyaW5naWZ5UmVzcG9uc2VCb2R5ICYmIGV2ZW50LmJvZHlcbiAgICAgICAgICAgICAgICA/IGV2ZW50LmJvZHkudG9TdHJpbmcoKVxuICAgICAgICAgICAgICAgIDogZXZlbnQuYm9keTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgX3ByZXBhcmVJbnRlcm5hbFJlcXVlc3RJbmZvICgpOiBMb2dnZWRSZXF1ZXN0W10ge1xuICAgICAgICBjb25zdCB0ZXN0UnVuICAgICAgICA9IHRlc3RSdW5UcmFja2VyLnJlc29sdmVDb250ZXh0VGVzdFJ1bigpO1xuICAgICAgICBsZXQgcHJlcGFyZWRSZXF1ZXN0cyA9IE9iamVjdC52YWx1ZXModGhpcy5faW50ZXJuYWxSZXF1ZXN0cyk7XG5cbiAgICAgICAgaWYgKHRlc3RSdW4pXG4gICAgICAgICAgICBwcmVwYXJlZFJlcXVlc3RzID0gcHJlcGFyZWRSZXF1ZXN0cy5maWx0ZXIociA9PiByLnRlc3RSdW5JZCA9PT0gdGVzdFJ1bi5pZCk7XG5cbiAgICAgICAgcmV0dXJuIHByZXBhcmVkUmVxdWVzdHM7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBfZ2V0Q29tcGxldGVkUmVxdWVzdHMgKCk6IExvZ2dlZFJlcXVlc3RbXSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9wcmVwYXJlSW50ZXJuYWxSZXF1ZXN0SW5mbygpLmZpbHRlcihyID0+IHIucmVzcG9uc2UpO1xuICAgIH1cblxuICAgIC8vIEFQSVxuICAgIHB1YmxpYyBjb250YWlucyAocHJlZGljYXRlOiAocmVxdWVzdDogTG9nZ2VkUmVxdWVzdCkgPT4gYm9vbGVhbik6IFJlRXhlY3V0YWJsZVByb21pc2Uge1xuICAgICAgICByZXR1cm4gUmVFeGVjdXRhYmxlUHJvbWlzZS5mcm9tRm4oYXN5bmMgKCkgPT4ge1xuICAgICAgICAgICAgcmV0dXJuICEhdGhpcy5fZ2V0Q29tcGxldGVkUmVxdWVzdHMoKS5maW5kKHByZWRpY2F0ZSk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIHB1YmxpYyBjb3VudCAocHJlZGljYXRlOiAocmVxdWVzdDogTG9nZ2VkUmVxdWVzdCkgPT4gYm9vbGVhbik6IFJlRXhlY3V0YWJsZVByb21pc2Uge1xuICAgICAgICByZXR1cm4gUmVFeGVjdXRhYmxlUHJvbWlzZS5mcm9tRm4oYXN5bmMgKCkgPT4ge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuX2dldENvbXBsZXRlZFJlcXVlc3RzKCkuZmlsdGVyKHByZWRpY2F0ZSkubGVuZ3RoO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBwdWJsaWMgY2xlYXIgKCk6IHZvaWQge1xuICAgICAgICBjb25zdCB0ZXN0UnVuID0gdGVzdFJ1blRyYWNrZXIucmVzb2x2ZUNvbnRleHRUZXN0UnVuKCk7XG5cbiAgICAgICAgaWYgKHRlc3RSdW4pIHtcbiAgICAgICAgICAgIE9iamVjdC5rZXlzKHRoaXMuX2ludGVybmFsUmVxdWVzdHMpLmZvckVhY2goaWQgPT4ge1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLl9pbnRlcm5hbFJlcXVlc3RzW2lkXS50ZXN0UnVuSWQgPT09IHRlc3RSdW4uaWQpXG4gICAgICAgICAgICAgICAgICAgIGRlbGV0ZSB0aGlzLl9pbnRlcm5hbFJlcXVlc3RzW2lkXTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIGVsc2VcbiAgICAgICAgICAgIHRoaXMuX2ludGVybmFsUmVxdWVzdHMgPSB7fTtcbiAgICB9XG5cbiAgICBwdWJsaWMgZ2V0IHJlcXVlc3RzICgpOiBMb2dnZWRSZXF1ZXN0W10ge1xuICAgICAgICByZXR1cm4gdGhpcy5fcHJlcGFyZUludGVybmFsUmVxdWVzdEluZm8oKTtcbiAgICB9XG59XG5cbmV4cG9ydCBkZWZhdWx0IGZ1bmN0aW9uIGNyZWF0ZVJlcXVlc3RMb2dnZXIgKHJlcXVlc3RGaWx0ZXJSdWxlSW5pdDogUmVxdWVzdEZpbHRlclJ1bGVJbml0IHwgUmVxdWVzdEZpbHRlclJ1bGVJbml0W10gfCB1bmRlZmluZWQsIGxvZ09wdGlvbnM6IFJlcXVlc3RIb29rTG9nT3B0aW9uc0luaXQpOiBSZXF1ZXN0TG9nZ2VySW1wbGVtZW50YXRpb24ge1xuICAgIHJldHVybiBuZXcgUmVxdWVzdExvZ2dlckltcGxlbWVudGF0aW9uKHJlcXVlc3RGaWx0ZXJSdWxlSW5pdCwgbG9nT3B0aW9ucyk7XG59XG4iXX0=