apollo-angular
Version:
Use your GraphQL data in your Angular app, with the Apollo Client
139 lines • 18.6 kB
JavaScript
import { Injectable } from '@angular/core';
import { Observable as LinkObservable } from '@apollo/client/core';
import { print } from 'graphql';
import { TestOperation } from './operation';
/**
* A testing backend for `Apollo`.
*
* `ApolloTestingBackend` works by keeping a list of all open operations.
* As operations come in, they're added to the list. Users can assert that specific
* operations were made and then flush them. In the end, a verify() method asserts
* that no unexpected operations were made.
*/
export class ApolloTestingBackend {
constructor() {
/**
* List of pending operations which have not yet been expected.
*/
this.open = [];
}
/**
* Handle an incoming operation by queueing it in the list of open operations.
*/
handle(op) {
return new LinkObservable((observer) => {
const testOp = new TestOperation(op, observer);
this.open.push(testOp);
});
}
/**
* Helper function to search for operations in the list of open operations.
*/
_match(match) {
if (typeof match === 'string') {
return this.open.filter((testOp) => testOp.operation.operationName === match);
}
else if (typeof match === 'function') {
return this.open.filter((testOp) => match(testOp.operation));
}
else {
if (this.isDocumentNode(match)) {
return this.open.filter((testOp) => print(testOp.operation.query) === print(match));
}
return this.open.filter((testOp) => this.matchOp(match, testOp));
}
}
matchOp(match, testOp) {
const variables = JSON.stringify(match.variables);
const extensions = JSON.stringify(match.extensions);
const sameName = this.compare(match.operationName, testOp.operation.operationName);
const sameVariables = this.compare(variables, testOp.operation.variables);
const sameQuery = print(testOp.operation.query) === print(match.query);
const sameExtensions = this.compare(extensions, testOp.operation.extensions);
return sameName && sameVariables && sameQuery && sameExtensions;
}
compare(expected, value) {
const prepare = (val) => typeof val === 'string' ? val : JSON.stringify(val);
const received = prepare(value);
return !expected || received === expected;
}
/**
* Search for operations in the list of open operations, and return all that match
* without asserting anything about the number of matches.
*/
match(match) {
const results = this._match(match);
results.forEach((result) => {
const index = this.open.indexOf(result);
if (index !== -1) {
this.open.splice(index, 1);
}
});
return results;
}
/**
* Expect that a single outstanding request matches the given matcher, and return
* it.
*
* operations returned through this API will no longer be in the list of open operations,
* and thus will not match twice.
*/
expectOne(match, description) {
description = description || this.descriptionFromMatcher(match);
const matches = this.match(match);
if (matches.length > 1) {
throw new Error(`Expected one matching operation for criteria "${description}", found ${matches.length} operations.`);
}
if (matches.length === 0) {
throw new Error(`Expected one matching operation for criteria "${description}", found none.`);
}
return matches[0];
}
/**
* Expect that no outstanding operations match the given matcher, and throw an error
* if any do.
*/
expectNone(match, description) {
description = description || this.descriptionFromMatcher(match);
const matches = this.match(match);
if (matches.length > 0) {
throw new Error(`Expected zero matching operations for criteria "${description}", found ${matches.length}.`);
}
}
/**
* Validate that there are no outstanding operations.
*/
verify() {
const open = this.open;
if (open.length > 0) {
// Show the methods and URLs of open operations in the error, for convenience.
const operations = open
.map((testOp) => testOp.operation.operationName)
.join(', ');
throw new Error(`Expected no open operations, found ${open.length}: ${operations}`);
}
}
isDocumentNode(docOrOp) {
return !docOrOp.operationName;
}
descriptionFromMatcher(matcher) {
if (typeof matcher === 'string') {
return `Match operationName: ${matcher}`;
}
else if (typeof matcher === 'object') {
if (this.isDocumentNode(matcher)) {
return `Match DocumentNode`;
}
const name = matcher.operationName || '(any)';
const variables = JSON.stringify(matcher.variables) || '(any)';
return `Match operation: ${name}, variables: ${variables}`;
}
else {
return `Match by function: ${matcher.name}`;
}
}
}
ApolloTestingBackend.decorators = [
{ type: Injectable }
];
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmFja2VuZC5qcyIsInNvdXJjZVJvb3QiOiIvd29ya3NwYWNlcy9hcG9sbG8tYW5ndWxhci9wYWNrYWdlcy9hcG9sbG8tYW5ndWxhci90ZXN0aW5nL3NyYy8iLCJzb3VyY2VzIjpbImJhY2tlbmQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFDLFVBQVUsRUFBQyxNQUFNLGVBQWUsQ0FBQztBQUV6QyxPQUFPLEVBQWMsVUFBVSxJQUFJLGNBQWMsRUFBQyxNQUFNLHFCQUFxQixDQUFDO0FBQzlFLE9BQU8sRUFBQyxLQUFLLEVBQWUsTUFBTSxTQUFTLENBQUM7QUFHNUMsT0FBTyxFQUFDLGFBQWEsRUFBWSxNQUFNLGFBQWEsQ0FBQztBQUVyRDs7Ozs7OztHQU9HO0FBRUgsTUFBTSxPQUFPLG9CQUFvQjtJQURqQztRQUVFOztXQUVHO1FBQ0ssU0FBSSxHQUFvQixFQUFFLENBQUM7SUF5SnJDLENBQUM7SUF2SkM7O09BRUc7SUFDSSxNQUFNLENBQUMsRUFBYTtRQUN6QixPQUFPLElBQUksY0FBYyxDQUFDLENBQUMsUUFBdUIsRUFBRSxFQUFFO1lBQ3BELE1BQU0sTUFBTSxHQUFHLElBQUksYUFBYSxDQUFDLEVBQUUsRUFBRSxRQUFRLENBQUMsQ0FBQztZQUMvQyxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUN6QixDQUFDLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFRDs7T0FFRztJQUNLLE1BQU0sQ0FBQyxLQUFxQjtRQUNsQyxJQUFJLE9BQU8sS0FBSyxLQUFLLFFBQVEsRUFBRTtZQUM3QixPQUFPLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUNyQixDQUFDLE1BQU0sRUFBRSxFQUFFLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxhQUFhLEtBQUssS0FBSyxDQUNyRCxDQUFDO1NBQ0g7YUFBTSxJQUFJLE9BQU8sS0FBSyxLQUFLLFVBQVUsRUFBRTtZQUN0QyxPQUFPLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUMsTUFBTSxFQUFFLEVBQUUsQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUM7U0FDOUQ7YUFBTTtZQUNMLElBQUksSUFBSSxDQUFDLGNBQWMsQ0FBQyxLQUFLLENBQUMsRUFBRTtnQkFDOUIsT0FBTyxJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FDckIsQ0FBQyxNQUFNLEVBQUUsRUFBRSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxLQUFLLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FDM0QsQ0FBQzthQUNIO1lBRUQsT0FBTyxJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDLE1BQU0sRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxLQUFLLEVBQUUsTUFBTSxDQUFDLENBQUMsQ0FBQztTQUNsRTtJQUNILENBQUM7SUFFTyxPQUFPLENBQUMsS0FBZ0IsRUFBRSxNQUFxQjtRQUNyRCxNQUFNLFNBQVMsR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxTQUFTLENBQUMsQ0FBQztRQUNsRCxNQUFNLFVBQVUsR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxVQUFVLENBQUMsQ0FBQztRQUVwRCxNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsT0FBTyxDQUMzQixLQUFLLENBQUMsYUFBYSxFQUNuQixNQUFNLENBQUMsU0FBUyxDQUFDLGFBQWEsQ0FDL0IsQ0FBQztRQUNGLE1BQU0sYUFBYSxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsU0FBUyxFQUFFLE1BQU0sQ0FBQyxTQUFTLENBQUMsU0FBUyxDQUFDLENBQUM7UUFFMUUsTUFBTSxTQUFTLEdBQUcsS0FBSyxDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLEtBQUssS0FBSyxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUV2RSxNQUFNLGNBQWMsR0FBRyxJQUFJLENBQUMsT0FBTyxDQUNqQyxVQUFVLEVBQ1YsTUFBTSxDQUFDLFNBQVMsQ0FBQyxVQUFVLENBQzVCLENBQUM7UUFFRixPQUFPLFFBQVEsSUFBSSxhQUFhLElBQUksU0FBUyxJQUFJLGNBQWMsQ0FBQztJQUNsRSxDQUFDO0lBRU8sT0FBTyxDQUFDLFFBQWlCLEVBQUUsS0FBdUI7UUFDeEQsTUFBTSxPQUFPLEdBQUcsQ0FBQyxHQUFRLEVBQUUsRUFBRSxDQUMzQixPQUFPLEdBQUcsS0FBSyxRQUFRLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUN0RCxNQUFNLFFBQVEsR0FBRyxPQUFPLENBQUMsS0FBSyxDQUFDLENBQUM7UUFFaEMsT0FBTyxDQUFDLFFBQVEsSUFBSSxRQUFRLEtBQUssUUFBUSxDQUFDO0lBQzVDLENBQUM7SUFFRDs7O09BR0c7SUFDSSxLQUFLLENBQUMsS0FBcUI7UUFDaEMsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUVuQyxPQUFPLENBQUMsT0FBTyxDQUFDLENBQUMsTUFBTSxFQUFFLEVBQUU7WUFDekIsTUFBTSxLQUFLLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLENBQUM7WUFDeEMsSUFBSSxLQUFLLEtBQUssQ0FBQyxDQUFDLEVBQUU7Z0JBQ2hCLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLEtBQUssRUFBRSxDQUFDLENBQUMsQ0FBQzthQUM1QjtRQUNILENBQUMsQ0FBQyxDQUFDO1FBQ0gsT0FBTyxPQUFPLENBQUM7SUFDakIsQ0FBQztJQUVEOzs7Ozs7T0FNRztJQUNJLFNBQVMsQ0FBQyxLQUFxQixFQUFFLFdBQW9CO1FBQzFELFdBQVcsR0FBRyxXQUFXLElBQUksSUFBSSxDQUFDLHNCQUFzQixDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQ2hFLE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDbEMsSUFBSSxPQUFPLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRTtZQUN0QixNQUFNLElBQUksS0FBSyxDQUNiLGlEQUFpRCxXQUFXLFlBQVksT0FBTyxDQUFDLE1BQU0sY0FBYyxDQUNyRyxDQUFDO1NBQ0g7UUFDRCxJQUFJLE9BQU8sQ0FBQyxNQUFNLEtBQUssQ0FBQyxFQUFFO1lBQ3hCLE1BQU0sSUFBSSxLQUFLLENBQ2IsaURBQWlELFdBQVcsZ0JBQWdCLENBQzdFLENBQUM7U0FDSDtRQUNELE9BQU8sT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3BCLENBQUM7SUFFRDs7O09BR0c7SUFDSSxVQUFVLENBQUMsS0FBcUIsRUFBRSxXQUFvQjtRQUMzRCxXQUFXLEdBQUcsV0FBVyxJQUFJLElBQUksQ0FBQyxzQkFBc0IsQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUNoRSxNQUFNLE9BQU8sR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQ2xDLElBQUksT0FBTyxDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUU7WUFDdEIsTUFBTSxJQUFJLEtBQUssQ0FDYixtREFBbUQsV0FBVyxZQUFZLE9BQU8sQ0FBQyxNQUFNLEdBQUcsQ0FDNUYsQ0FBQztTQUNIO0lBQ0gsQ0FBQztJQUVEOztPQUVHO0lBQ0ksTUFBTTtRQUNYLE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUM7UUFFdkIsSUFBSSxJQUFJLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRTtZQUNuQiw4RUFBOEU7WUFDOUUsTUFBTSxVQUFVLEdBQUcsSUFBSTtpQkFDcEIsR0FBRyxDQUFDLENBQUMsTUFBTSxFQUFFLEVBQUUsQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDLGFBQWEsQ0FBQztpQkFDL0MsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO1lBQ2QsTUFBTSxJQUFJLEtBQUssQ0FDYixzQ0FBc0MsSUFBSSxDQUFDLE1BQU0sS0FBSyxVQUFVLEVBQUUsQ0FDbkUsQ0FBQztTQUNIO0lBQ0gsQ0FBQztJQUVPLGNBQWMsQ0FDcEIsT0FBaUM7UUFFakMsT0FBTyxDQUFFLE9BQXFCLENBQUMsYUFBYSxDQUFDO0lBQy9DLENBQUM7SUFFTyxzQkFBc0IsQ0FBQyxPQUF1QjtRQUNwRCxJQUFJLE9BQU8sT0FBTyxLQUFLLFFBQVEsRUFBRTtZQUMvQixPQUFPLHdCQUF3QixPQUFPLEVBQUUsQ0FBQztTQUMxQzthQUFNLElBQUksT0FBTyxPQUFPLEtBQUssUUFBUSxFQUFFO1lBQ3RDLElBQUksSUFBSSxDQUFDLGNBQWMsQ0FBQyxPQUFPLENBQUMsRUFBRTtnQkFDaEMsT0FBTyxvQkFBb0IsQ0FBQzthQUM3QjtZQUVELE1BQU0sSUFBSSxHQUFHLE9BQU8sQ0FBQyxhQUFhLElBQUksT0FBTyxDQUFDO1lBQzlDLE1BQU0sU0FBUyxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsT0FBTyxDQUFDLFNBQVMsQ0FBQyxJQUFJLE9BQU8sQ0FBQztZQUUvRCxPQUFPLG9CQUFvQixJQUFJLGdCQUFnQixTQUFTLEVBQUUsQ0FBQztTQUM1RDthQUFNO1lBQ0wsT0FBTyxzQkFBc0IsT0FBTyxDQUFDLElBQUksRUFBRSxDQUFDO1NBQzdDO0lBQ0gsQ0FBQzs7O1lBN0pGLFVBQVUiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge0luamVjdGFibGV9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHtPYnNlcnZlcn0gZnJvbSAncnhqcyc7XG5pbXBvcnQge0ZldGNoUmVzdWx0LCBPYnNlcnZhYmxlIGFzIExpbmtPYnNlcnZhYmxlfSBmcm9tICdAYXBvbGxvL2NsaWVudC9jb3JlJztcbmltcG9ydCB7cHJpbnQsIERvY3VtZW50Tm9kZX0gZnJvbSAnZ3JhcGhxbCc7XG5cbmltcG9ydCB7QXBvbGxvVGVzdGluZ0NvbnRyb2xsZXIsIE1hdGNoT3BlcmF0aW9ufSBmcm9tICcuL2NvbnRyb2xsZXInO1xuaW1wb3J0IHtUZXN0T3BlcmF0aW9uLCBPcGVyYXRpb259IGZyb20gJy4vb3BlcmF0aW9uJztcblxuLyoqXG4gKiBBIHRlc3RpbmcgYmFja2VuZCBmb3IgYEFwb2xsb2AuXG4gKlxuICogYEFwb2xsb1Rlc3RpbmdCYWNrZW5kYCB3b3JrcyBieSBrZWVwaW5nIGEgbGlzdCBvZiBhbGwgb3BlbiBvcGVyYXRpb25zLlxuICogQXMgb3BlcmF0aW9ucyBjb21lIGluLCB0aGV5J3JlIGFkZGVkIHRvIHRoZSBsaXN0LiBVc2VycyBjYW4gYXNzZXJ0IHRoYXQgc3BlY2lmaWNcbiAqIG9wZXJhdGlvbnMgd2VyZSBtYWRlIGFuZCB0aGVuIGZsdXNoIHRoZW0uIEluIHRoZSBlbmQsIGEgdmVyaWZ5KCkgbWV0aG9kIGFzc2VydHNcbiAqIHRoYXQgbm8gdW5leHBlY3RlZCBvcGVyYXRpb25zIHdlcmUgbWFkZS5cbiAqL1xuQEluamVjdGFibGUoKVxuZXhwb3J0IGNsYXNzIEFwb2xsb1Rlc3RpbmdCYWNrZW5kIGltcGxlbWVudHMgQXBvbGxvVGVzdGluZ0NvbnRyb2xsZXIge1xuICAvKipcbiAgICogTGlzdCBvZiBwZW5kaW5nIG9wZXJhdGlvbnMgd2hpY2ggaGF2ZSBub3QgeWV0IGJlZW4gZXhwZWN0ZWQuXG4gICAqL1xuICBwcml2YXRlIG9wZW46IFRlc3RPcGVyYXRpb25bXSA9IFtdO1xuXG4gIC8qKlxuICAgKiBIYW5kbGUgYW4gaW5jb21pbmcgb3BlcmF0aW9uIGJ5IHF1ZXVlaW5nIGl0IGluIHRoZSBsaXN0IG9mIG9wZW4gb3BlcmF0aW9ucy5cbiAgICovXG4gIHB1YmxpYyBoYW5kbGUob3A6IE9wZXJhdGlvbik6IExpbmtPYnNlcnZhYmxlPEZldGNoUmVzdWx0PiB7XG4gICAgcmV0dXJuIG5ldyBMaW5rT2JzZXJ2YWJsZSgob2JzZXJ2ZXI6IE9ic2VydmVyPGFueT4pID0+IHtcbiAgICAgIGNvbnN0IHRlc3RPcCA9IG5ldyBUZXN0T3BlcmF0aW9uKG9wLCBvYnNlcnZlcik7XG4gICAgICB0aGlzLm9wZW4ucHVzaCh0ZXN0T3ApO1xuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIEhlbHBlciBmdW5jdGlvbiB0byBzZWFyY2ggZm9yIG9wZXJhdGlvbnMgaW4gdGhlIGxpc3Qgb2Ygb3BlbiBvcGVyYXRpb25zLlxuICAgKi9cbiAgcHJpdmF0ZSBfbWF0Y2gobWF0Y2g6IE1hdGNoT3BlcmF0aW9uKTogVGVzdE9wZXJhdGlvbltdIHtcbiAgICBpZiAodHlwZW9mIG1hdGNoID09PSAnc3RyaW5nJykge1xuICAgICAgcmV0dXJuIHRoaXMub3Blbi5maWx0ZXIoXG4gICAgICAgICh0ZXN0T3ApID0+IHRlc3RPcC5vcGVyYXRpb24ub3BlcmF0aW9uTmFtZSA9PT0gbWF0Y2gsXG4gICAgICApO1xuICAgIH0gZWxzZSBpZiAodHlwZW9mIG1hdGNoID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICByZXR1cm4gdGhpcy5vcGVuLmZpbHRlcigodGVzdE9wKSA9PiBtYXRjaCh0ZXN0T3Aub3BlcmF0aW9uKSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGlmICh0aGlzLmlzRG9jdW1lbnROb2RlKG1hdGNoKSkge1xuICAgICAgICByZXR1cm4gdGhpcy5vcGVuLmZpbHRlcihcbiAgICAgICAgICAodGVzdE9wKSA9PiBwcmludCh0ZXN0T3Aub3BlcmF0aW9uLnF1ZXJ5KSA9PT0gcHJpbnQobWF0Y2gpLFxuICAgICAgICApO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gdGhpcy5vcGVuLmZpbHRlcigodGVzdE9wKSA9PiB0aGlzLm1hdGNoT3AobWF0Y2gsIHRlc3RPcCkpO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgbWF0Y2hPcChtYXRjaDogT3BlcmF0aW9uLCB0ZXN0T3A6IFRlc3RPcGVyYXRpb24pOiBib29sZWFuIHtcbiAgICBjb25zdCB2YXJpYWJsZXMgPSBKU09OLnN0cmluZ2lmeShtYXRjaC52YXJpYWJsZXMpO1xuICAgIGNvbnN0IGV4dGVuc2lvbnMgPSBKU09OLnN0cmluZ2lmeShtYXRjaC5leHRlbnNpb25zKTtcblxuICAgIGNvbnN0IHNhbWVOYW1lID0gdGhpcy5jb21wYXJlKFxuICAgICAgbWF0Y2gub3BlcmF0aW9uTmFtZSxcbiAgICAgIHRlc3RPcC5vcGVyYXRpb24ub3BlcmF0aW9uTmFtZSxcbiAgICApO1xuICAgIGNvbnN0IHNhbWVWYXJpYWJsZXMgPSB0aGlzLmNvbXBhcmUodmFyaWFibGVzLCB0ZXN0T3Aub3BlcmF0aW9uLnZhcmlhYmxlcyk7XG5cbiAgICBjb25zdCBzYW1lUXVlcnkgPSBwcmludCh0ZXN0T3Aub3BlcmF0aW9uLnF1ZXJ5KSA9PT0gcHJpbnQobWF0Y2gucXVlcnkpO1xuXG4gICAgY29uc3Qgc2FtZUV4dGVuc2lvbnMgPSB0aGlzLmNvbXBhcmUoXG4gICAgICBleHRlbnNpb25zLFxuICAgICAgdGVzdE9wLm9wZXJhdGlvbi5leHRlbnNpb25zLFxuICAgICk7XG5cbiAgICByZXR1cm4gc2FtZU5hbWUgJiYgc2FtZVZhcmlhYmxlcyAmJiBzYW1lUXVlcnkgJiYgc2FtZUV4dGVuc2lvbnM7XG4gIH1cblxuICBwcml2YXRlIGNvbXBhcmUoZXhwZWN0ZWQ/OiBzdHJpbmcsIHZhbHVlPzogT2JqZWN0IHwgc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgY29uc3QgcHJlcGFyZSA9ICh2YWw6IGFueSkgPT5cbiAgICAgIHR5cGVvZiB2YWwgPT09ICdzdHJpbmcnID8gdmFsIDogSlNPTi5zdHJpbmdpZnkodmFsKTtcbiAgICBjb25zdCByZWNlaXZlZCA9IHByZXBhcmUodmFsdWUpO1xuXG4gICAgcmV0dXJuICFleHBlY3RlZCB8fCByZWNlaXZlZCA9PT0gZXhwZWN0ZWQ7XG4gIH1cblxuICAvKipcbiAgICogU2VhcmNoIGZvciBvcGVyYXRpb25zIGluIHRoZSBsaXN0IG9mIG9wZW4gb3BlcmF0aW9ucywgYW5kIHJldHVybiBhbGwgdGhhdCBtYXRjaFxuICAgKiB3aXRob3V0IGFzc2VydGluZyBhbnl0aGluZyBhYm91dCB0aGUgbnVtYmVyIG9mIG1hdGNoZXMuXG4gICAqL1xuICBwdWJsaWMgbWF0Y2gobWF0Y2g6IE1hdGNoT3BlcmF0aW9uKTogVGVzdE9wZXJhdGlvbltdIHtcbiAgICBjb25zdCByZXN1bHRzID0gdGhpcy5fbWF0Y2gobWF0Y2gpO1xuXG4gICAgcmVzdWx0cy5mb3JFYWNoKChyZXN1bHQpID0+IHtcbiAgICAgIGNvbnN0IGluZGV4ID0gdGhpcy5vcGVuLmluZGV4T2YocmVzdWx0KTtcbiAgICAgIGlmIChpbmRleCAhPT0gLTEpIHtcbiAgICAgICAgdGhpcy5vcGVuLnNwbGljZShpbmRleCwgMSk7XG4gICAgICB9XG4gICAgfSk7XG4gICAgcmV0dXJuIHJlc3VsdHM7XG4gIH1cblxuICAvKipcbiAgICogRXhwZWN0IHRoYXQgYSBzaW5nbGUgb3V0c3RhbmRpbmcgcmVxdWVzdCBtYXRjaGVzIHRoZSBnaXZlbiBtYXRjaGVyLCBhbmQgcmV0dXJuXG4gICAqIGl0LlxuICAgKlxuICAgKiBvcGVyYXRpb25zIHJldHVybmVkIHRocm91Z2ggdGhpcyBBUEkgd2lsbCBubyBsb25nZXIgYmUgaW4gdGhlIGxpc3Qgb2Ygb3BlbiBvcGVyYXRpb25zLFxuICAgKiBhbmQgdGh1cyB3aWxsIG5vdCBtYXRjaCB0d2ljZS5cbiAgICovXG4gIHB1YmxpYyBleHBlY3RPbmUobWF0Y2g6IE1hdGNoT3BlcmF0aW9uLCBkZXNjcmlwdGlvbj86IHN0cmluZyk6IFRlc3RPcGVyYXRpb24ge1xuICAgIGRlc2NyaXB0aW9uID0gZGVzY3JpcHRpb24gfHwgdGhpcy5kZXNjcmlwdGlvbkZyb21NYXRjaGVyKG1hdGNoKTtcbiAgICBjb25zdCBtYXRjaGVzID0gdGhpcy5tYXRjaChtYXRjaCk7XG4gICAgaWYgKG1hdGNoZXMubGVuZ3RoID4gMSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBgRXhwZWN0ZWQgb25lIG1hdGNoaW5nIG9wZXJhdGlvbiBmb3IgY3JpdGVyaWEgXCIke2Rlc2NyaXB0aW9ufVwiLCBmb3VuZCAke21hdGNoZXMubGVuZ3RofSBvcGVyYXRpb25zLmAsXG4gICAgICApO1xuICAgIH1cbiAgICBpZiAobWF0Y2hlcy5sZW5ndGggPT09IDApIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgYEV4cGVjdGVkIG9uZSBtYXRjaGluZyBvcGVyYXRpb24gZm9yIGNyaXRlcmlhIFwiJHtkZXNjcmlwdGlvbn1cIiwgZm91bmQgbm9uZS5gLFxuICAgICAgKTtcbiAgICB9XG4gICAgcmV0dXJuIG1hdGNoZXNbMF07XG4gIH1cblxuICAvKipcbiAgICogRXhwZWN0IHRoYXQgbm8gb3V0c3RhbmRpbmcgb3BlcmF0aW9ucyBtYXRjaCB0aGUgZ2l2ZW4gbWF0Y2hlciwgYW5kIHRocm93IGFuIGVycm9yXG4gICAqIGlmIGFueSBkby5cbiAgICovXG4gIHB1YmxpYyBleHBlY3ROb25lKG1hdGNoOiBNYXRjaE9wZXJhdGlvbiwgZGVzY3JpcHRpb24/OiBzdHJpbmcpOiB2b2lkIHtcbiAgICBkZXNjcmlwdGlvbiA9IGRlc2NyaXB0aW9uIHx8IHRoaXMuZGVzY3JpcHRpb25Gcm9tTWF0Y2hlcihtYXRjaCk7XG4gICAgY29uc3QgbWF0Y2hlcyA9IHRoaXMubWF0Y2gobWF0Y2gpO1xuICAgIGlmIChtYXRjaGVzLmxlbmd0aCA+IDApIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgYEV4cGVjdGVkIHplcm8gbWF0Y2hpbmcgb3BlcmF0aW9ucyBmb3IgY3JpdGVyaWEgXCIke2Rlc2NyaXB0aW9ufVwiLCBmb3VuZCAke21hdGNoZXMubGVuZ3RofS5gLFxuICAgICAgKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogVmFsaWRhdGUgdGhhdCB0aGVyZSBhcmUgbm8gb3V0c3RhbmRpbmcgb3BlcmF0aW9ucy5cbiAgICovXG4gIHB1YmxpYyB2ZXJpZnkoKTogdm9pZCB7XG4gICAgY29uc3Qgb3BlbiA9IHRoaXMub3BlbjtcblxuICAgIGlmIChvcGVuLmxlbmd0aCA+IDApIHtcbiAgICAgIC8vIFNob3cgdGhlIG1ldGhvZHMgYW5kIFVSTHMgb2Ygb3BlbiBvcGVyYXRpb25zIGluIHRoZSBlcnJvciwgZm9yIGNvbnZlbmllbmNlLlxuICAgICAgY29uc3Qgb3BlcmF0aW9ucyA9IG9wZW5cbiAgICAgICAgLm1hcCgodGVzdE9wKSA9PiB0ZXN0T3Aub3BlcmF0aW9uLm9wZXJhdGlvbk5hbWUpXG4gICAgICAgIC5qb2luKCcsICcpO1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBgRXhwZWN0ZWQgbm8gb3BlbiBvcGVyYXRpb25zLCBmb3VuZCAke29wZW4ubGVuZ3RofTogJHtvcGVyYXRpb25zfWAsXG4gICAgICApO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgaXNEb2N1bWVudE5vZGUoXG4gICAgZG9jT3JPcDogRG9jdW1lbnROb2RlIHwgT3BlcmF0aW9uLFxuICApOiBkb2NPck9wIGlzIERvY3VtZW50Tm9kZSB7XG4gICAgcmV0dXJuICEoZG9jT3JPcCBhcyBPcGVyYXRpb24pLm9wZXJhdGlvbk5hbWU7XG4gIH1cblxuICBwcml2YXRlIGRlc2NyaXB0aW9uRnJvbU1hdGNoZXIobWF0Y2hlcjogTWF0Y2hPcGVyYXRpb24pOiBzdHJpbmcge1xuICAgIGlmICh0eXBlb2YgbWF0Y2hlciA9PT0gJ3N0cmluZycpIHtcbiAgICAgIHJldHVybiBgTWF0Y2ggb3BlcmF0aW9uTmFtZTogJHttYXRjaGVyfWA7XG4gICAgfSBlbHNlIGlmICh0eXBlb2YgbWF0Y2hlciA9PT0gJ29iamVjdCcpIHtcbiAgICAgIGlmICh0aGlzLmlzRG9jdW1lbnROb2RlKG1hdGNoZXIpKSB7XG4gICAgICAgIHJldHVybiBgTWF0Y2ggRG9jdW1lbnROb2RlYDtcbiAgICAgIH1cblxuICAgICAgY29uc3QgbmFtZSA9IG1hdGNoZXIub3BlcmF0aW9uTmFtZSB8fCAnKGFueSknO1xuICAgICAgY29uc3QgdmFyaWFibGVzID0gSlNPTi5zdHJpbmdpZnkobWF0Y2hlci52YXJpYWJsZXMpIHx8ICcoYW55KSc7XG5cbiAgICAgIHJldHVybiBgTWF0Y2ggb3BlcmF0aW9uOiAke25hbWV9LCB2YXJpYWJsZXM6ICR7dmFyaWFibGVzfWA7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBgTWF0Y2ggYnkgZnVuY3Rpb246ICR7bWF0Y2hlci5uYW1lfWA7XG4gICAgfVxuICB9XG59XG4iXX0=