/**
 * @fileoverview added by tsickle
 * Generated from: utils/test/widget-object.ts
 * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
 */
import { __assign } from "tslib";
/*!
 * Copyright 2019 VMware, Inc.
 * SPDX-License-Identifier: BSD-2-Clause
 */
import { TestBed } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
/**
 * An implementation of the page object pattern, but applied to widgets, since they can be reused on multiple pages.
 *
 * The main purpose for the wrapper are providing access to the internals of a widget avoiding duplication of code that
 * queries the internals of a component from a test.
 *
 * ## Subclass Rules
 *
 * - Methods exposed by subclasses should not expose HTMLElements or DebugElements directly. That would encourage
 * callers to query it from the outside creating potential duplicate querying code and abstraction leaks.
 *  - Subclasses also should not have testing assertions. They should only provide the state and the calling test can
 * assert code on its own.
 *
 * `T` is the type of the JS/TS object being wrapped
 *
 * It is recommended that files for implementations be named with a `.wo.ts` extension
 *
 * @deprecated
 * @abstract
 * @template T
 */
var /**
 * An implementation of the page object pattern, but applied to widgets, since they can be reused on multiple pages.
 *
 * The main purpose for the wrapper are providing access to the internals of a widget avoiding duplication of code that
 * queries the internals of a component from a test.
 *
 * ## Subclass Rules
 *
 * - Methods exposed by subclasses should not expose HTMLElements or DebugElements directly. That would encourage
 * callers to query it from the outside creating potential duplicate querying code and abstraction leaks.
 *  - Subclasses also should not have testing assertions. They should only provide the state and the calling test can
 * assert code on its own.
 *
 * `T` is the type of the JS/TS object being wrapped
 *
 * It is recommended that files for implementations be named with a `.wo.ts` extension
 *
 * @deprecated
 * @abstract
 * @template T
 */
WidgetObject = /** @class */ (function () {
    /**
     *
     * Constructor should only be called directly if you are directly instantiating the widget being wrapped (T). If you
     * need to find a widget within the tree, you should use {@link find}.
     *
     * @param component The component instance being managed. Whenever possible, we should access the component's API.
     * @param root The root element (host) for the component instance. We typically prefer to interact with the
     * component but there are times when we must check the DOM.
     * @param fixture The test fixture, so we can call {@link ComponentFixture#detectChanges} after something that
     * requires re-rendering of the DOM.
     */
    function WidgetObject(fixture, root, component) {
        if (root === void 0) { root = fixture.debugElement; }
        if (component === void 0) { component = fixture.componentInstance; }
        this.fixture = fixture;
        this.root = root;
        this.component = component;
    }
    /**
     * @return {?}
     */
    WidgetObject.prototype.detectChanges = /**
     * @return {?}
     */
    function () {
        this.fixture.detectChanges();
    };
    /**
     * Finds first element within this widget matching the given selector
     * @param selector What to search for
     * @param parent Where to start the search; defaults to the root of this component
     */
    /**
     * Finds first element within this widget matching the given selector
     * @protected
     * @param {?} selector What to search for
     * @param {?=} parent Where to start the search; defaults to the root of this component
     * @return {?}
     */
    WidgetObject.prototype.findElement = /**
     * Finds first element within this widget matching the given selector
     * @protected
     * @param {?} selector What to search for
     * @param {?=} parent Where to start the search; defaults to the root of this component
     * @return {?}
     */
    function (selector, parent) {
        if (parent === void 0) { parent = this.root; }
        /** @type {?} */
        var query = typeof selector === 'string' ? By.css(selector) : By.directive(selector);
        return parent.query(query);
    };
    /**
     * Same as {@link findElement} but returns all elements
     */
    /**
     * Same as {\@link findElement} but returns all elements
     * @protected
     * @param {?} selector
     * @param {?=} parent
     * @return {?}
     */
    WidgetObject.prototype.findElements = /**
     * Same as {\@link findElement} but returns all elements
     * @protected
     * @param {?} selector
     * @param {?=} parent
     * @return {?}
     */
    function (selector, parent) {
        if (parent === void 0) { parent = this.root; }
        /** @type {?} */
        var query = typeof selector === 'string' ? By.css(selector) : By.directive(selector);
        return parent.queryAll(query);
    };
    /**
     * Clicks an element and detects changes so the DOM is immediately updated
     * @param cssSelector Pass this in if you want to click a specific element. If not passed in, the entire node will
     * receive the click event
     * @param parent the parent element for which to search for the {@param cssSelector} within. Defaults to root if not provided.
     */
    /**
     * Clicks an element and detects changes so the DOM is immediately updated
     * @protected
     * @param {?=} cssSelector Pass this in if you want to click a specific element. If not passed in, the entire node will
     * receive the click event
     * @param {?=} parent the parent element for which to search for the {\@param cssSelector} within. Defaults to root if not provided.
     * @return {?}
     */
    WidgetObject.prototype.click = /**
     * Clicks an element and detects changes so the DOM is immediately updated
     * @protected
     * @param {?=} cssSelector Pass this in if you want to click a specific element. If not passed in, the entire node will
     * receive the click event
     * @param {?=} parent the parent element for which to search for the {\@param cssSelector} within. Defaults to root if not provided.
     * @return {?}
     */
    function (cssSelector, parent) {
        if (parent === void 0) { parent = this.root; }
        /** @type {?} */
        var nativeElement = parent.query(By.css(cssSelector)).nativeElement;
        nativeElement.click();
        this.detectChanges();
    };
    /**
     * Send a keyboard event of type {@param eventType} with properties {@param eventProperties} on an element
     * found by the {@param cssSelector} within the provided {@param parent} or the current root element.
     * Setting the event properties is done with `Object.defineProperty` on the created event. This allows setting
     * properties like `which` that is deprecated and cannot be set with the native approach of creating keyboard event.
     * @param eventType The keyboard event type like 'keyup', 'keydown', 'keypress'
     * @param eventProperties properties of the event like `code`, `key` etc.
     * @param cssSelector Pass this in if you want trigger the event on a specific element.
     *        If not passed in, the event will be triggered on the entire node
     * @param parent the parent element for which to search for the {@param cssSelector} within. Defaults to root if not provided.
     */
    /**
     * Send a keyboard event of type {\@param eventType} with properties {\@param eventProperties} on an element
     * found by the {\@param cssSelector} within the provided {\@param parent} or the current root element.
     * Setting the event properties is done with `Object.defineProperty` on the created event. This allows setting
     * properties like `which` that is deprecated and cannot be set with the native approach of creating keyboard event.
     * @protected
     * @param {?} eventType The keyboard event type like 'keyup', 'keydown', 'keypress'
     * @param {?} eventProperties properties of the event like `code`, `key` etc.
     * @param {?=} cssSelector Pass this in if you want trigger the event on a specific element.
     *        If not passed in, the event will be triggered on the entire node
     * @param {?=} parent the parent element for which to search for the {\@param cssSelector} within. Defaults to root if not provided.
     * @return {?}
     */
    WidgetObject.prototype.sendKeyboardEvent = /**
     * Send a keyboard event of type {\@param eventType} with properties {\@param eventProperties} on an element
     * found by the {\@param cssSelector} within the provided {\@param parent} or the current root element.
     * Setting the event properties is done with `Object.defineProperty` on the created event. This allows setting
     * properties like `which` that is deprecated and cannot be set with the native approach of creating keyboard event.
     * @protected
     * @param {?} eventType The keyboard event type like 'keyup', 'keydown', 'keypress'
     * @param {?} eventProperties properties of the event like `code`, `key` etc.
     * @param {?=} cssSelector Pass this in if you want trigger the event on a specific element.
     *        If not passed in, the event will be triggered on the entire node
     * @param {?=} parent the parent element for which to search for the {\@param cssSelector} within. Defaults to root if not provided.
     * @return {?}
     */
    function (eventType, eventProperties, cssSelector, parent) {
        if (parent === void 0) { parent = this.root; }
        /** @type {?} */
        var nativeElement = parent.query(By.css(cssSelector)).nativeElement;
        // Create keyboard event that bubbles up the chain
        /** @type {?} */
        var event = new KeyboardEvent(eventType, { bubbles: true });
        // Use `Object.defineProperty` in order to be able to set even deprecated, readonly properties like `which`
        Object.keys(eventProperties).forEach((/**
         * @param {?} key
         * @return {?}
         */
        function (key) {
            Object.defineProperty(event, key, { value: eventProperties[key] });
        }));
        nativeElement.dispatchEvent(event);
        this.detectChanges();
    };
    /**
     * Sets the value of an input element or textarea element
     * @param value the value that the element should display
     * @param cssSelector Pass this in if you want trigger the event on a specific element.
     *        If not passed in, the event will be triggered on the entire node
     * @param parent the parent element for which to search for the {@param cssSelector} within. Defaults to root if not provided.
     */
    /**
     * Sets the value of an input element or textarea element
     * @protected
     * @param {?} value the value that the element should display
     * @param {?=} cssSelector Pass this in if you want trigger the event on a specific element.
     *        If not passed in, the event will be triggered on the entire node
     * @param {?=} parent the parent element for which to search for the {\@param cssSelector} within. Defaults to root if not provided.
     * @return {?}
     */
    WidgetObject.prototype.setInputValue = /**
     * Sets the value of an input element or textarea element
     * @protected
     * @param {?} value the value that the element should display
     * @param {?=} cssSelector Pass this in if you want trigger the event on a specific element.
     *        If not passed in, the event will be triggered on the entire node
     * @param {?=} parent the parent element for which to search for the {\@param cssSelector} within. Defaults to root if not provided.
     * @return {?}
     */
    function (value, cssSelector, parent) {
        if (parent === void 0) { parent = this.root; }
        /** @type {?} */
        var nativeElement = parent.query(By.css(cssSelector)).nativeElement;
        nativeElement.value = String(value);
        nativeElement.dispatchEvent(new Event('input'));
        this.detectChanges();
    };
    /**
     * Returns text content of this widget
     * If the element cannot be found, gives empty string.
     * @param cssSelector Pass this in if you want to retrieve text for a specific element within this widget.
     * @param parent Where to start the search; defaults to the root of this component
     */
    /**
     * Returns text content of this widget
     * If the element cannot be found, gives empty string.
     * @protected
     * @param {?} cssSelector Pass this in if you want to retrieve text for a specific element within this widget.
     * @param {?=} parent Where to start the search; defaults to the root of this component
     * @return {?}
     */
    WidgetObject.prototype.getText = /**
     * Returns text content of this widget
     * If the element cannot be found, gives empty string.
     * @protected
     * @param {?} cssSelector Pass this in if you want to retrieve text for a specific element within this widget.
     * @param {?=} parent Where to start the search; defaults to the root of this component
     * @return {?}
     */
    function (cssSelector, parent) {
        if (parent === void 0) { parent = this.root; }
        /** @type {?} */
        var element = this.findElement(cssSelector, parent);
        return element ? this.getNodeText(element) : '';
    };
    /**
     * Same as {@link getText} but return the text for all matching nodes
     */
    /**
     * Same as {\@link getText} but return the text for all matching nodes
     * @protected
     * @param {?} cssSelector
     * @return {?}
     */
    WidgetObject.prototype.getTexts = /**
     * Same as {\@link getText} but return the text for all matching nodes
     * @protected
     * @param {?} cssSelector
     * @return {?}
     */
    function (cssSelector) {
        var _this = this;
        return this.findElements(cssSelector).map((/**
         * @param {?} el
         * @return {?}
         */
        function (el) { return _this.getNodeText(el); }));
    };
    /**
     * @protected
     * @param {?} el
     * @return {?}
     */
    WidgetObject.prototype.getNodeText = /**
     * @protected
     * @param {?} el
     * @return {?}
     */
    function (el) {
        // The || '' is because textContent could technically be null when passed in the document
        // element object. We know that cannot be pased in here, so we ignore it for coverage
        // but we still need the line there to make strictNullChecks work
        return el.nativeElement.textContent.trim() || /* istanbul ignore next */ '';
    };
    return WidgetObject;
}());
/**
 * An implementation of the page object pattern, but applied to widgets, since they can be reused on multiple pages.
 *
 * The main purpose for the wrapper are providing access to the internals of a widget avoiding duplication of code that
 * queries the internals of a component from a test.
 *
 * ## Subclass Rules
 *
 * - Methods exposed by subclasses should not expose HTMLElements or DebugElements directly. That would encourage
 * callers to query it from the outside creating potential duplicate querying code and abstraction leaks.
 *  - Subclasses also should not have testing assertions. They should only provide the state and the calling test can
 * assert code on its own.
 *
 * `T` is the type of the JS/TS object being wrapped
 *
 * It is recommended that files for implementations be named with a `.wo.ts` extension
 *
 * @deprecated
 * @abstract
 * @template T
 */
export { WidgetObject };
if (false) {
    /**
     * @type {?}
     * @protected
     */
    WidgetObject.prototype.fixture;
    /**
     * @type {?}
     * @protected
     */
    WidgetObject.prototype.root;
    /** @type {?} */
    WidgetObject.prototype.component;
}
/**
 * Subclasses should implement the FindableWidget interface so they can be found with {\@link WidgetFinder}
 *
 * ## Note
 * This is done by creating a static property `tagName`on your subclass, not a regular instance, since this
 * interface represents a constructor for a {\@link WidgetObject}, not an instance.
 * @record
 * @template T
 */
export function FindableWidget() { }
if (false) {
    /** @type {?} */
    FindableWidget.prototype.tagName;
}
/**
 * Arguments for {\@link WidgetFinder#findWidgets} and {\@link WidgetFinder#find}
 * @record
 * @template T
 */
export function FindParams() { }
if (false) {
    /**
     * The constructor of the widget to be found
     * @type {?}
     */
    FindParams.prototype.woConstructor;
    /**
     * If provided, search starts from this container. It defaults to the fixture's root debugElement
     * @type {?|undefined}
     */
    FindParams.prototype.ancestor;
    /**
     * Optional CSS class name that can be used when there could be multiple instances of the object within the
     * fixture tree
     * @type {?|undefined}
     */
    FindParams.prototype.className;
}
/**
 * @deprecated Finds instances that implement {\@link FindableWidget}
 * H is the host component's type. This finder is only for old unit tests.
 * Please use AngularWidgetObjectFinder instead.
 * @template H
 */
var /**
 * @deprecated Finds instances that implement {\@link FindableWidget}
 * H is the host component's type. This finder is only for old unit tests.
 * Please use AngularWidgetObjectFinder instead.
 * @template H
 */
WidgetFinder = /** @class */ (function () {
    /**
     * @param componentConstructor The host component to be created as the root of the tests's fixture
     */
    function WidgetFinder(componentConstructor) {
        this.fixture = TestBed.createComponent(componentConstructor);
        this.hostComponent = this.fixture.componentInstance;
    }
    /**
     * Finds widgets within a fixture
     * @return A Potentially empty list of widgets matching the given specs
     */
    /**
     * Finds widgets within a fixture
     * @template C, T
     * @param {?} params
     * @param {?=} parent
     * @return {?} A Potentially empty list of widgets matching the given specs
     */
    WidgetFinder.prototype.findWidgets = /**
     * Finds widgets within a fixture
     * @template C, T
     * @param {?} params
     * @param {?=} parent
     * @return {?} A Potentially empty list of widgets matching the given specs
     */
    function (params, parent) {
        var _this = this;
        /** @type {?} */
        var defaults = { ancestor: this.fixture.debugElement, className: '' };
        var _a = isFindParamsObject(params)
            ? __assign(__assign({}, defaults), params) : __assign(__assign({}, defaults), { woConstructor: params }), woConstructor = _a.woConstructor, ancestor = _a.ancestor, className = _a.className;
        /** @type {?} */
        var query = woConstructor.tagName;
        if (className) {
            query += "." + className;
        }
        /** @type {?} */
        var componentRoots = (parent ? parent : ancestor).queryAll(By.css(query));
        /** @type {?} */
        var widgets = componentRoots.map((
        // Typescript is not able to infer it correctly as the subclass but we know for sure
        // Typescript is not able to infer it correctly as the subclass but we know for sure
        /**
         * @param {?} root
         * @return {?}
         */
        function (root) { return (/** @type {?} */ (new woConstructor(_this.fixture, root, root.componentInstance))); }));
        return widgets;
    };
    /**
     * Finds a single widget object
     * @throws An error if the widget is not found or if there are multiple instances
     */
    /**
     * Finds a single widget object
     * @throws An error if the widget is not found or if there are multiple instances
     * @template C, T
     * @param {?} params
     * @return {?}
     */
    WidgetFinder.prototype.find = /**
     * Finds a single widget object
     * @throws An error if the widget is not found or if there are multiple instances
     * @template C, T
     * @param {?} params
     * @return {?}
     */
    function (params) {
        /** @type {?} */
        var widgets = this.findWidgets(params);
        /** @type {?} */
        var tagName = isFindParamsObject(params) ? params.woConstructor.tagName : params.tagName;
        if (widgets.length === 0) {
            throw Error("Did not find a <" + tagName + ">");
        }
        if (widgets.length > 1) {
            throw Error("Expected to find a single <" + tagName + "> but found " + widgets.length);
        }
        return (/** @type {?} */ (widgets[0]));
    };
    /**
     * @return {?}
     */
    WidgetFinder.prototype.detectChanges = /**
     * @return {?}
     */
    function () {
        this.fixture.detectChanges();
    };
    return WidgetFinder;
}());
/**
 * @deprecated Finds instances that implement {\@link FindableWidget}
 * H is the host component's type. This finder is only for old unit tests.
 * Please use AngularWidgetObjectFinder instead.
 * @template H
 */
export { WidgetFinder };
if (false) {
    /**
     * We don't care or could possibly know the type of fixture
     * @type {?}
     * @private
     */
    WidgetFinder.prototype.fixture;
    /**
     * If you need direct access to manipulate the host
     * @type {?}
     */
    WidgetFinder.prototype.hostComponent;
}
/**
 * @template T
 * @param {?} params
 * @return {?}
 */
export function isFindParamsObject(params) {
    return !!((/** @type {?} */ (params))).woConstructor;
}
/**
 * Can be used in tests that use `this` to share a finder with before/AfterEach instead of leaky closures
 * @record
 * @template T
 */
export function HasFinder() { }
if (false) {
    /** @type {?} */
    HasFinder.prototype.finder;
}
//# sourceMappingURL=data:application/json;base64, 