UNPKG

@ngneat/spectator

Version:

A powerful tool to simplify your Angular tests

288 lines 44.9 kB
import { DebugElement, ElementRef, OutputEmitterRef } from '@angular/core'; import { tick } from '@angular/core/testing'; import { By } from '@angular/platform-browser'; import { Observable } from 'rxjs'; import { dispatchFakeEvent, dispatchKeyboardEvent, dispatchMouseEvent, dispatchTouchEvent } from '../dispatch-events'; import { DOMSelector } from '../dom-selectors'; import { createMouseEvent } from '../event-creators'; import { patchElementFocus } from '../internals/element-focus'; import { getChildren } from '../internals/query'; import { selectOption } from '../select-option'; import { typeInElement } from '../type-in-element'; import { isString } from '../types'; import { BaseSpectator } from './base-spectator'; const KEY_UP = 'keyup'; /** * @internal */ export class DomSpectator extends BaseSpectator { constructor(fixture, debugElement, instance, element) { super(); this.fixture = fixture; this.debugElement = debugElement; this.instance = instance; this.element = element; } inject(token) { return super.inject(token); } detectChanges() { this.fixture.detectChanges(); } query(directiveOrSelector, options) { if ((options || {}).root) { if (isString(directiveOrSelector)) { return document.querySelector(directiveOrSelector); } if (directiveOrSelector instanceof DOMSelector) { return directiveOrSelector.execute(document)[0] || null; } return getChildren(this.getRootDebugElement())(directiveOrSelector, options)[0] || null; } if (options?.parentSelector) { const debugElement = this.getDebugElement(options.parentSelector); if (!debugElement) { /* eslint-disable no-console */ console.error(`${directiveOrSelector} does not exists`); return null; } return (getChildren(debugElement)(directiveOrSelector, { root: options.root, read: options.read, })[0] || null); } return getChildren(this.debugElement)(directiveOrSelector, options)[0] || null; } queryAll(directiveOrSelector, options) { if ((options || {}).root) { if (isString(directiveOrSelector)) { return Array.from(document.querySelectorAll(directiveOrSelector)); } if (directiveOrSelector instanceof DOMSelector) { return directiveOrSelector.execute(document); } return getChildren(this.getRootDebugElement())(directiveOrSelector, options); } if (options?.parentSelector) { const debugElement = this.getDebugElement(options.parentSelector); if (!debugElement) { /* eslint-disable no-console */ console.error(`${directiveOrSelector} does not exists`); return []; } return getChildren(debugElement)(directiveOrSelector, { root: options.root, read: options.read, }); } return getChildren(this.debugElement)(directiveOrSelector, options); } queryLast(directiveOrSelector, options) { let result = []; if ((options || {}).root) { if (isString(directiveOrSelector)) { result = Array.from(document.querySelectorAll(directiveOrSelector)); } else if (directiveOrSelector instanceof DOMSelector) { result = directiveOrSelector.execute(document); } else { result = getChildren(this.getRootDebugElement())(directiveOrSelector, options); } } else if (options?.parentSelector) { const debugElement = this.getDebugElement(options.parentSelector); if (!debugElement) { /* eslint-disable no-console */ console.error(`${directiveOrSelector} does not exists`); result = []; } else { result = getChildren(debugElement)(directiveOrSelector, { root: options.root, read: options.read, }); } } else { result = getChildren(this.debugElement)(directiveOrSelector, options); } if (result && result.length) { return result[result.length - 1]; } return null; } output(output) { const eventEmitter = this.instance[output]; if (!(eventEmitter instanceof Observable) && !(eventEmitter instanceof OutputEmitterRef)) { throw new Error(`${String(output)} is not an @Output or an output function`); } return eventEmitter; } tick(millis) { tick(millis); this.detectChanges(); } click(selector = this.element) { const element = this.getNativeElement(selector); if (!(element instanceof HTMLElement)) { throw new Error(`Cannot click: ${selector} is not a HTMLElement`); } element.click(); this.detectChanges(); } blur(selector = this.element) { const element = this.getNativeElement(selector); if (!(element instanceof HTMLElement)) { throw new Error(`Cannot blur: ${selector} is not a HTMLElement`); } patchElementFocus(element); element.blur(); this.detectChanges(); } focus(selector = this.element) { const element = this.getNativeElement(selector); if (!(element instanceof HTMLElement)) { throw new Error(`Cannot focus: ${selector} is not a HTMLElement`); } patchElementFocus(element); element.focus(); this.detectChanges(); } dispatchMouseEvent(selector = this.element, type, x = 0, y = 0, event = createMouseEvent(type, x, y)) { const element = this.getNativeElement(selector); if (!(element instanceof Node)) { throw new Error(`Cannot dispatch mouse event: ${selector} is not a node`); } const dispatchedEvent = dispatchMouseEvent(element, type, x, y, event); this.detectChanges(); return dispatchedEvent; } dispatchKeyboardEvent(selector = this.element, type, keyOrKeyCode, target) { const element = this.getNativeElement(selector); if (!(element instanceof Node)) { throw new Error(`Cannot dispatch keyboard event: ${selector} is not a node`); } const event = dispatchKeyboardEvent(element, type, keyOrKeyCode, target); this.detectChanges(); return event; } dispatchFakeEvent(selector = this.element, type, canBubble) { const event = dispatchFakeEvent(this.getNativeElement(selector), type, canBubble); this.detectChanges(); return event; } triggerEventHandler(directiveOrSelector, eventName, eventObj, options) { const triggerDebugElement = this.getDebugElement(directiveOrSelector, options); if (!triggerDebugElement) { /* eslint-disable no-console */ console.error(`${directiveOrSelector} does not exists`); return; } triggerDebugElement.triggerEventHandler(eventName, eventObj); this.detectChanges(); } get keyboard() { return { pressKey: (key, selector = this.element, event = KEY_UP) => { this.dispatchKeyboardEvent(selector, event, key); }, pressEscape: (selector = this.element, event = KEY_UP) => { this.dispatchKeyboardEvent(selector, event, { key: 'Escape', keyCode: 27 }); }, pressEnter: (selector = this.element, event = KEY_UP) => { this.dispatchKeyboardEvent(selector, event, { key: 'Enter', keyCode: 13 }); }, pressTab: (selector = this.element, event = KEY_UP) => { this.dispatchKeyboardEvent(selector, event, { key: 'Tab', keyCode: 9 }); }, pressBackspace: (selector = this.element, event = KEY_UP) => { this.dispatchKeyboardEvent(selector, event, { key: 'Backspace', keyCode: 8 }); }, }; } get mouse() { return { contextmenu: (selector = this.element) => { this.dispatchMouseEvent(selector, 'contextmenu'); }, dblclick: (selector = this.element) => { this.dispatchMouseEvent(selector, 'dblclick'); }, }; } dispatchTouchEvent(selector = this.element, type, x = 0, y = 0) { dispatchTouchEvent(this.getNativeElement(selector), type, x, y); this.detectChanges(); } typeInElement(value, selector = this.element) { typeInElement(value, this.getNativeElement(selector)); this.detectChanges(); } selectOption(selector = this.element, options, config = { emitEvents: true }) { if (!selector) { throw new Error(`Cannot find select: ${selector}`); } selectOption(options, this.getNativeElement(selector), config); this.detectChanges(); } getNativeElement(selector) { let element; // Support global objects window and document if (selector === window || selector === document) { return selector; } if (isString(selector)) { const exists = this.debugElement.query(By.css(selector)); if (exists) { element = exists.nativeElement; } else { /* eslint-disable no-console */ console.error(`${selector} does not exists`); } } else if (selector instanceof DOMSelector) { element = selector.execute(document)[0] || null; } else { if (selector instanceof DebugElement || selector instanceof ElementRef) { element = selector.nativeElement; } else { element = selector; } } return element; } getDebugElement(directiveOrSelector, options) { const debugElement = options?.root ? this.getRootDebugElement() : this.debugElement; if (isString(directiveOrSelector)) { return debugElement.query(By.css(directiveOrSelector)); } else if (directiveOrSelector instanceof DebugElement) { return directiveOrSelector; } else { return debugElement.query(By.directive(directiveOrSelector)); } } getRootDebugElement() { let element = this.debugElement; /** * This bounded loop call is required to access the debug element for * root dom element */ while (true) { if (!element) { throw Error('Unable to find root element'); } if (!element.parent) { // Found the root element return element; } element = element.parent; } } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZG9tLXNwZWN0YXRvci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL3NwZWN0YXRvci9zcmMvbGliL2Jhc2UvZG9tLXNwZWN0YXRvci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsWUFBWSxFQUFFLFVBQVUsRUFBZ0IsZ0JBQWdCLEVBQVEsTUFBTSxlQUFlLENBQUM7QUFDL0YsT0FBTyxFQUFvQixJQUFJLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQztBQUMvRCxPQUFPLEVBQUUsRUFBRSxFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFDL0MsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUVsQyxPQUFPLEVBQUUsaUJBQWlCLEVBQUUscUJBQXFCLEVBQUUsa0JBQWtCLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUN0SCxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFDL0MsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sbUJBQW1CLENBQUM7QUFDckQsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0sNEJBQTRCLENBQUM7QUFDL0QsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBRWpELE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUVoRCxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFDbkQsT0FBTyxFQUE2RixRQUFRLEVBQUUsTUFBTSxVQUFVLENBQUM7QUFFL0gsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBRWpELE1BQU0sTUFBTSxHQUFHLE9BQU8sQ0FBQztBQU92Qjs7R0FFRztBQUNILE1BQU0sT0FBZ0IsWUFBZ0IsU0FBUSxhQUFhO0lBQ3pELFlBQ1MsT0FBOEIsRUFDOUIsWUFBMEIsRUFDdkIsUUFBVyxFQUNkLE9BQWdC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bUJBQW1CO1FBQ3pCLElBQUksT0FBTyxHQUFvQyxJQUFJLENBQUMsWUFBWSxDQUFDO1FBRWpFOzs7V0FHRztRQUNILE9BQU8sSUFBSSxFQUFFLENBQUM7WUFDWixJQUFJLENBQUMsT0FBTyxFQUFFLENBQUM7Z0JBQ2IsTUFBTSxLQUFLLENBQUMsNkJBQTZCLENBQUMsQ0FBQztZQUM3QyxDQUFDO1lBRUQsSUFBSSxDQUFDLE9BQU8sQ0FBQyxNQUFNLEVBQUUsQ0FBQztnQkFDcEIseUJBQXlCO2dCQUN6QixPQUFPLE9BQU8sQ0FBQztZQUNqQixDQUFDO1lBRUQsT0FBTyxHQUFHLE9BQU8sQ0FBQyxNQUFNLENBQUM7UUFDM0IsQ0FBQztJQUNILENBQUM7Q0FDRiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IERlYnVnRWxlbWVudCwgRWxlbWVudFJlZiwgRXZlbnRFbWl0dGVyLCBPdXRwdXRFbWl0dGVyUmVmLCBUeXBlIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBDb21wb25lbnRGaXh0dXJlLCB0aWNrIH0gZnJvbSAnQGFuZ3VsYXIvY29yZS90ZXN0aW5nJztcbmltcG9ydCB7IEJ5IH0gZnJvbSAnQGFuZ3VsYXIvcGxhdGZvcm0tYnJvd3Nlcic7XG5pbXBvcnQgeyBPYnNlcnZhYmxlIH0gZnJvbSAncnhqcyc7XG5cbmltcG9ydCB7IGRpc3BhdGNoRmFrZUV2ZW50LCBkaXNwYXRjaEtleWJvYXJkRXZlbnQsIGRpc3BhdGNoTW91c2VFdmVudCwgZGlzcGF0Y2hUb3VjaEV2ZW50IH0gZnJvbSAnLi4vZGlzcGF0Y2gtZXZlbnRzJztcbmltcG9ydCB7IERPTVNlbGVjdG9yIH0gZnJvbSAnLi4vZG9tLXNlbGVjdG9ycyc7XG5pbXBvcnQgeyBjcmVhdGVNb3VzZUV2ZW50IH0gZnJvbSAnLi4vZXZlbnQtY3JlYXRvcnMnO1xuaW1wb3J0IHsgcGF0Y2hFbGVtZW50Rm9jdXMgfSBmcm9tICcuLi9pbnRlcm5hbHMvZWxlbWVudC1mb2N1cyc7XG5pbXBvcnQgeyBnZXRDaGlsZHJlbiB9IGZyb20gJy4uL2ludGVybmFscy9xdWVyeSc7XG5pbXBvcnQgeyBTcHlPYmplY3QgfSBmcm9tICcuLi9tb2NrJztcbmltcG9ydCB7IHNlbGVjdE9wdGlvbiB9IGZyb20gJy4uL3NlbGVjdC1vcHRpb24nO1xuaW1wb3J0IHsgVG9rZW4gfSBmcm9tICcuLi90b2tlbic7XG5pbXBvcnQgeyB0eXBlSW5FbGVtZW50IH0gZnJvbSAnLi4vdHlwZS1pbi1lbGVtZW50JztcbmltcG9ydCB7IE91dHB1dFR5cGUsIEtleWJvYXJkRXZlbnRPcHRpb25zLCBLZXlzTWF0Y2hpbmcsIFF1ZXJ5T3B0aW9ucywgUXVlcnlUeXBlLCBTcGVjdGF0b3JFbGVtZW50LCBpc1N0cmluZyB9IGZyb20gJy4uL3R5cGVzJztcblxuaW1wb3J0IHsgQmFzZVNwZWN0YXRvciB9IGZyb20gJy4vYmFzZS1zcGVjdGF0b3InO1xuXG5jb25zdCBLRVlfVVAgPSAna2V5dXAnO1xuXG50eXBlIEtleXNNYXRjaGluZ1JldHVyblR5cGU8VCwgVj4gPSBrZXlvZiB7IFtQIGluIGtleW9mIFQgYXMgVFtQXSBleHRlbmRzIFYgPyBQIDogbmV2ZXJdOiBQIH0gJiBrZXlvZiBUO1xudHlwZSBLZXlzTWF0Y2hpbmdPdXRwdXRGdW5jdGlvbjxUPiA9IEtleXNNYXRjaGluZ1JldHVyblR5cGU8VCwgT3V0cHV0RW1pdHRlclJlZjxhbnk+PjtcbnR5cGUgS2V5c01hdGNoaW5nQ2xhc3NpY091dHB1dDxUPiA9IEtleXNNYXRjaGluZ1JldHVyblR5cGU8VCwgRXZlbnRFbWl0dGVyPGFueT4+O1xudHlwZSBLZXlzTWF0Y2hpbmdPdXRwdXQ8VD4gPSBLZXlzTWF0Y2hpbmdPdXRwdXRGdW5jdGlvbjxUPiB8IEtleXNNYXRjaGluZ0NsYXNzaWNPdXRwdXQ8VD47XG5cbi8qKlxuICogQGludGVybmFsXG4gKi9cbmV4cG9ydCBhYnN0cmFjdCBjbGFzcyBEb21TcGVjdGF0b3I8ST4gZXh0ZW5kcyBCYXNlU3BlY3RhdG9yIHtcbiAgY29uc3RydWN0b3IoXG4gICAgcHVibGljIGZpeHR1cmU6IENvbXBvbmVudEZpeHR1cmU8YW55PixcbiAgICBwdWJsaWMgZGVidWdFbGVtZW50OiBEZWJ1Z0VsZW1lbnQsXG4gICAgcHJvdGVjdGVkIGluc3RhbmNlOiBJLFxuICAgIHB1YmxpYyBlbGVtZW50OiBFbGVtZW50LFxuICApIHtcbiAgICBzdXBlcigpO1xuICB9XG5cbiAgcHVibGljIGluamVjdDxUPih0b2tlbjogVG9rZW48VD4pOiBTcHlPYmplY3Q8VD4ge1xuICAgIHJldHVybiBzdXBlci5pbmplY3QodG9rZW4pO1xuICB9XG5cbiAgcHVibGljIGRldGVjdENoYW5nZXMoKTogdm9pZCB7XG4gICAgdGhpcy5maXh0dXJlLmRldGVjdENoYW5nZXMoKTtcbiAgfVxuXG4gIHB1YmxpYyBxdWVyeTxSIGV4dGVuZHMgRWxlbWVudD4oc2VsZWN0b3I6IHN0cmluZyB8IERPTVNlbGVjdG9yLCBvcHRpb25zPzogeyByb290OiBib29sZWFuIH0pOiBSIHwgbnVsbDtcbiAgcHVibGljIHF1ZXJ5PFI+KGRpcmVjdGl2ZTogVHlwZTxSPiwgb3B0aW9ucz86IHsgcm9vdDogYm9vbGVhbiB9KTogUiB8IG51bGw7XG4gIHB1YmxpYyBxdWVyeTxSIGV4dGVuZHMgRWxlbWVudD4oc2VsZWN0b3I6IHN0cmluZyB8IERPTVNlbGVjdG9yLCBvcHRpb25zPzogeyBwYXJlbnRTZWxlY3RvcjogVHlwZTxhbnk+IHwgc3RyaW5nIH0pOiBSIHwgbnVsbDtcbiAgcHVibGljIHF1ZXJ5PFI+KGRpcmVjdGl2ZTogVHlwZTxSPiwgb3B0aW9ucz86IHsgcGFyZW50U2VsZWN0b3I/OiBUeXBlPGFueT4gfCBzdHJpbmcgfSk6IFIgfCBudWxsO1xuICBwdWJsaWMgcXVlcnk8Uj4oXG4gICAgZGlyZWN0aXZlT3JTZWxlY3RvcjogVHlwZTxhbnk+IHwgc3RyaW5nLFxuICAgIG9wdGlvbnM6IHsgcmVhZDogVG9rZW48Uj47IHJvb3Q/OiBib29sZWFuOyBwYXJlbnRTZWxlY3Rvcj86IFR5cGU8YW55PiB8IHN0cmluZyB9LFxuICApOiBSIHwgbnVsbDtcbiAgcHVibGljIHF1ZXJ5PFI+KGRpcmVjdGl2ZU9yU2VsZWN0b3I6IFF1ZXJ5VHlwZSwgb3B0aW9ucz86IFF1ZXJ5T3B0aW9uczxSPik6IFIgfCBFbGVtZW50IHwgbnVsbCB7XG4gICAgaWYgKChvcHRpb25zIHx8IHt9KS5yb290KSB7XG4gICAgICBpZiAoaXNTdHJpbmcoZGlyZWN0aXZlT3JTZWxlY3RvcikpIHtcbiAgICAgICAgcmV0dXJuIGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoZGlyZWN0aXZlT3JTZWxlY3Rvcik7XG4gICAgICB9XG5cbiAgICAgIGlmIChkaXJlY3RpdmVPclNlbGVjdG9yIGluc3RhbmNlb2YgRE9NU2VsZWN0b3IpIHtcbiAgICAgICAgcmV0dXJuIGRpcmVjdGl2ZU9yU2VsZWN0b3IuZXhlY3V0ZShkb2N1bWVudCBhcyBhbnkpWzBdIHx8IG51bGw7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBnZXRDaGlsZHJlbjxSPih0aGlzLmdldFJvb3REZWJ1Z0VsZW1lbnQoKSkoZGlyZWN0aXZlT3JTZWxlY3Rvciwgb3B0aW9ucylbMF0gfHwgbnVsbDtcbiAgICB9XG5cbiAgICBpZiAob3B0aW9ucz8ucGFyZW50U2VsZWN0b3IpIHtcbiAgICAgIGNvbnN0IGRlYnVnRWxlbWVudCA9IHRoaXMuZ2V0RGVidWdFbGVtZW50KG9wdGlvbnMucGFyZW50U2VsZWN0b3IpO1xuICAgICAgaWYgKCFkZWJ1Z0VsZW1lbnQpIHtcbiAgICAgICAgLyogZXNsaW50LWRpc2FibGUgbm8tY29uc29sZSAqL1xuICAgICAgICBjb25zb2xlLmVycm9yKGAke2RpcmVjdGl2ZU9yU2VsZWN0b3J9IGRvZXMgbm90IGV4aXN0c2ApO1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIChcbiAgICAgICAgZ2V0Q2hpbGRyZW48Uj4oZGVidWdFbGVtZW50IGFzIERlYnVnRWxlbWVudCkoZGlyZWN0aXZlT3JTZWxlY3Rvciwge1xuICAgICAgICAgIHJvb3Q6IG9wdGlvbnMucm9vdCxcbiAgICAgICAgICByZWFkOiBvcHRpb25zLnJlYWQsXG4gICAgICAgIH0pWzBdIHx8IG51bGxcbiAgICAgICk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGdldENoaWxkcmVuPFI+KHRoaXMuZGVidWdFbGVtZW50KShkaXJlY3RpdmVPclNlbGVjdG9yLCBvcHRpb25zKVswXSB8fCBudWxsO1xuICB9XG5cbiAgcHVibGljIHF1ZXJ5QWxsPFIgZXh0ZW5kcyBFbGVtZW50PihzZWxlY3Rvcjogc3RyaW5nIHwgRE9NU2VsZWN0b3IsIG9wdGlvbnM/OiB7IHJvb3Q6IGJvb2xlYW4gfSk6IFJbXTtcbiAgcHVibGljIHF1ZXJ5QWxsPFI+KGRpcmVjdGl2ZTogVHlwZTxSPiwgb3B0aW9ucz86IHsgcm9vdDogYm9vbGVhbiB9KTogUltdO1xuICBwdWJsaWMgcXVlcnlBbGw8UiBleHRlbmRzIEVsZW1lbnQ+KHNlbGVjdG9yOiBzdHJpbmcgfCBET01TZWxlY3Rvciwgb3B0aW9ucz86IHsgcGFyZW50U2VsZWN0b3I6IFR5cGU8YW55PiB8IHN0cmluZyB9KTogUltdO1xuICBwdWJsaWMgcXVlcnlBbGw8Uj4oZGlyZWN0aXZlOiBUeXBlPFI+LCBvcHRpb25zPzogeyBwYXJlbnRTZWxlY3RvcjogVHlwZTxhbnk+IHwgc3RyaW5nIH0pOiBSW107XG4gIHB1YmxpYyBxdWVyeUFsbDxSPihcbiAgICBkaXJlY3RpdmVPclNlbGVjdG9yOiBUeXBlPGFueT4gfCBzdHJpbmcsXG4gICAgb3B0aW9uczogeyByZWFkOiBUb2tlbjxSPjsgcm9vdD86IGJvb2xlYW47IHBhcmVudFNlbGVjdG9yPzogVHlwZTxhbnk+IHwgc3RyaW5nIH0sXG4gICk6IFJbXTtcbiAgcHVibGljIHF1ZXJ5QWxsPFI+KGRpcmVjdGl2ZU9yU2VsZWN0b3I6IFF1ZXJ5VHlwZSwgb3B0aW9ucz86IFF1ZXJ5T3B0aW9uczxSPik6IFJbXSB8IEVsZW1lbnRbXSB7XG4gICAgaWYgKChvcHRpb25zIHx8IHt9KS5yb290KSB7XG4gICAgICBpZiAoaXNTdHJpbmcoZGlyZWN0aXZlT3JTZWxlY3RvcikpIHtcbiAgICAgICAgcmV0dXJuIEFycmF5LmZyb20oZG9jdW1lbnQucXVlcnlTZWxlY3RvckFsbChkaXJlY3RpdmVPclNlbGVjdG9yKSk7XG4gICAgICB9XG5cbiAgICAgIGlmIChkaXJlY3RpdmVPclNlbGVjdG9yIGluc3RhbmNlb2YgRE9NU2VsZWN0b3IpIHtcbiAgICAgICAgcmV0dXJuIGRpcmVjdGl2ZU9yU2VsZWN0b3IuZXhlY3V0ZShkb2N1bWVudCBhcyBhbnkpO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gZ2V0Q2hpbGRyZW48Uj4odGhpcy5nZXRSb290RGVidWdFbGVtZW50KCkpKGRpcmVjdGl2ZU9yU2VsZWN0b3IsIG9wdGlvbnMpO1xuICAgIH1cblxuICAgIGlmIChvcHRpb25zPy5wYXJlbnRTZWxlY3Rvcikge1xuICAgICAgY29uc3QgZGVidWdFbGVtZW50ID0gdGhpcy5nZXREZWJ1Z0VsZW1lbnQob3B0aW9ucy5wYXJlbnRTZWxlY3Rvcik7XG4gICAgICBpZiAoIWRlYnVnRWxlbWVudCkge1xuICAgICAgICAvKiBlc2xpbnQtZGlzYWJsZSBuby1jb25zb2xlICovXG4gICAgICAgIGNvbnNvbGUuZXJyb3IoYCR7ZGlyZWN0aXZlT3JTZWxlY3Rvcn0gZG9lcyBub3QgZXhpc3RzYCk7XG4gICAgICAgIHJldHVybiBbXTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIGdldENoaWxkcmVuPFI+KGRlYnVnRWxlbWVudCBhcyBEZWJ1Z0VsZW1lbnQpKGRpcmVjdGl2ZU9yU2VsZWN0b3IsIHtcbiAgICAgICAgcm9vdDogb3B0aW9ucy5yb290LFxuICAgICAgICByZWFkOiBvcHRpb25zLnJlYWQsXG4gICAgICB9KTtcbiAgICB9XG5cbiAgICByZXR1cm4gZ2V0Q2hpbGRyZW48Uj4odGhpcy5kZWJ1Z0VsZW1lbnQpKGRpcmVjdGl2ZU9yU2VsZWN0b3IsIG9wdGlvbnMpO1xuICB9XG5cbiAgcHVibGljIHF1ZXJ5TGFzdDxSIGV4dGVuZHMgRWxlbWVudD4oc2VsZWN0b3I6IHN0cmluZyB8IERPTVNlbGVjdG9yLCBvcHRpb25zPzogeyByb290OiBib29sZWFuIH0pOiBSIHwgbnVsbDtcbiAgcHVibGljIHF1ZXJ5TGFzdDxSPihkaXJlY3RpdmU6IFR5cGU8Uj4sIG9wdGlvbnM/OiB7IHJvb3Q6IGJvb2xlYW4gfSk6IFIgfCBudWxsO1xuICBwdWJsaWMgcXVlcnlMYXN0PFIgZXh0ZW5kcyBFbGVtZW50PihzZWxlY3Rvcjogc3RyaW5nIHwgRE9NU2VsZWN0b3IsIG9wdGlvbnM/OiB7IHBhcmVudFNlbGVjdG9yOiBUeXBlPGFueT4gfCBzdHJpbmcgfSk6IFIgfCBudWxsO1xuICBwdWJsaWMgcXVlcnlMYXN0PFI+KGRpcmVjdGl2ZTogVHlwZTxSPiwgb3B0aW9ucz86IHsgcGFyZW50U2VsZWN0b3I6IFR5cGU8YW55PiB8IHN0cmluZyB9KTogUiB8IG51bGw7XG4gIHB1YmxpYyBxdWVyeUxhc3Q8Uj4oXG4gICAgZGlyZWN0aXZlT3JTZWxlY3RvcjogVHlwZTxhbnk+IHwgc3RyaW5nLFxuICAgIG9wdGlvbnM6IHsgcmVhZDogVG9rZW48Uj47IHJvb3Q/OiBib29sZWFuOyBwYXJlbnRTZWxlY3Rvcj86IFR5cGU8YW55PiB8IHN0cmluZyB9LFxuICApOiBSIHwgbnVsbDtcbiAgcHVibGljIHF1ZXJ5TGFzdDxSPihkaXJlY3RpdmVPclNlbGVjdG9yOiBRdWVyeVR5cGUsIG9wdGlvbnM/OiBRdWVyeU9wdGlvbnM8Uj4pOiBSIHwgRWxlbWVudCB8IG51bGwge1xuICAgIGxldCByZXN1bHQ6IChSIHwgRWxlbWVudClbXSA9IFtdO1xuXG4gICAgaWYgKChvcHRpb25zIHx8IHt9KS5yb290KSB7XG4gICAgICBpZiAoaXNTdHJpbmcoZGlyZWN0aXZlT3JTZWxlY3RvcikpIHtcbiAgICAgICAgcmVzdWx0ID0gQXJyYXkuZnJvbShkb2N1bWVudC5xdWVyeVNlbGVjdG9yQWxsKGRpcmVjdGl2ZU9yU2VsZWN0b3IpKTtcbiAgICAgIH0gZWxzZSBpZiAoZGlyZWN0aXZlT3JTZWxlY3RvciBpbnN0YW5jZW9mIERPTVNlbGVjdG9yKSB7XG4gICAgICAgIHJlc3VsdCA9IGRpcmVjdGl2ZU9yU2VsZWN0b3IuZXhlY3V0ZShkb2N1bWVudCBhcyBhbnkpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmVzdWx0ID0gZ2V0Q2hpbGRyZW48Uj4odGhpcy5nZXRSb290RGVidWdFbGVtZW50KCkpKGRpcmVjdGl2ZU9yU2VsZWN0b3IsIG9wdGlvbnMpO1xuICAgICAgfVxuICAgIH0gZWxzZSBpZiAob3B0aW9ucz8ucGFyZW50U2VsZWN0b3IpIHtcbiAgICAgIGNvbnN0IGRlYnVnRWxlbWVudCA9IHRoaXMuZ2V0RGVidWdFbGVtZW50KG9wdGlvbnMucGFyZW50U2VsZWN0b3IpO1xuICAgICAgaWYgKCFkZWJ1Z0VsZW1lbnQpIHtcbiAgICAgICAgLyogZXNsaW50LWRpc2FibGUgbm8tY29uc29sZSAqL1xuICAgICAgICBjb25zb2xlLmVycm9yKGAke2RpcmVjdGl2ZU9yU2VsZWN0b3J9IGRvZXMgbm90IGV4aXN0c2ApO1xuICAgICAgICByZXN1bHQgPSBbXTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJlc3VsdCA9IGdldENoaWxkcmVuPFI+KGRlYnVnRWxlbWVudCBhcyBEZWJ1Z0VsZW1lbnQpKGRpcmVjdGl2ZU9yU2VsZWN0b3IsIHtcbiAgICAgICAgICByb290OiBvcHRpb25zLnJvb3QsXG4gICAgICAgICAgcmVhZDogb3B0aW9ucy5yZWFkLFxuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgcmVzdWx0ID0gZ2V0Q2hpbGRyZW48Uj4odGhpcy5kZWJ1Z0VsZW1lbnQpKGRpcmVjdGl2ZU9yU2VsZWN0b3IsIG9wdGlvbnMpO1xuICAgIH1cblxuICAgIGlmIChyZXN1bHQgJiYgcmVzdWx0Lmxlbmd0aCkge1xuICAgICAgcmV0dXJuIHJlc3VsdFtyZXN1bHQubGVuZ3RoIC0gMV07XG4gICAgfVxuXG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICBwdWJsaWMgb3V0cHV0PEsgZXh0ZW5kcyBLZXlzTWF0Y2hpbmdPdXRwdXQ8ST4gPSBLZXlzTWF0Y2hpbmdPdXRwdXQ8ST4+KG91dHB1dDogSyk6IElbS107XG4gIHB1YmxpYyBvdXRwdXQ8VCwgSyBleHRlbmRzIEtleXNNYXRjaGluZ0NsYXNzaWNPdXRwdXQ8ST4gPSBLZXlzTWF0Y2hpbmdDbGFzc2ljT3V0cHV0PEk+PihvdXRwdXQ6IEspOiBPYnNlcnZhYmxlPFQ+O1xuICBwdWJsaWMgb3V0cHV0PFQsIEsgZXh0ZW5kcyBLZXlzTWF0Y2hpbmdPdXRwdXRGdW5jdGlvbjxJPiA9IEtleXNNYXRjaGluZ091dHB1dEZ1bmN0aW9uPEk+PihvdXRwdXQ6IEspOiBPdXRwdXRFbWl0dGVyUmVmPFQ+O1xuICBwdWJsaWMgb3V0cHV0PFQsIEsgZXh0ZW5kcyBLZXlzTWF0Y2hpbmdPdXRwdXQ8ST4+KG91dHB1dDogSyk6IElbS10gfCBPYnNlcnZhYmxlPFQ+IHwgT3V0cHV0RW1pdHRlclJlZjxUPiB7XG4gICAgY29uc3QgZXZlbnRFbWl0dGVyID0gdGhpcy5pbnN0YW5jZVtvdXRwdXRdO1xuXG4gICAgaWYgKCEoZXZlbnRFbWl0dGVyIGluc3RhbmNlb2YgT2JzZXJ2YWJsZSkgJiYgIShldmVudEVtaXR0ZXIgaW5zdGFuY2VvZiBPdXRwdXRFbWl0dGVyUmVmKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGAke1N0cmluZyhvdXRwdXQpfSBpcyBub3QgYW4gQE91dHB1dCBvciBhbiBvdXRwdXQgZnVuY3Rpb25gKTtcbiAgICB9XG5cbiAgICByZXR1cm4gZXZlbnRFbWl0dGVyO1xuICB9XG5cbiAgcHVibGljIHRpY2sobWlsbGlzPzogbnVtYmVyKTogdm9pZCB7XG4gICAgdGljayhtaWxsaXMpO1xuICAgIHRoaXMuZGV0ZWN0Q2hhbmdlcygpO1xuICB9XG5cbiAgcHVibGljIGNsaWNrKHNlbGVjdG9yOiBTcGVjdGF0b3JFbGVtZW50ID0gdGhpcy5lbGVtZW50KTogdm9pZCB7XG4gICAgY29uc3QgZWxlbWVudCA9IHRoaXMuZ2V0TmF0aXZlRWxlbWVudChzZWxlY3Rvcik7XG5cbiAgICBpZiAoIShlbGVtZW50IGluc3RhbmNlb2YgSFRNTEVsZW1lbnQpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYENhbm5vdCBjbGljazogJHtzZWxlY3Rvcn0gaXMgbm90IGEgSFRNTEVsZW1lbnRgKTtcbiAgICB9XG5cbiAgICBlbGVtZW50LmNsaWNrKCk7XG4gICAgdGhpcy5kZXRlY3RDaGFuZ2VzKCk7XG4gIH1cblxuICBwdWJsaWMgYmx1cihzZWxlY3RvcjogU3BlY3RhdG9yRWxlbWVudCA9IHRoaXMuZWxlbWVudCk6IHZvaWQge1xuICAgIGNvbnN0IGVsZW1lbnQgPSB0aGlzLmdldE5hdGl2ZUVsZW1lbnQoc2VsZWN0b3IpO1xuXG4gICAgaWYgKCEoZWxlbWVudCBpbnN0YW5jZW9mIEhUTUxFbGVtZW50KSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBDYW5ub3QgYmx1cjogJHtzZWxlY3Rvcn0gaXMgbm90IGEgSFRNTEVsZW1lbnRgKTtcbiAgICB9XG5cbiAgICBwYXRjaEVsZW1lbnRGb2N1cyhlbGVtZW50KTtcbiAgICBlbGVtZW50LmJsdXIoKTtcbiAgICB0aGlzLmRldGVjdENoYW5nZXMoKTtcbiAgfVxuXG4gIHB1YmxpYyBmb2N1cyhzZWxlY3RvcjogU3BlY3RhdG9yRWxlbWVudCA9IHRoaXMuZWxlbWVudCk6IHZvaWQge1xuICAgIGNvbnN0IGVsZW1lbnQgPSB0aGlzLmdldE5hdGl2ZUVsZW1lbnQoc2VsZWN0b3IpO1xuXG4gICAgaWYgKCEoZWxlbWVudCBpbnN0YW5jZW9mIEhUTUxFbGVtZW50KSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBDYW5ub3QgZm9jdXM6ICR7c2VsZWN0b3J9IGlzIG5vdCBhIEhUTUxFbGVtZW50YCk7XG4gICAgfVxuXG4gICAgcGF0Y2hFbGVtZW50Rm9jdXMoZWxlbWVudCk7XG4gICAgZWxlbWVudC5mb2N1cygpO1xuICAgIHRoaXMuZGV0ZWN0Q2hhbmdlcygpO1xuICB9XG5cbiAgcHVibGljIGRpc3BhdGNoTW91c2VFdmVudChcbiAgICBzZWxlY3RvcjogU3BlY3RhdG9yRWxlbWVudCA9IHRoaXMuZWxlbWVudCxcbiAgICB0eXBlOiBzdHJpbmcsXG4gICAgeDogbnVtYmVyID0gMCxcbiAgICB5OiBudW1iZXIgPSAwLFxuICAgIGV2ZW50OiBNb3VzZUV2ZW50ID0gY3JlYXRlTW91c2VFdmVudCh0eXBlLCB4LCB5KSxcbiAgKTogTW91c2VFdmVudCB7XG4gICAgY29uc3QgZWxlbWVudCA9IHRoaXMuZ2V0TmF0aXZlRWxlbWVudChzZWxlY3Rvcik7XG5cbiAgICBpZiAoIShlbGVtZW50IGluc3RhbmNlb2YgTm9kZSkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgQ2Fubm90IGRpc3BhdGNoIG1vdXNlIGV2ZW50OiAke3NlbGVjdG9yfSBpcyBub3QgYSBub2RlYCk7XG4gICAgfVxuXG4gICAgY29uc3QgZGlzcGF0Y2hlZEV2ZW50ID0gZGlzcGF0Y2hNb3VzZUV2ZW50KGVsZW1lbnQsIHR5cGUsIHgsIHksIGV2ZW50KTtcbiAgICB0aGlzLmRldGVjdENoYW5nZXMoKTtcblxuICAgIHJldHVybiBkaXNwYXRjaGVkRXZlbnQ7XG4gIH1cblxuICBwdWJsaWMgZGlzcGF0Y2hLZXlib2FyZEV2ZW50KHNlbGVjdG9yOiBTcGVjdGF0b3JFbGVtZW50LCB0eXBlOiBzdHJpbmcsIGtleUNvZGU6IG51bWJlciwgdGFyZ2V0PzogRWxlbWVudCk6IEtleWJvYXJkRXZlbnQ7XG4gIHB1YmxpYyBkaXNwYXRjaEtleWJvYXJkRXZlbnQoc2VsZWN0b3I6IFNwZWN0YXRvckVsZW1lbnQsIHR5cGU6IHN0cmluZywga2V5OiBzdHJpbmcsIHRhcmdldD86IEVsZW1lbnQpOiBLZXlib2FyZEV2ZW50O1xuICBwdWJsaWMgZGlzcGF0Y2hLZXlib2FyZEV2ZW50KHNlbGVjdG9yOiBTcGVjdGF0b3JFbGVtZW50LCB0eXBlOiBzdHJpbmcsIGtleUFuZENvZGU6IEtleWJvYXJkRXZlbnRPcHRpb25zLCB0YXJnZXQ/OiBFbGVtZW50KTogS2V5Ym9hcmRFdmVudDtcbiAgcHVibGljIGRpc3BhdGNoS2V5Ym9hcmRFdmVudChcbiAgICBzZWxlY3RvcjogU3BlY3RhdG9yRWxlbWVudCA9IHRoaXMuZWxlbWVudCxcbiAgICB0eXBlOiBzdHJpbmcsXG4gICAga2V5T3JLZXlDb2RlOiBzdHJpbmcgfCBudW1iZXIgfCBLZXlib2FyZEV2ZW50T3B0aW9ucyxcbiAgICB0YXJnZXQ/OiBFbGVtZW50LFxuICApOiBLZXlib2FyZEV2ZW50IHtcbiAgICBjb25zdCBlbGVtZW50ID0gdGhpcy5nZXROYXRpdmVFbGVtZW50KHNlbGVjdG9yKTtcblxuICAgIGlmICghKGVsZW1lbnQgaW5zdGFuY2VvZiBOb2RlKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBDYW5ub3QgZGlzcGF0Y2gga2V5Ym9hcmQgZXZlbnQ6ICR7c2VsZWN0b3J9IGlzIG5vdCBhIG5vZGVgKTtcbiAgICB9XG5cbiAgICBjb25zdCBldmVudCA9IGRpc3BhdGNoS2V5Ym9hcmRFdmVudChlbGVtZW50LCB0eXBlLCBrZXlPcktleUNvZGUsIHRhcmdldCk7XG5cbiAgICB0aGlzLmRldGVjdENoYW5nZXMoKTtcblxuICAgIHJldHVybiBldmVudDtcbiAgfVxuXG4gIHB1YmxpYyBkaXNwYXRjaEZha2VFdmVudChzZWxlY3RvcjogU3BlY3RhdG9yRWxlbWVudCA9IHRoaXMuZWxlbWVudCwgdHlwZTogc3RyaW5nLCBjYW5CdWJibGU/OiBib29sZWFuKTogRXZlbnQge1xuICAgIGNvbnN0IGV2ZW50ID0gZGlzcGF0Y2hGYWtlRXZlbnQodGhpcy5nZXROYXRpdmVFbGVtZW50KHNlbGVjdG9yKSwgdHlwZSwgY2FuQnViYmxlKTtcbiAgICB0aGlzLmRldGVjdENoYW5nZXMoKTtcblxuICAgIHJldHVybiBldmVudDtcbiAgfVxuXG4gIHB1YmxpYyB0cmlnZ2VyRXZlbnRIYW5kbGVyPEMgPSBhbnksIEsgZXh0ZW5kcyBLZXlzTWF0Y2hpbmc8QywgRXZlbnRFbWl0dGVyPGFueT4gfCBPdXRwdXRFbWl0dGVyUmVmPGFueT4+ID0gYW55PihcbiAgICBkaXJlY3RpdmVPclNlbGVjdG9yOiBUeXBlPEM+IHwgc3RyaW5nIHwgRGVidWdFbGVtZW50LFxuICAgIGV2ZW50TmFtZTogSyxcbiAgICBldmVudE9iajogT3V0cHV0VHlwZTxDW0tdPixcbiAgICBvcHRpb25zPzogeyByb290OiBib29sZWFuIH0sXG4gICkge1xuICAgIGNvbnN0IHRyaWdnZXJEZWJ1Z0VsZW1lbnQgPSB0aGlzLmdldERlYnVnRWxlbWVudChkaXJlY3RpdmVPclNlbGVjdG9yLCBvcHRpb25zKTtcbiAgICBpZiAoIXRyaWdnZXJEZWJ1Z0VsZW1lbnQpIHtcbiAgICAgIC8qIGVzbGludC1kaXNhYmxlIG5vLWNvbnNvbGUgKi9cbiAgICAgIGNvbnNvbGUuZXJyb3IoYCR7ZGlyZWN0aXZlT3JTZWxlY3Rvcn0gZG9lcyBub3QgZXhpc3RzYCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdHJpZ2dlckRlYnVnRWxlbWVudC50cmlnZ2VyRXZlbnRIYW5kbGVyKGV2ZW50TmFtZSBhcyBzdHJpbmcsIGV2ZW50T2JqKTtcblxuICAgIHRoaXMuZGV0ZWN0Q2hhbmdlcygpO1xuICB9XG5cbiAgcHVibGljIGdldCBrZXlib2FyZCgpIHtcbiAgICByZXR1cm4ge1xuICAgICAgcHJlc3NLZXk6IChrZXk6IHN0cmluZywgc2VsZWN0b3I6IFNwZWN0YXRvckVsZW1lbnQgPSB0aGlzLmVsZW1lbnQsIGV2ZW50ID0gS0VZX1VQKSA9PiB7XG4gICAgICAgIHRoaXMuZGlzcGF0Y2hLZXlib2FyZEV2ZW50KHNlbGVjdG9yLCBldmVudCwga2V5KTtcbiAgICAgIH0sXG4gICAgICBwcmVzc0VzY2FwZTogKHNlbGVjdG9yOiBTcGVjdGF0b3JFbGVtZW50ID0gdGhpcy5lbGVtZW50LCBldmVudCA9IEtFWV9VUCkgPT4ge1xuICAgICAgICB0aGlzLmRpc3BhdGNoS2V5Ym9hcmRFdmVudChzZWxlY3RvciwgZXZlbnQsIHsga2V5OiAnRXNjYXBlJywga2V5Q29kZTogMjcgfSk7XG4gICAgICB9LFxuICAgICAgcHJlc3NFbnRlcjogKHNlbGVjdG9yOiBTcGVjdGF0b3JFbGVtZW50ID0gdGhpcy5lbGVtZW50LCBldmVudCA9IEtFWV9VUCkgPT4ge1xuICAgICAgICB0aGlzLmRpc3BhdGNoS2V5Ym9hcmRFdmVudChzZWxlY3RvciwgZXZlbnQsIHsga2V5OiAnRW50ZXInLCBrZXlDb2RlOiAxMyB9KTtcbiAgICAgIH0sXG4gICAgICBwcmVzc1RhYjogKHNlbGVjdG9yOiBTcGVjdGF0b3JFbGVtZW50ID0gdGhpcy5lbGVtZW50LCBldmVudCA9IEtFWV9VUCkgPT4ge1xuICAgICAgICB0aGlzLmRpc3BhdGNoS2V5Ym9hcmRFdmVudChzZWxlY3RvciwgZXZlbnQsIHsga2V5OiAnVGFiJywga2V5Q29kZTogOSB9KTtcbiAgICAgIH0sXG4gICAgICBwcmVzc0JhY2tzcGFjZTogKHNlbGVjdG9yOiBTcGVjdGF0b3JFbGVtZW50ID0gdGhpcy5lbGVtZW50LCBldmVudCA9IEtFWV9VUCkgPT4ge1xuICAgICAgICB0aGlzLmRpc3BhdGNoS2V5Ym9hcmRFdmVudChzZWxlY3RvciwgZXZlbnQsIHsga2V5OiAnQmFja3NwYWNlJywga2V5Q29kZTogOCB9KTtcbiAgICAgIH0sXG4gICAgfTtcbiAgfVxuXG4gIHB1YmxpYyBnZXQgbW91c2UoKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIGNvbnRleHRtZW51OiAoc2VsZWN0b3I6IFNwZWN0YXRvckVsZW1lbnQgPSB0aGlzLmVsZW1lbnQpID0+IHtcbiAgICAgICAgdGhpcy5kaXNwYXRjaE1vdXNlRXZlbnQoc2VsZWN0b3IsICdjb250ZXh0bWVudScpO1xuICAgICAgfSxcbiAgICAgIGRibGNsaWNrOiAoc2VsZWN0b3I6IFNwZWN0YXRvckVsZW1lbnQgPSB0aGlzLmVsZW1lbnQpID0+IHtcbiAgICAgICAgdGhpcy5kaXNwYXRjaE1vdXNlRXZlbnQoc2VsZWN0b3IsICdkYmxjbGljaycpO1xuICAgICAgfSxcbiAgICB9O1xuICB9XG5cbiAgcHVibGljIGRpc3BhdGNoVG91Y2hFdmVudChzZWxlY3RvcjogU3BlY3RhdG9yRWxlbWVudCA9IHRoaXMuZWxlbWVudCwgdHlwZTogc3RyaW5nLCB4OiBudW1iZXIgPSAwLCB5OiBudW1iZXIgPSAwKTogdm9pZCB7XG4gICAgZGlzcGF0Y2hUb3VjaEV2ZW50KHRoaXMuZ2V0TmF0aXZlRWxlbWVudChzZWxlY3RvciksIHR5cGUsIHgsIHkpO1xuICAgIHRoaXMuZGV0ZWN0Q2hhbmdlcygpO1xuICB9XG5cbiAgcHVibGljIHR5cGVJbkVsZW1lbnQodmFsdWU6IHN0cmluZywgc2VsZWN0b3I6IFNwZWN0YXRvckVsZW1lbnQgPSB0aGlzLmVsZW1lbnQpOiB2b2lkIHtcbiAgICB0eXBlSW5FbGVtZW50KHZhbHVlLCB0aGlzLmdldE5hdGl2ZUVsZW1lbnQoc2VsZWN0b3IpKTtcbiAgICB0aGlzLmRldGVjdENoYW5nZXMoKTtcbiAgfVxuXG4gIHB1YmxpYyBzZWxlY3RPcHRpb24oXG4gICAgc2VsZWN0b3I6IFNwZWN0YXRvckVsZW1lbnQgPSB0aGlzLmVsZW1lbnQsXG4gICAgb3B0aW9uczogc3RyaW5nIHwgc3RyaW5nW10gfCBIVE1MT3B0aW9uRWxlbWVudCB8IEhUTUxPcHRpb25FbGVtZW50W10sXG4gICAgY29uZmlnOiB7IGVtaXRFdmVudHM6IGJvb2xlYW4gfSA9IHsgZW1pdEV2ZW50czogdHJ1ZSB9LFxuICApOiB2b2lkIHtcbiAgICBpZiAoIXNlbGVjdG9yKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYENhbm5vdCBmaW5kIHNlbGVjdDogJHtzZWxlY3Rvcn1gKTtcbiAgICB9XG4gICAgc2VsZWN0T3B0aW9uKG9wdGlvbnMsIHRoaXMuZ2V0TmF0aXZlRWxlbWVudChzZWxlY3RvciksIGNvbmZpZyk7XG4gICAgdGhpcy5kZXRlY3RDaGFuZ2VzKCk7XG4gIH1cblxuICBwcml2YXRlIGdldE5hdGl2ZUVsZW1lbnQoc2VsZWN0b3I6IFNwZWN0YXRvckVsZW1lbnQpOiBIVE1MRWxlbWVudCB8IFdpbmRvdyB8IERvY3VtZW50IHtcbiAgICBsZXQgZWxlbWVudDtcblxuICAgIC8vIFN1cHBvcnQgZ2xvYmFsIG9iamVjdHMgd2luZG93IGFuZCBkb2N1bWVudFxuICAgIGlmIChzZWxlY3RvciA9PT0gd2luZG93IHx8IHNlbGVjdG9yID09PSBkb2N1bWVudCkge1xuICAgICAgcmV0dXJuIHNlbGVjdG9yIGFzIGFueTtcbiAgICB9XG5cbiAgICBpZiAoaXNTdHJpbmcoc2VsZWN0b3IpKSB7XG4gICAgICBjb25zdCBleGlzdHMgPSB0aGlzLmRlYnVnRWxlbWVudC5xdWVyeShCeS5jc3Moc2VsZWN0b3IpKTtcbiAgICAgIGlmIChleGlzdHMpIHtcbiAgICAgICAgZWxlbWVudCA9IGV4aXN0cy5uYXRpdmVFbGVtZW50O1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLyogZXNsaW50LWRpc2FibGUgbm8tY29uc29sZSAqL1xuICAgICAgICBjb25zb2xlLmVycm9yKGAke3NlbGVjdG9yfSBkb2VzIG5vdCBleGlzdHNgKTtcbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKHNlbGVjdG9yIGluc3RhbmNlb2YgRE9NU2VsZWN0b3IpIHtcbiAgICAgIGVsZW1lbnQgPSBzZWxlY3Rvci5leGVjdXRlKGRvY3VtZW50IGFzIGFueSlbMF0gfHwgbnVsbDtcbiAgICB9IGVsc2Uge1xuICAgICAgaWYgKHNlbGVjdG9yIGluc3RhbmNlb2YgRGVidWdFbGVtZW50IHx8IHNlbGVjdG9yIGluc3RhbmNlb2YgRWxlbWVudFJlZikge1xuICAgICAgICBlbGVtZW50ID0gc2VsZWN0b3IubmF0aXZlRWxlbWVudDtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGVsZW1lbnQgPSBzZWxlY3RvcjtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gZWxlbWVudDtcbiAgfVxuXG4gIHByaXZhdGUgZ2V0RGVidWdFbGVtZW50KFxuICAgIGRpcmVjdGl2ZU9yU2VsZWN0b3I6IHN0cmluZyB8IERlYnVnRWxlbWVudCB8IFR5cGU8dW5rbm93bj4sXG4gICAgb3B0aW9ucz86IHsgcm9vdDogYm9vbGVhbiB9LFxuICApOiBEZWJ1Z0VsZW1lbnQgfCB1bmRlZmluZWQge1xuICAgIGNvbnN0IGRlYnVnRWxlbWVudCA9IG9wdGlvbnM/LnJvb3QgPyB0aGlzLmdldFJvb3REZWJ1Z0VsZW1lbnQoKSA6IHRoaXMuZGVidWdFbGVtZW50O1xuXG4gICAgaWYgKGlzU3RyaW5nKGRpcmVjdGl2ZU9yU2VsZWN0b3IpKSB7XG4gICAgICByZXR1cm4gZGVidWdFbGVtZW50LnF1ZXJ5KEJ5LmNzcyhkaXJlY3RpdmVPclNlbGVjdG9yKSk7XG4gICAgfSBlbHNlIGlmIChkaXJlY3RpdmVPclNlbGVjdG9yIGluc3RhbmNlb2YgRGVidWdFbGVtZW50KSB7XG4gICAgICByZXR1cm4gZGlyZWN0aXZlT3JTZWxlY3RvcjtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIGRlYnVnRWxlbWVudC5xdWVyeShCeS5kaXJlY3RpdmUoZGlyZWN0aXZlT3JTZWxlY3RvcikpO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgZ2V0Um9vdERlYnVnRWxlbWVudCgpOiBEZWJ1Z0VsZW1lbnQge1xuICAgIGxldCBlbGVtZW50OiBEZWJ1Z0VsZW1lbnQgfCBudWxsIHwgdW5kZWZpbmVkID0gdGhpcy5kZWJ1Z0VsZW1lbnQ7XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIGJvdW5kZWQgbG9vcCBjYWxsIGlzIHJlcXVpcmVkIHRvIGFjY2VzcyB0aGUgZGVidWcgZWxlbWVudCBmb3JcbiAgICAgKiByb290IGRvbSBlbGVtZW50XG4gICAgICovXG4gICAgd2hpbGUgKHRydWUpIHtcbiAgICAgIGlmICghZWxlbWVudCkge1xuICAgICAgICB0aHJvdyBFcnJvcignVW5hYmxlIHRvIGZpbmQgcm9vdCBlbGVtZW50Jyk7XG4gICAgICB9XG5cbiAgICAgIGlmICghZWxlbWVudC5wYXJlbnQpIHtcbiAgICAgICAgLy8gRm91bmQgdGhlIHJvb3QgZWxlbWVudFxuICAgICAgICByZXR1cm4gZWxlbWVudDtcbiAgICAgIH1cblxuICAgICAgZWxlbWVudCA9IGVsZW1lbnQucGFyZW50O1xuICAgIH1cbiAgfVxufVxuIl19