UNPKG

@angular/cdk

Version:

Angular Material Component Development Kit

199 lines 34.1 kB
/** * @license * Copyright Google LLC All Rights Reserved. * * Use of this source code is governed by an MIT-style license that can be * found in the LICENSE file at https://angular.io/license */ import { _getTextWithExcludedElements, } from '@angular/cdk/testing'; import * as webdriver from 'selenium-webdriver'; import { getSeleniumWebDriverModifierKeys, seleniumWebDriverKeyMap } from './selenium-webdriver-keys'; /** A `TestElement` implementation for WebDriver. */ export class SeleniumWebDriverElement { constructor(element, _stabilize) { this.element = element; this._stabilize = _stabilize; } /** Blur the element. */ async blur() { await this._executeScript((element) => element.blur(), this.element()); await this._stabilize(); } /** Clear the element's input (for input and textarea elements only). */ async clear() { await this.element().clear(); await this._stabilize(); } async click(...args) { await this._dispatchClickEventSequence(args, webdriver.Button.LEFT); await this._stabilize(); } async rightClick(...args) { await this._dispatchClickEventSequence(args, webdriver.Button.RIGHT); await this._stabilize(); } /** Focus the element. */ async focus() { await this._executeScript((element) => element.focus(), this.element()); await this._stabilize(); } /** Get the computed value of the given CSS property for the element. */ async getCssValue(property) { await this._stabilize(); return this.element().getCssValue(property); } /** Hovers the mouse over the element. */ async hover() { await this._actions().mouseMove(this.element()).perform(); await this._stabilize(); } /** Moves the mouse away from the element. */ async mouseAway() { await this._actions().mouseMove(this.element(), { x: -1, y: -1 }).perform(); await this._stabilize(); } async sendKeys(...modifiersAndKeys) { const first = modifiersAndKeys[0]; let modifiers; let rest; if (typeof first !== 'string' && typeof first !== 'number') { modifiers = first; rest = modifiersAndKeys.slice(1); } else { modifiers = {}; rest = modifiersAndKeys; } const modifierKeys = getSeleniumWebDriverModifierKeys(modifiers); const keys = rest .map(k => (typeof k === 'string' ? k.split('') : [seleniumWebDriverKeyMap[k]])) .reduce((arr, k) => arr.concat(k), []) // webdriver.Key.chord doesn't work well with geckodriver (mozilla/geckodriver#1502), // so avoid it if no modifier keys are required. .map(k => (modifierKeys.length > 0 ? webdriver.Key.chord(...modifierKeys, k) : k)); await this.element().sendKeys(...keys); await this._stabilize(); } /** * Gets the text from the element. * @param options Options that affect what text is included. */ async text(options) { await this._stabilize(); if (options?.exclude) { return this._executeScript(_getTextWithExcludedElements, this.element(), options.exclude); } // We don't go through the WebDriver `getText`, because it excludes text from hidden elements. return this._executeScript((element) => (element.textContent || '').trim(), this.element()); } /** Gets the value for the given attribute from the element. */ async getAttribute(name) { await this._stabilize(); return this._executeScript((element, attribute) => element.getAttribute(attribute), this.element(), name); } /** Checks whether the element has the given class. */ async hasClass(name) { await this._stabilize(); const classes = (await this.getAttribute('class')) || ''; return new Set(classes.split(/\s+/).filter(c => c)).has(name); } /** Gets the dimensions of the element. */ async getDimensions() { await this._stabilize(); const { width, height } = await this.element().getSize(); const { x: left, y: top } = await this.element().getLocation(); return { width, height, left, top }; } /** Gets the value of a property of an element. */ async getProperty(name) { await this._stabilize(); return this._executeScript((element, property) => element[property], this.element(), name); } /** Sets the value of a property of an input. */ async setInputValue(newValue) { await this._executeScript((element, value) => (element.value = value), this.element(), newValue); await this._stabilize(); } /** Selects the options at the specified indexes inside of a native `select` element. */ async selectOptions(...optionIndexes) { await this._stabilize(); const options = await this.element().findElements(webdriver.By.css('option')); const indexes = new Set(optionIndexes); // Convert to a set to remove duplicates. if (options.length && indexes.size) { // Reset the value so all the selected states are cleared. We can // reuse the input-specific method since the logic is the same. await this.setInputValue(''); for (let i = 0; i < options.length; i++) { if (indexes.has(i)) { // We have to hold the control key while clicking on options so that multiple can be // selected in multi-selection mode. The key doesn't do anything for single selection. await this._actions().keyDown(webdriver.Key.CONTROL).perform(); await options[i].click(); await this._actions().keyUp(webdriver.Key.CONTROL).perform(); } } await this._stabilize(); } } /** Checks whether this element matches the given selector. */ async matchesSelector(selector) { await this._stabilize(); return this._executeScript((element, s) => (Element.prototype.matches || Element.prototype.msMatchesSelector).call(element, s), this.element(), selector); } /** Checks whether the element is focused. */ async isFocused() { await this._stabilize(); return webdriver.WebElement.equals(this.element(), this.element().getDriver().switchTo().activeElement()); } /** * Dispatches an event with a particular name. * @param name Name of the event to be dispatched. */ async dispatchEvent(name, data) { await this._executeScript(dispatchEvent, name, this.element(), data); await this._stabilize(); } /** Gets the webdriver action sequence. */ _actions() { return this.element().getDriver().actions(); } /** Executes a function in the browser. */ async _executeScript(script, ...var_args) { return this.element() .getDriver() .executeScript(script, ...var_args); } /** Dispatches all the events that are part of a click event sequence. */ async _dispatchClickEventSequence(args, button) { let modifiers = {}; if (args.length && typeof args[args.length - 1] === 'object') { modifiers = args.pop(); } const modifierKeys = getSeleniumWebDriverModifierKeys(modifiers); // Omitting the offset argument to mouseMove results in clicking the center. // This is the default behavior we want, so we use an empty array of offsetArgs if // no args remain after popping the modifiers from the args passed to this function. const offsetArgs = (args.length === 2 ? [{ x: args[0], y: args[1] }] : []); let actions = this._actions().mouseMove(this.element(), ...offsetArgs); for (const modifierKey of modifierKeys) { actions = actions.keyDown(modifierKey); } actions = actions.click(button); for (const modifierKey of modifierKeys) { actions = actions.keyUp(modifierKey); } await actions.perform(); } } /** * Dispatches an event with a particular name and data to an element. Note that this needs to be a * pure function, because it gets stringified by WebDriver and is executed inside the browser. */ function dispatchEvent(name, element, data) { const event = document.createEvent('Event'); event.initEvent(name); // tslint:disable-next-line:ban Have to use `Object.assign` to preserve the original object. Object.assign(event, data || {}); element.dispatchEvent(event); } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VsZW5pdW0td2ViLWRyaXZlci1lbGVtZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vc3JjL2Nkay90ZXN0aW5nL3NlbGVuaXVtLXdlYmRyaXZlci9zZWxlbml1bS13ZWItZHJpdmVyLWVsZW1lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7OztHQU1HO0FBRUgsT0FBTyxFQUNMLDRCQUE0QixHQU83QixNQUFNLHNCQUFzQixDQUFDO0FBQzlCLE9BQU8sS0FBSyxTQUFTLE1BQU0sb0JBQW9CLENBQUM7QUFDaEQsT0FBTyxFQUFDLGdDQUFnQyxFQUFFLHVCQUF1QixFQUFDLE1BQU0sMkJBQTJCLENBQUM7QUFFcEcsb0RBQW9EO0FBQ3BELE1BQU0sT0FBTyx3QkFBd0I7SUFDbkMsWUFDVyxPQUFtQyxFQUNwQyxVQUErQjtRQUQ5QixZQUFPLEdBQVAsT0FBTyxDQUE0QjtRQUNwQyxlQUFVLEdBQVYsVUFBVSxDQUFxQjtJQUN0QyxDQUFDO0lBRUosd0JBQXdCO0lBQ3hCLEtBQUssQ0FBQyxJQUFJO1FBQ1IsTUFBTSxJQUFJLENBQUMsY0FBYyxDQUFDLENBQUMsT0FBb0IsRUFBRSxFQUFFLENBQUMsT0FBTyxDQUFDLElBQUksRUFBRSxFQUFFLElBQUksQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFDO1FBQ3BGLE1BQU0sSUFBSSxDQUFDLFVBQVUsRUFBRSxDQUFDO0lBQzFCLENBQUM7SUFFRCx3RUFBd0U7SUFDeEUsS0FBSyxDQUFDLEtBQUs7UUFDVCxNQUFNLElBQUksQ0FBQyxPQUFPLEVBQUUsQ0FBQyxLQUFLLEVBQUUsQ0FBQztRQUM3QixNQUFNLElBQUksQ0FBQyxVQUFVLEVBQUUsQ0FBQztJQUMxQixDQUFDO0lBaUJELEtBQUssQ0FBQyxLQUFLLENBQ1QsR0FBRyxJQUFtRjtRQUV0RixNQUFNLElBQUksQ0FBQywyQkFBMkIsQ0FBQyxJQUFJLEVBQUUsU0FBUyxDQUFDLE1BQU0sQ0FBQyxJ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Q0FBQyxDQUFDO1NBQ3RDO1FBRUQsTUFBTSxPQUFPLENBQUMsT0FBTyxFQUFFLENBQUM7SUFDMUIsQ0FBQztDQUNGO0FBRUQ7OztHQUdHO0FBQ0gsU0FBUyxhQUFhLENBQUMsSUFBWSxFQUFFLE9BQWdCLEVBQUUsSUFBZ0M7SUFDckYsTUFBTSxLQUFLLEdBQUcsUUFBUSxDQUFDLFdBQVcsQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUM1QyxLQUFLLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ3RCLDRGQUE0RjtJQUM1RixNQUFNLENBQUMsTUFBTSxDQUFDLEtBQUssRUFBRSxJQUFJLElBQUksRUFBRSxDQUFDLENBQUM7SUFDakMsT0FBTyxDQUFDLGFBQWEsQ0FBQyxLQUFLLENBQUMsQ0FBQztBQUMvQixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IEdvb2dsZSBMTEMgQWxsIFJpZ2h0cyBSZXNlcnZlZC5cbiAqXG4gKiBVc2Ugb2YgdGhpcyBzb3VyY2UgY29kZSBpcyBnb3Zlcm5lZCBieSBhbiBNSVQtc3R5bGUgbGljZW5zZSB0aGF0IGNhbiBiZVxuICogZm91bmQgaW4gdGhlIExJQ0VOU0UgZmlsZSBhdCBodHRwczovL2FuZ3VsYXIuaW8vbGljZW5zZVxuICovXG5cbmltcG9ydCB7XG4gIF9nZXRUZXh0V2l0aEV4Y2x1ZGVkRWxlbWVudHMsXG4gIEVsZW1lbnREaW1lbnNpb25zLFxuICBFdmVudERhdGEsXG4gIE1vZGlmaWVyS2V5cyxcbiAgVGVzdEVsZW1lbnQsXG4gIFRlc3RLZXksXG4gIFRleHRPcHRpb25zLFxufSBmcm9tICdAYW5ndWxhci9jZGsvdGVzdGluZyc7XG5pbXBvcnQgKiBhcyB3ZWJkcml2ZXIgZnJvbSAnc2VsZW5pdW0td2ViZHJpdmVyJztcbmltcG9ydCB7Z2V0U2VsZW5pdW1XZWJEcml2ZXJNb2RpZmllcktleXMsIHNlbGVuaXVtV2ViRHJpdmVyS2V5TWFwfSBmcm9tICcuL3NlbGVuaXVtLXdlYmRyaXZlci1rZXlzJztcblxuLyoqIEEgYFRlc3RFbGVtZW50YCBpbXBsZW1lbnRhdGlvbiBmb3IgV2ViRHJpdmVyLiAqL1xuZXhwb3J0IGNsYXNzIFNlbGVuaXVtV2ViRHJpdmVyRWxlbWVudCBpbXBsZW1lbnRzIFRlc3RFbGVtZW50IHtcbiAgY29uc3RydWN0b3IoXG4gICAgcmVhZG9ubHkgZWxlbWVudDogKCkgPT4gd2ViZHJpdmVyLldlYkVsZW1lbnQsXG4gICAgcHJpdmF0ZSBfc3RhYmlsaXplOiAoKSA9PiBQcm9taXNlPHZvaWQ+LFxuICApIHt9XG5cbiAgLyoqIEJsdXIgdGhlIGVsZW1lbnQuICovXG4gIGFzeW5jIGJsdXIoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgYXdhaXQgdGhpcy5fZXhlY3V0ZVNjcmlwdCgoZWxlbWVudDogSFRNTEVsZW1lbnQpID0+IGVsZW1lbnQuYmx1cigpLCB0aGlzLmVsZW1lbnQoKSk7XG4gICAgYXdhaXQgdGhpcy5fc3RhYmlsaXplKCk7XG4gIH1cblxuICAvKiogQ2xlYXIgdGhlIGVsZW1lbnQncyBpbnB1dCAoZm9yIGlucHV0IGFuZCB0ZXh0YXJlYSBlbGVtZW50cyBvbmx5KS4gKi9cbiAgYXN5bmMgY2xlYXIoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgYXdhaXQgdGhpcy5lbGVtZW50KCkuY2xlYXIoKTtcbiAgICBhd2FpdCB0aGlzLl9zdGFiaWxpemUoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDbGljayB0aGUgZWxlbWVudCBhdCB0aGUgZGVmYXVsdCBsb2NhdGlvbiBmb3IgdGhlIGN1cnJlbnQgZW52aXJvbm1lbnQuIElmIHlvdSBuZWVkIHRvIGd1YXJhbnRlZVxuICAgKiB0aGUgZWxlbWVudCBpcyBjbGlja2VkIGF0IGEgc3BlY2lmaWMgbG9jYXRpb24sIGNvbnNpZGVyIHVzaW5nIGBjbGljaygnY2VudGVyJylgIG9yXG4gICAqIGBjbGljayh4LCB5KWAgaW5zdGVhZC5cbiAgICovXG4gIGNsaWNrKG1vZGlmaWVycz86IE1vZGlmaWVyS2V5cyk6IFByb21pc2U8dm9pZD47XG4gIC8qKiBDbGljayB0aGUgZWxlbWVudCBhdCB0aGUgZWxlbWVudCdzIGNlbnRlci4gKi9cbiAgY2xpY2sobG9jYXRpb246ICdjZW50ZXInLCBtb2RpZmllcnM/OiBNb2RpZmllcktleXMpOiBQcm9taXNlPHZvaWQ+O1xuICAvKipcbiAgICogQ2xpY2sgdGhlIGVsZW1lbnQgYXQgdGhlIHNwZWNpZmllZCBjb29yZGluYXRlcyByZWxhdGl2ZSB0byB0aGUgdG9wLWxlZnQgb2YgdGhlIGVsZW1lbnQuXG4gICAqIEBwYXJhbSByZWxhdGl2ZVggQ29vcmRpbmF0ZSB3aXRoaW4gdGhlIGVsZW1lbnQsIGFsb25nIHRoZSBYLWF4aXMgYXQgd2hpY2ggdG8gY2xpY2suXG4gICAqIEBwYXJhbSByZWxhdGl2ZVkgQ29vcmRpbmF0ZSB3aXRoaW4gdGhlIGVsZW1lbnQsIGFsb25nIHRoZSBZLWF4aXMgYXQgd2hpY2ggdG8gY2xpY2suXG4gICAqIEBwYXJhbSBtb2RpZmllcnMgTW9kaWZpZXIga2V5cyBoZWxkIHdoaWxlIGNsaWNraW5nXG4gICAqL1xuICBjbGljayhyZWxhdGl2ZVg6IG51bWJlciwgcmVsYXRpdmVZOiBudW1iZXIsIG1vZGlmaWVycz86IE1vZGlmaWVyS2V5cyk6IFByb21pc2U8dm9pZD47XG4gIGFzeW5jIGNsaWNrKFxuICAgIC4uLmFyZ3M6IFtNb2RpZmllcktleXM/XSB8IFsnY2VudGVyJywgTW9kaWZpZXJLZXlzP10gfCBbbnVtYmVyLCBudW1iZXIsIE1vZGlmaWVyS2V5cz9dXG4gICk6IFByb21pc2U8dm9pZD4ge1xuICAgIGF3YWl0IHRoaXMuX2Rpc3BhdGNoQ2xpY2tFdmVudFNlcXVlbmNlKGFyZ3MsIHdlYmRyaXZlci5CdXR0b24uTEVGVCk7XG4gICAgYXdhaXQgdGhpcy5fc3RhYmlsaXplKCk7XG4gIH1cblxuICAvKipcbiAgICogUmlnaHQgY2xpY2tzIG9uIHRoZSBlbGVtZW50IGF0IHRoZSBzcGVjaWZpZWQgY29vcmRpbmF0ZXMgcmVsYXRpdmUgdG8gdGhlIHRvcC1sZWZ0IG9mIGl0LlxuICAgKiBAcGFyYW0gcmVsYXRpdmVYIENvb3JkaW5hdGUgd2l0aGluIHRoZSBlbGVtZW50LCBhbG9uZyB0aGUgWC1heGlzIGF0IHdoaWNoIHRvIGNsaWNrLlxuICAgKiBAcGFyYW0gcmVsYXRpdmVZIENvb3JkaW5hdGUgd2l0aGluIHRoZSBlbGVtZW50LCBhbG9uZyB0aGUgWS1heGlzIGF0IHdoaWNoIHRvIGNsaWNrLlxuICAgKiBAcGFyYW0gbW9kaWZpZXJzIE1vZGlmaWVyIGtleXMgaGVsZCB3aGlsZSBjbGlja2luZ1xuICAgKi9cbiAgcmlnaHRDbGljayhyZWxhdGl2ZVg6IG51bWJlciwgcmVsYXRpdmVZOiBudW1iZXIsIG1vZGlmaWVycz86IE1vZGlmaWVyS2V5cyk6IFByb21pc2U8dm9pZD47XG4gIGFzeW5jIHJpZ2h0Q2xpY2soXG4gICAgLi4uYXJnczogW01vZGlmaWVyS2V5cz9dIHwgWydjZW50ZXInLCBNb2RpZmllcktleXM/XSB8IFtudW1iZXIsIG51bWJlciwgTW9kaWZpZXJLZXlzP11cbiAgKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgYXdhaXQgdGhpcy5fZGlzcGF0Y2hDbGlja0V2ZW50U2VxdWVuY2UoYXJncywgd2ViZHJpdmVyLkJ1dHRvbi5SSUdIVCk7XG4gICAgYXdhaXQgdGhpcy5fc3RhYmlsaXplKCk7XG4gIH1cblxuICAvKiogRm9jdXMgdGhlIGVsZW1lbnQuICovXG4gIGFzeW5jIGZvY3VzKCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGF3YWl0IHRoaXMuX2V4ZWN1dGVTY3JpcHQoKGVsZW1lbnQ6IEhUTUxFbGVtZW50KSA9PiBlbGVtZW50LmZvY3VzKCksIHRoaXMuZWxlbWVudCgpKTtcbiAgICBhd2FpdCB0aGlzLl9zdGFiaWxpemUoKTtcbiAgfVxuXG4gIC8qKiBHZXQgdGhlIGNvbXB1dGVkIHZhbHVlIG9mIHRoZSBnaXZlbiBDU1MgcHJvcGVydHkgZm9yIHRoZSBlbGVtZW50LiAqL1xuICBhc3luYyBnZXRDc3NWYWx1ZShwcm9wZXJ0eTogc3RyaW5nKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgICBhd2FpdCB0aGlzLl9zdGFiaWxpemUoKTtcbiAgICByZXR1cm4gdGhpcy5lbGVtZW50KCkuZ2V0Q3NzVmFsdWUocHJvcGVydHkpO1xuICB9XG5cbiAgLyoqIEhvdmVycyB0aGUgbW91c2Ugb3ZlciB0aGUgZWxlbWVudC4gKi9cbiAgYXN5bmMgaG92ZXIoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgYXdhaXQgdGhpcy5fYWN0aW9ucygpLm1vdXNlTW92ZSh0aGlzLmVsZW1lbnQoKSkucGVyZm9ybSgpO1xuICAgIGF3YWl0IHRoaXMuX3N0YWJpbGl6ZSgpO1xuICB9XG5cbiAgLyoqIE1vdmVzIHRoZSBtb3VzZSBhd2F5IGZyb20gdGhlIGVsZW1lbnQuICovXG4gIGFzeW5jIG1vdXNlQXdheSgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBhd2FpdCB0aGlzLl9hY3Rpb25zKCkubW91c2VNb3ZlKHRoaXMuZWxlbWVudCgpLCB7eDogLTEsIHk6IC0xfSkucGVyZm9ybSgpO1xuICAgIGF3YWl0IHRoaXMuX3N0YWJpbGl6ZSgpO1xuICB9XG5cbiAgLyoqXG4gICAqIFNlbmRzIHRoZSBnaXZlbiBzdHJpbmcgdG8gdGhlIGlucHV0IGFzIGEgc2VyaWVzIG9mIGtleSBwcmVzc2VzLiBBbHNvIGZpcmVzIGlucHV0IGV2ZW50c1xuICAgKiBhbmQgYXR0ZW1wdHMgdG8gYWRkIHRoZSBzdHJpbmcgdG8gdGhlIEVsZW1lbnQncyB2YWx1ZS5cbiAgICovXG4gIGFzeW5jIHNlbmRLZXlzKC4uLmtleXM6IChzdHJpbmcgfCBUZXN0S2V5KVtdKTogUHJvbWlzZTx2b2lkPjtcbiAgLyoqXG4gICAqIFNlbmRzIHRoZSBnaXZlbiBzdHJpbmcgdG8gdGhlIGlucHV0IGFzIGEgc2VyaWVzIG9mIGtleSBwcmVzc2VzLiBBbHNvIGZpcmVzIGlucHV0IGV2ZW50c1xuICAgKiBhbmQgYXR0ZW1wdHMgdG8gYWRkIHRoZSBzdHJpbmcgdG8gdGhlIEVsZW1lbnQncyB2YWx1ZS5cbiAgICovXG4gIGFzeW5jIHNlbmRLZXlzKG1vZGlmaWVyczogTW9kaWZpZXJLZXlzLCAuLi5rZXlzOiAoc3RyaW5nIHwgVGVzdEtleSlbXSk6IFByb21pc2U8dm9pZD47XG4gIGFzeW5jIHNlbmRLZXlzKC4uLm1vZGlmaWVyc0FuZEtleXM6IGFueVtdKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgZmlyc3QgPSBtb2RpZmllcnNBbmRLZXlzWzBdO1xuICAgIGxldCBtb2RpZmllcnM6IE1vZGlmaWVyS2V5cztcbiAgICBsZXQgcmVzdDogKHN0cmluZyB8IFRlc3RLZXkpW107XG4gICAgaWYgKHR5cGVvZiBmaXJzdCAhPT0gJ3N0cmluZycgJiYgdHlwZW9mIGZpcnN0ICE9PSAnbnVtYmVyJykge1xuICAgICAgbW9kaWZpZXJzID0gZmlyc3Q7XG4gICAgICByZXN0ID0gbW9kaWZpZXJzQW5kS2V5cy5zbGljZSgxKTtcbiAgICB9IGVsc2Uge1xuICAgICAgbW9kaWZpZXJzID0ge307XG4gICAgICByZXN0ID0gbW9kaWZpZXJzQW5kS2V5cztcbiAgICB9XG5cbiAgICBjb25zdCBtb2RpZmllcktleXMgPSBnZXRTZWxlbml1bVdlYkRyaXZlck1vZGlmaWVyS2V5cyhtb2RpZmllcnMpO1xuICAgIGNvbnN0IGtleXMgPSByZXN0XG4gICAgICAubWFwKGsgPT4gKHR5cGVvZiBrID09PSAnc3RyaW5nJyA/IGsuc3BsaXQoJycpIDogW3NlbGVuaXVtV2ViRHJpdmVyS2V5TWFwW2tdXSkpXG4gICAgICAucmVkdWNlKChhcnIsIGspID0+IGFyci5jb25jYXQoayksIFtdKVxuICAgICAgLy8gd2ViZHJpdmVyLktleS5jaG9yZCBkb2Vzbid0IHdvcmsgd2VsbCB3aXRoIGdlY2tvZHJpdmVyIChtb3ppbGxhL2dlY2tvZHJpdmVyIzE1MDIpLFxuICAgICAgLy8gc28gYXZvaWQgaXQgaWYgbm8gbW9kaWZpZXIga2V5cyBhcmUgcmVxdWlyZWQuXG4gICAgICAubWFwKGsgPT4gKG1vZGlmaWVyS2V5cy5sZW5ndGggPiAwID8gd2ViZHJpdmVyLktleS5jaG9yZCguLi5tb2RpZmllcktleXMsIGspIDogaykpO1xuXG4gICAgYXdhaXQgdGhpcy5lbGVtZW50KCkuc2VuZEtleXMoLi4ua2V5cyk7XG4gICAgYXdhaXQgdGhpcy5fc3RhYmlsaXplKCk7XG4gIH1cblxuICAvKipcbiAgICogR2V0cyB0aGUgdGV4dCBmcm9tIHRoZSBlbGVtZW50LlxuICAgKiBAcGFyYW0gb3B0aW9ucyBPcHRpb25zIHRoYXQgYWZmZWN0IHdoYXQgdGV4dCBpcyBpbmNsdWRlZC5cbiAgICovXG4gIGFzeW5jIHRleHQob3B0aW9ucz86IFRleHRPcHRpb25zKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgICBhd2FpdCB0aGlzLl9zdGFiaWxpemUoKTtcbiAgICBpZiAob3B0aW9ucz8uZXhjbHVkZSkge1xuICAgICAgcmV0dXJuIHRoaXMuX2V4ZWN1dGVTY3JpcHQoX2dldFRleHRXaXRoRXhjbHVkZWRFbGVtZW50cywgdGhpcy5lbGVtZW50KCksIG9wdGlvbnMuZXhjbHVkZSk7XG4gICAgfVxuICAgIC8vIFdlIGRvbid0IGdvIHRocm91Z2ggdGhlIFdlYkRyaXZlciBgZ2V0VGV4dGAsIGJlY2F1c2UgaXQgZXhjbHVkZXMgdGV4dCBmcm9tIGhpZGRlbiBlbGVtZW50cy5cbiAgICByZXR1cm4gdGhpcy5fZXhlY3V0ZVNjcmlwdChcbiAgICAgIChlbGVtZW50OiBFbGVtZW50KSA9PiAoZWxlbWVudC50ZXh0Q29udGVudCB8fCAnJykudHJpbSgpLFxuICAgICAgdGhpcy5lbGVtZW50KCksXG4gICAgKTtcbiAgfVxuXG4gIC8qKiBHZXRzIHRoZSB2YWx1ZSBmb3IgdGhlIGdpdmVuIGF0dHJpYnV0ZSBmcm9tIHRoZSBlbGVtZW50LiAqL1xuICBhc3luYyBnZXRBdHRyaWJ1dGUobmFtZTogc3RyaW5nKTogUHJvbWlzZTxzdHJpbmcgfCBudWxsPiB7XG4gICAgYXdhaXQgdGhpcy5fc3RhYmlsaXplKCk7XG4gICAgcmV0dXJuIHRoaXMuX2V4ZWN1dGVTY3JpcHQoXG4gICAgICAoZWxlbWVudDogRWxlbWVudCwgYXR0cmlidXRlOiBzdHJpbmcpID0+IGVsZW1lbnQuZ2V0QXR0cmlidXRlKGF0dHJpYnV0ZSksXG4gICAgICB0aGlzLmVsZW1lbnQoKSxcbiAgICAgIG5hbWUsXG4gICAgKTtcbiAgfVxuXG4gIC8qKiBDaGVja3Mgd2hldGhlciB0aGUgZWxlbWVudCBoYXMgdGhlIGdpdmVuIGNsYXNzLiAqL1xuICBhc3luYyBoYXNDbGFzcyhuYW1lOiBzdHJpbmcpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICBhd2FpdCB0aGlzLl9zdGFiaWxpemUoKTtcbiAgICBjb25zdCBjbGFzc2VzID0gKGF3YWl0IHRoaXMuZ2V0QXR0cmlidXRlKCdjbGFzcycpKSB8fCAnJztcbiAgICByZXR1cm4gbmV3IFNldChjbGFzc2VzLnNwbGl0KC9cXHMrLykuZmlsdGVyKGMgPT4gYykpLmhhcyhuYW1lKTtcbiAgfVxuXG4gIC8qKiBHZXRzIHRoZSBkaW1lbnNpb25zIG9mIHRoZSBlbGVtZW50LiAqL1xuICBhc3luYyBnZXREaW1lbnNpb25zKCk6IFByb21pc2U8RWxlbWVudERpbWVuc2lvbnM+IHtcbiAgICBhd2FpdCB0aGlzLl9zdGFiaWxpemUoKTtcbiAgICBjb25zdCB7d2lkdGgsIGhlaWdodH0gPSBhd2FpdCB0aGlzLmVsZW1lbnQoKS5nZXRTaXplKCk7XG4gICAgY29uc3Qge3g6IGxlZnQsIHk6IHRvcH0gPSBhd2FpdCB0aGlzLmVsZW1lbnQoKS5nZXRMb2NhdGlvbigpO1xuICAgIHJldHVybiB7d2lkdGgsIGhlaWdodCwgbGVmdCwgdG9wfTtcbiAgfVxuXG4gIC8qKiBHZXRzIHRoZSB2YWx1ZSBvZiBhIHByb3BlcnR5IG9mIGFuIGVsZW1lbnQuICovXG4gIGFzeW5jIGdldFByb3BlcnR5PFQgPSBhbnk+KG5hbWU6IHN0cmluZyk6IFByb21pc2U8VD4ge1xuICAgIGF3YWl0IHRoaXMuX3N0YWJpbGl6ZSgpO1xuICAgIHJldHVybiB0aGlzLl9leGVjdXRlU2NyaXB0KFxuICAgICAgKGVsZW1lbnQ6IEVsZW1lbnQsIHByb3BlcnR5OiBrZXlvZiBFbGVtZW50KSA9PiBlbGVtZW50W3Byb3BlcnR5XSxcbiAgICAgIHRoaXMuZWxlbWVudCgpLFxuICAgICAgbmFtZSxcbiAgICApO1xuICB9XG5cbiAgLyoqIFNldHMgdGhlIHZhbHVlIG9mIGEgcHJvcGVydHkgb2YgYW4gaW5wdXQuICovXG4gIGFzeW5jIHNldElucHV0VmFsdWUobmV3VmFsdWU6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICAgIGF3YWl0IHRoaXMuX2V4ZWN1dGVTY3JpcHQoXG4gICAgICAoZWxlbWVudDogSFRNTElucHV0RWxlbWVudCwgdmFsdWU6IHN0cmluZykgPT4gKGVsZW1lbnQudmFsdWUgPSB2YWx1ZSksXG4gICAgICB0aGlzLmVsZW1lbnQoKSxcbiAgICAgIG5ld1ZhbHVlLFxuICAgICk7XG4gICAgYXdhaXQgdGhpcy5fc3RhYmlsaXplKCk7XG4gIH1cblxuICAvKiogU2VsZWN0cyB0aGUgb3B0aW9ucyBhdCB0aGUgc3BlY2lmaWVkIGluZGV4ZXMgaW5zaWRlIG9mIGEgbmF0aXZlIGBzZWxlY3RgIGVsZW1lbnQuICovXG4gIGFzeW5jIHNlbGVjdE9wdGlvbnMoLi4ub3B0aW9uSW5kZXhlczogbnVtYmVyW10pOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBhd2FpdCB0aGlzLl9zdGFiaWxpemUoKTtcbiAgICBjb25zdCBvcHRpb25zID0gYXdhaXQgdGhpcy5lbGVtZW50KCkuZmluZEVsZW1lbnRzKHdlYmRyaXZlci5CeS5jc3MoJ29wdGlvbicpKTtcbiAgICBjb25zdCBpbmRleGVzID0gbmV3IFNldChvcHRpb25JbmRleGVzKTsgLy8gQ29udmVydCB0byBhIHNldCB0byByZW1vdmUgZHVwbGljYXRlcy5cblxuICAgIGlmIChvcHRpb25zLmxlbmd0aCAmJiBpbmRleGVzLnNpemUpIHtcbiAgICAgIC8vIFJlc2V0IHRoZSB2YWx1ZSBzbyBhbGwgdGhlIHNlbGVjdGVkIHN0YXRlcyBhcmUgY2xlYXJlZC4gV2UgY2FuXG4gICAgICAvLyByZXVzZSB0aGUgaW5wdXQtc3BlY2lmaWMgbWV0aG9kIHNpbmNlIHRoZSBsb2dpYyBpcyB0aGUgc2FtZS5cbiAgICAgIGF3YWl0IHRoaXMuc2V0SW5wdXRWYWx1ZSgnJyk7XG5cbiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgb3B0aW9ucy5sZW5ndGg7IGkrKykge1xuICAgICAgICBpZiAoaW5kZXhlcy5oYXMoaSkpIHtcbiAgICAgICAgICAvLyBXZSBoYXZlIHRvIGhvbGQgdGhlIGNvbnRyb2wga2V5IHdoaWxlIGNsaWNraW5nIG9uIG9wdGlvbnMgc28gdGhhdCBtdWx0aXBsZSBjYW4gYmVcbiAgICAgICAgICAvLyBzZWxlY3RlZCBpbiBtdWx0aS1zZWxlY3Rpb24gbW9kZS4gVGhlIGtleSBkb2Vzbid0IGRvIGFueXRoaW5nIGZvciBzaW5nbGUgc2VsZWN0aW9uLlxuICAgICAgICAgIGF3YWl0IHRoaXMuX2FjdGlvbnMoKS5rZXlEb3duKHdlYmRyaXZlci5LZXkuQ09OVFJPTCkucGVyZm9ybSgpO1xuICAgICAgICAgIGF3YWl0IG9wdGlvbnNbaV0uY2xpY2soKTtcbiAgICAgICAgICBhd2FpdCB0aGlzLl9hY3Rpb25zKCkua2V5VXAod2ViZHJpdmVyLktleS5DT05UUk9MKS5wZXJmb3JtKCk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgYXdhaXQgdGhpcy5fc3RhYmlsaXplKCk7XG4gICAgfVxuICB9XG5cbiAgLyoqIENoZWNrcyB3aGV0aGVyIHRoaXMgZWxlbWVudCBtYXRjaGVzIHRoZSBnaXZlbiBzZWxlY3Rvci4gKi9cbiAgYXN5bmMgbWF0Y2hlc1NlbGVjdG9yKHNlbGVjdG9yOiBzdHJpbmcpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICBhd2FpdCB0aGlzLl9zdGFiaWxpemUoKTtcbiAgICByZXR1cm4gdGhpcy5fZXhlY3V0ZVNjcmlwdChcbiAgICAgIChlbGVtZW50OiBFbGVtZW50LCBzOiBzdHJpbmcpID0+XG4gICAgICAgIChFbGVtZW50LnByb3RvdHlwZS5tYXRjaGVzIHx8IChFbGVtZW50LnByb3RvdHlwZSBhcyBhbnkpLm1zTWF0Y2hlc1NlbGVjdG9yKS5jYWxsKFxuICAgICAgICAgIGVsZW1lbnQsXG4gICAgICAgICAgcyxcbiAgICAgICAgKSxcbiAgICAgIHRoaXMuZWxlbWVudCgpLFxuICAgICAgc2VsZWN0b3IsXG4gICAgKTtcbiAgfVxuXG4gIC8qKiBDaGVja3Mgd2hldGhlciB0aGUgZWxlbWVudCBpcyBmb2N1c2VkLiAqL1xuICBhc3luYyBpc0ZvY3VzZWQoKTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgYXdhaXQgdGhpcy5fc3RhYmlsaXplKCk7XG4gICAgcmV0dXJuIHdlYmRyaXZlci5XZWJFbGVtZW50LmVxdWFscyhcbiAgICAgIHRoaXMuZWxlbWVudCgpLFxuICAgICAgdGhpcy5lbGVtZW50KCkuZ2V0RHJpdmVyKCkuc3dpdGNoVG8oKS5hY3RpdmVFbGVtZW50KCksXG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBEaXNwYXRjaGVzIGFuIGV2ZW50IHdpdGggYSBwYXJ0aWN1bGFyIG5hbWUuXG4gICAqIEBwYXJhbSBuYW1lIE5hbWUgb2YgdGhlIGV2ZW50IHRvIGJlIGRpc3BhdGNoZWQuXG4gICAqL1xuICBhc3luYyBkaXNwYXRjaEV2ZW50KG5hbWU6IHN0cmluZywgZGF0YT86IFJlY29yZDxzdHJpbmcsIEV2ZW50RGF0YT4pOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBhd2FpdCB0aGlzLl9leGVjdXRlU2NyaXB0KGRpc3BhdGNoRXZlbnQsIG5hbWUsIHRoaXMuZWxlbWVudCgpLCBkYXRhKTtcbiAgICBhd2FpdCB0aGlzLl9zdGFiaWxpemUoKTtcbiAgfVxuXG4gIC8qKiBHZXRzIHRoZSB3ZWJkcml2ZXIgYWN0aW9uIHNlcXVlbmNlLiAqL1xuICBwcml2YXRlIF9hY3Rpb25zKCkge1xuICAgIHJldHVybiB0aGlzLmVsZW1lbnQoKS5nZXREcml2ZXIoKS5hY3Rpb25zKCk7XG4gIH1cblxuICAvKiogRXhlY3V0ZXMgYSBmdW5jdGlvbiBpbiB0aGUgYnJvd3Nlci4gKi9cbiAgcHJpdmF0ZSBhc3luYyBfZXhlY3V0ZVNjcmlwdDxUPihzY3JpcHQ6IEZ1bmN0aW9uLCAuLi52YXJfYXJnczogYW55W10pOiBQcm9taXNlPFQ+IHtcbiAgICByZXR1cm4gdGhpcy5lbGVtZW50KClcbiAgICAgIC5nZXREcml2ZXIoKVxuICAgICAgLmV4ZWN1dGVTY3JpcHQoc2NyaXB0LCAuLi52YXJfYXJncyk7XG4gIH1cblxuICAvKiogRGlzcGF0Y2hlcyBhbGwgdGhlIGV2ZW50cyB0aGF0IGFyZSBwYXJ0IG9mIGEgY2xpY2sgZXZlbnQgc2VxdWVuY2UuICovXG4gIHByaXZhdGUgYXN5bmMgX2Rpc3BhdGNoQ2xpY2tFdmVudFNlcXVlbmNlKFxuICAgIGFyZ3M6IFtNb2RpZmllcktleXM/XSB8IFsnY2VudGVyJywgTW9kaWZpZXJLZXlzP10gfCBbbnVtYmVyLCBudW1iZXIsIE1vZGlmaWVyS2V5cz9dLFxuICAgIGJ1dHRvbjogc3RyaW5nLFxuICApIHtcbiAgICBsZXQgbW9kaWZpZXJzOiBNb2RpZmllcktleXMgPSB7fTtcbiAgICBpZiAoYXJncy5sZW5ndGggJiYgdHlwZW9mIGFyZ3NbYXJncy5sZW5ndGggLSAxXSA9PT0gJ29iamVjdCcpIHtcbiAgICAgIG1vZGlmaWVycyA9IGFyZ3MucG9wKCkgYXMgTW9kaWZpZXJLZXlzO1xuICAgIH1cbiAgICBjb25zdCBtb2RpZmllcktleXMgPSBnZXRTZWxlbml1bVdlYkRyaXZlck1vZGlmaWVyS2V5cyhtb2RpZmllcnMpO1xuXG4gICAgLy8gT21pdHRpbmcgdGhlIG9mZnNldCBhcmd1bWVudCB0byBtb3VzZU1vdmUgcmVzdWx0cyBpbiBjbGlja2luZyB0aGUgY2VudGVyLlxuICAgIC8vIFRoaXMgaXMgdGhlIGRlZmF1bHQgYmVoYXZpb3Igd2Ugd2FudCwgc28gd2UgdXNlIGFuIGVtcHR5IGFycmF5IG9mIG9mZnNldEFyZ3MgaWZcbiAgICAvLyBubyBhcmdzIHJlbWFpbiBhZnRlciBwb3BwaW5nIHRoZSBtb2RpZmllcnMgZnJvbSB0aGUgYXJncyBwYXNzZWQgdG8gdGhpcyBmdW5jdGlvbi5cbiAgICBjb25zdCBvZmZzZXRBcmdzID0gKGFyZ3MubGVuZ3RoID09PSAyID8gW3t4OiBhcmdzWzBdLCB5OiBhcmdzWzFdfV0gOiBbXSkgYXMgW1xuICAgICAge3g6IG51bWJlcjsgeTogbnVtYmVyfSxcbiAgICBdO1xuXG4gICAgbGV0IGFjdGlvbnMgPSB0aGlzLl9hY3Rpb25zKCkubW91c2VNb3ZlKHRoaXMuZWxlbWVudCgpLCAuLi5vZmZzZXRBcmdzKTtcblxuICAgIGZvciAoY29uc3QgbW9kaWZpZXJLZXkgb2YgbW9kaWZpZXJLZXlzKSB7XG4gICAgICBhY3Rpb25zID0gYWN0aW9ucy5rZXlEb3duKG1vZGlmaWVyS2V5KTtcbiAgICB9XG4gICAgYWN0aW9ucyA9IGFjdGlvbnMuY2xpY2soYnV0dG9uKTtcbiAgICBmb3IgKGNvbnN0IG1vZGlmaWVyS2V5IG9mIG1vZGlmaWVyS2V5cykge1xuICAgICAgYWN0aW9ucyA9IGFjdGlvbnMua2V5VXAobW9kaWZpZXJLZXkpO1xuICAgIH1cblxuICAgIGF3YWl0IGFjdGlvbnMucGVyZm9ybSgpO1xuICB9XG59XG5cbi8qKlxuICogRGlzcGF0Y2hlcyBhbiBldmVudCB3aXRoIGEgcGFydGljdWxhciBuYW1lIGFuZCBkYXRhIHRvIGFuIGVsZW1lbnQuIE5vdGUgdGhhdCB0aGlzIG5lZWRzIHRvIGJlIGFcbiAqIHB1cmUgZnVuY3Rpb24sIGJlY2F1c2UgaXQgZ2V0cyBzdHJpbmdpZmllZCBieSBXZWJEcml2ZXIgYW5kIGlzIGV4ZWN1dGVkIGluc2lkZSB0aGUgYnJvd3Nlci5cbiAqL1xuZnVuY3Rpb24gZGlzcGF0Y2hFdmVudChuYW1lOiBzdHJpbmcsIGVsZW1lbnQ6IEVsZW1lbnQsIGRhdGE/OiBSZWNvcmQ8c3RyaW5nLCBFdmVudERhdGE+KSB7XG4gIGNvbnN0IGV2ZW50ID0gZG9jdW1lbnQuY3JlYXRlRXZlbnQoJ0V2ZW50Jyk7XG4gIGV2ZW50LmluaXRFdmVudChuYW1lKTtcbiAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOmJhbiBIYXZlIHRvIHVzZSBgT2JqZWN0LmFzc2lnbmAgdG8gcHJlc2VydmUgdGhlIG9yaWdpbmFsIG9iamVjdC5cbiAgT2JqZWN0LmFzc2lnbihldmVudCwgZGF0YSB8fCB7fSk7XG4gIGVsZW1lbnQuZGlzcGF0Y2hFdmVudChldmVudCk7XG59XG4iXX0=