import { __awaiter } from 'tslib';
import { HarnessPredicate, ComponentHarness, parallel, TestKey } from '@angular/cdk/testing';
import { coerceBooleanProperty } from '@angular/cdk/coercion';

/**
 * @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
 */

/**
 * @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
 */
/** Sets up the filter predicates for a datepicker input harness. */
function getInputPredicate(type, options) {
    return new HarnessPredicate(type, options)
        .addOption('value', options.value, (harness, value) => {
        return HarnessPredicate.stringMatches(harness.getValue(), value);
    })
        .addOption('placeholder', options.placeholder, (harness, placeholder) => {
        return HarnessPredicate.stringMatches(harness.getPlaceholder(), placeholder);
    });
}
/** Base class for datepicker input harnesses. */
class MatDatepickerInputHarnessBase extends ComponentHarness {
    /** Whether the input is disabled. */
    isDisabled() {
        return __awaiter(this, void 0, void 0, function* () {
            return (yield this.host()).getProperty('disabled');
        });
    }
    /** Whether the input is required. */
    isRequired() {
        return __awaiter(this, void 0, void 0, function* () {
            return (yield this.host()).getProperty('required');
        });
    }
    /** Gets the value of the input. */
    getValue() {
        return __awaiter(this, void 0, void 0, function* () {
            // The "value" property of the native input is always defined.
            return (yield (yield this.host()).getProperty('value'));
        });
    }
    /**
     * Sets the value of the input. The value will be set by simulating
     * keypresses that correspond to the given value.
     */
    setValue(newValue) {
        return __awaiter(this, void 0, void 0, function* () {
            const inputEl = yield this.host();
            yield inputEl.clear();
            // We don't want to send keys for the value if the value is an empty
            // string in order to clear the value. Sending keys with an empty string
            // still results in unnecessary focus events.
            if (newValue) {
                yield inputEl.sendKeys(newValue);
            }
            // @breaking-change 12.0.0 Remove null check once `dispatchEvent` is a required method.
            if (inputEl.dispatchEvent) {
                yield inputEl.dispatchEvent('change');
            }
        });
    }
    /** Gets the placeholder of the input. */
    getPlaceholder() {
        return __awaiter(this, void 0, void 0, function* () {
            return (yield (yield this.host()).getProperty('placeholder'));
        });
    }
    /**
     * Focuses the input and returns a promise that indicates when the
     * action is complete.
     */
    focus() {
        return __awaiter(this, void 0, void 0, function* () {
            return (yield this.host()).focus();
        });
    }
    /**
     * Blurs the input and returns a promise that indicates when the
     * action is complete.
     */
    blur() {
        return __awaiter(this, void 0, void 0, function* () {
            return (yield this.host()).blur();
        });
    }
    /** Whether the input is focused. */
    isFocused() {
        return __awaiter(this, void 0, void 0, function* () {
            return (yield this.host()).isFocused();
        });
    }
    /** Gets the formatted minimum date for the input's value. */
    getMin() {
        return __awaiter(this, void 0, void 0, function* () {
            return (yield this.host()).getAttribute('min');
        });
    }
    /** Gets the formatted maximum date for the input's value. */
    getMax() {
        return __awaiter(this, void 0, void 0, function* () {
            return (yield this.host()).getAttribute('max');
        });
    }
}

/**
 * @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
 */
/** Harness for interacting with a standard Material calendar cell in tests. */
class MatCalendarCellHarness extends ComponentHarness {
    constructor() {
        super(...arguments);
        /** Reference to the inner content element inside the cell. */
        this._content = this.locatorFor('.mat-calendar-body-cell-content');
    }
    /**
     * Gets a `HarnessPredicate` that can be used to search for a `MatCalendarCellHarness`
     * that meets certain criteria.
     * @param options Options for filtering which cell instances are considered a match.
     * @return a `HarnessPredicate` configured with the given options.
     */
    static with(options = {}) {
        return new HarnessPredicate(MatCalendarCellHarness, options)
            .addOption('text', options.text, (harness, text) => {
            return HarnessPredicate.stringMatches(harness.getText(), text);
        })
            .addOption('selected', options.selected, (harness, selected) => __awaiter(this, void 0, void 0, function* () {
            return (yield harness.isSelected()) === selected;
        }))
            .addOption('active', options.active, (harness, active) => __awaiter(this, void 0, void 0, function* () {
            return (yield harness.isActive()) === active;
        }))
            .addOption('disabled', options.disabled, (harness, disabled) => __awaiter(this, void 0, void 0, function* () {
            return (yield harness.isDisabled()) === disabled;
        }))
            .addOption('today', options.today, (harness, today) => __awaiter(this, void 0, void 0, function* () {
            return (yield harness.isToday()) === today;
        }))
            .addOption('inRange', options.inRange, (harness, inRange) => __awaiter(this, void 0, void 0, function* () {
            return (yield harness.isInRange()) === inRange;
        }))
            .addOption('inComparisonRange', options.inComparisonRange, (harness, inComparisonRange) => __awaiter(this, void 0, void 0, function* () {
            return (yield harness.isInComparisonRange()) === inComparisonRange;
        }))
            .addOption('inPreviewRange', options.inPreviewRange, (harness, inPreviewRange) => __awaiter(this, void 0, void 0, function* () {
            return (yield harness.isInPreviewRange()) === inPreviewRange;
        }));
    }
    /** Gets the text of the calendar cell. */
    getText() {
        return __awaiter(this, void 0, void 0, function* () {
            return (yield this._content()).text();
        });
    }
    /** Gets the aria-label of the calendar cell. */
    getAriaLabel() {
        return __awaiter(this, void 0, void 0, function* () {
            // We're guaranteed for the `aria-label` to be defined
            // since this is a private element that we control.
            return (yield this.host()).getAttribute('aria-label');
        });
    }
    /** Whether the cell is selected. */
    isSelected() {
        return __awaiter(this, void 0, void 0, function* () {
            const host = yield this.host();
            return (yield host.getAttribute('aria-selected')) === 'true';
        });
    }
    /** Whether the cell is disabled. */
    isDisabled() {
        return __awaiter(this, void 0, void 0, function* () {
            return this._hasState('disabled');
        });
    }
    /** Whether the cell is currently activated using keyboard navigation. */
    isActive() {
        return __awaiter(this, void 0, void 0, function* () {
            return this._hasState('active');
        });
    }
    /** Whether the cell represents today's date. */
    isToday() {
        return __awaiter(this, void 0, void 0, function* () {
            return (yield this._content()).hasClass('mat-calendar-body-today');
        });
    }
    /** Selects the calendar cell. Won't do anything if the cell is disabled. */
    select() {
        return __awaiter(this, void 0, void 0, function* () {
            return (yield this.host()).click();
        });
    }
    /** Hovers over the calendar cell. */
    hover() {
        return __awaiter(this, void 0, void 0, function* () {
            return (yield this.host()).hover();
        });
    }
    /** Moves the mouse away from the calendar cell. */
    mouseAway() {
        return __awaiter(this, void 0, void 0, function* () {
            return (yield this.host()).mouseAway();
        });
    }
    /** Focuses the calendar cell. */
    focus() {
        return __awaiter(this, void 0, void 0, function* () {
            return (yield this.host()).focus();
        });
    }
    /** Removes focus from the calendar cell. */
    blur() {
        return __awaiter(this, void 0, void 0, function* () {
            return (yield this.host()).blur();
        });
    }
    /** Whether the cell is the start of the main range. */
    isRangeStart() {
        return __awaiter(this, void 0, void 0, function* () {
            return this._hasState('range-start');
        });
    }
    /** Whether the cell is the end of the main range. */
    isRangeEnd() {
        return __awaiter(this, void 0, void 0, function* () {
            return this._hasState('range-end');
        });
    }
    /** Whether the cell is part of the main range. */
    isInRange() {
        return __awaiter(this, void 0, void 0, function* () {
            return this._hasState('in-range');
        });
    }
    /** Whether the cell is the start of the comparison range. */
    isComparisonRangeStart() {
        return __awaiter(this, void 0, void 0, function* () {
            return this._hasState('comparison-start');
        });
    }
    /** Whether the cell is the end of the comparison range. */
    isComparisonRangeEnd() {
        return __awaiter(this, void 0, void 0, function* () {
            return this._hasState('comparison-end');
        });
    }
    /** Whether the cell is inside of the comparison range. */
    isInComparisonRange() {
        return __awaiter(this, void 0, void 0, function* () {
            return this._hasState('in-comparison-range');
        });
    }
    /** Whether the cell is the start of the preview range. */
    isPreviewRangeStart() {
        return __awaiter(this, void 0, void 0, function* () {
            return this._hasState('preview-start');
        });
    }
    /** Whether the cell is the end of the preview range. */
    isPreviewRangeEnd() {
        return __awaiter(this, void 0, void 0, function* () {
            return this._hasState('preview-end');
        });
    }
    /** Whether the cell is inside of the preview range. */
    isInPreviewRange() {
        return __awaiter(this, void 0, void 0, function* () {
            return this._hasState('in-preview');
        });
    }
    /** Returns whether the cell has a particular CSS class-based state. */
    _hasState(name) {
        return __awaiter(this, void 0, void 0, function* () {
            return (yield this.host()).hasClass(`mat-calendar-body-${name}`);
        });
    }
}
MatCalendarCellHarness.hostSelector = '.mat-calendar-body-cell';

/**
 * @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
 */
/** Harness for interacting with a standard Material calendar in tests. */
class MatCalendarHarness extends ComponentHarness {
    constructor() {
        super(...arguments);
        /** Queries for the calendar's period toggle button. */
        this._periodButton = this.locatorFor('.mat-calendar-period-button');
    }
    /**
     * Gets a `HarnessPredicate` that can be used to search for a `MatCalendarHarness`
     * that meets certain criteria.
     * @param options Options for filtering which calendar instances are considered a match.
     * @return a `HarnessPredicate` configured with the given options.
     */
    static with(options = {}) {
        return new HarnessPredicate(MatCalendarHarness, options);
    }
    /**
     * Gets a list of cells inside the calendar.
     * @param filter Optionally filters which cells are included.
     */
    getCells(filter = {}) {
        return __awaiter(this, void 0, void 0, function* () {
            return this.locatorForAll(MatCalendarCellHarness.with(filter))();
        });
    }
    /** Gets the current view that is being shown inside the calendar. */
    getCurrentView() {
        return __awaiter(this, void 0, void 0, function* () {
            if (yield this.locatorForOptional('mat-multi-year-view')()) {
                return 2 /* MULTI_YEAR */;
            }
            if (yield this.locatorForOptional('mat-year-view')()) {
                return 1 /* YEAR */;
            }
            return 0 /* MONTH */;
        });
    }
    /** Gets the label of the current calendar view. */
    getCurrentViewLabel() {
        return __awaiter(this, void 0, void 0, function* () {
            return (yield this._periodButton()).text();
        });
    }
    /** Changes the calendar view by clicking on the view toggle button. */
    changeView() {
        return __awaiter(this, void 0, void 0, function* () {
            return (yield this._periodButton()).click();
        });
    }
    /** Goes to the next page of the current view (e.g. next month when inside the month view). */
    next() {
        return __awaiter(this, void 0, void 0, function* () {
            return (yield this.locatorFor('.mat-calendar-next-button')()).click();
        });
    }
    /**
     * Goes to the previous page of the current view
     * (e.g. previous month when inside the month view).
     */
    previous() {
        return __awaiter(this, void 0, void 0, function* () {
            return (yield this.locatorFor('.mat-calendar-previous-button')()).click();
        });
    }
    /**
     * Selects a cell in the current calendar view.
     * @param filter An optional filter to apply to the cells. The first cell matching the filter
     *     will be selected.
     */
    selectCell(filter = {}) {
        return __awaiter(this, void 0, void 0, function* () {
            const cells = yield this.getCells(filter);
            if (!cells.length) {
                throw Error(`Cannot find calendar cell matching filter ${JSON.stringify(filter)}`);
            }
            yield cells[0].select();
        });
    }
}
MatCalendarHarness.hostSelector = '.mat-calendar';

/**
 * @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
 */
/** Base class for harnesses that can trigger a calendar. */
class DatepickerTriggerHarnessBase extends ComponentHarness {
    /** Opens the calendar if the trigger is enabled and it has a calendar. */
    openCalendar() {
        return __awaiter(this, void 0, void 0, function* () {
            const [isDisabled, hasCalendar] = yield parallel(() => [this.isDisabled(), this.hasCalendar()]);
            if (!isDisabled && hasCalendar) {
                return this._openCalendar();
            }
        });
    }
    /** Closes the calendar if it is open. */
    closeCalendar() {
        return __awaiter(this, void 0, void 0, function* () {
            if (yield this.isCalendarOpen()) {
                yield closeCalendar(getCalendarId(this.host()), this.documentRootLocatorFactory());
                // This is necessary so that we wait for the closing animation to finish in touch UI mode.
                yield this.forceStabilize();
            }
        });
    }
    /** Gets whether there is a calendar associated with the trigger. */
    hasCalendar() {
        return __awaiter(this, void 0, void 0, function* () {
            return (yield getCalendarId(this.host())) != null;
        });
    }
    /**
     * Gets the `MatCalendarHarness` that is associated with the trigger.
     * @param filter Optionally filters which calendar is included.
     */
    getCalendar(filter = {}) {
        return __awaiter(this, void 0, void 0, function* () {
            return getCalendar(filter, this.host(), this.documentRootLocatorFactory());
        });
    }
}
/** Gets the ID of the calendar that a particular test element can trigger. */
function getCalendarId(host) {
    return __awaiter(this, void 0, void 0, function* () {
        return (yield host).getAttribute('data-mat-calendar');
    });
}
/** Closes the calendar with a specific ID. */
function closeCalendar(calendarId, documentLocator) {
    return __awaiter(this, void 0, void 0, function* () {
        // We close the calendar by clicking on the backdrop, even though all datepicker variants
        // have the ability to close by pressing escape. The backdrop is preferrable, because the
        // escape key has multiple functions inside a range picker (either cancel the current range
        // or close the calendar). Since we don't have access to set the ID on the backdrop in all
        // cases, we set a unique class instead which is the same as the calendar's ID and suffixed
        // with `-backdrop`.
        const backdropSelector = `.${yield calendarId}-backdrop`;
        return (yield documentLocator.locatorFor(backdropSelector)()).click();
    });
}
/** Gets the test harness for a calendar associated with a particular host. */
function getCalendar(filter, host, documentLocator) {
    return __awaiter(this, void 0, void 0, function* () {
        const calendarId = yield getCalendarId(host);
        if (!calendarId) {
            throw Error(`Element is not associated with a calendar`);
        }
        return documentLocator.locatorFor(MatCalendarHarness.with(Object.assign(Object.assign({}, filter), { selector: `#${calendarId}` })))();
    });
}

/**
 * @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
 */
/** Harness for interacting with a standard Material datepicker inputs in tests. */
class MatDatepickerInputHarness extends MatDatepickerInputHarnessBase {
    /**
     * Gets a `HarnessPredicate` that can be used to search for a `MatDatepickerInputHarness`
     * that meets certain criteria.
     * @param options Options for filtering which input instances are considered a match.
     * @return a `HarnessPredicate` configured with the given options.
     */
    static with(options = {}) {
        return getInputPredicate(MatDatepickerInputHarness, options);
    }
    /** Gets whether the calendar associated with the input is open. */
    isCalendarOpen() {
        return __awaiter(this, void 0, void 0, function* () {
            // `aria-owns` is set only if there's an open datepicker so we can use it as an indicator.
            const host = yield this.host();
            return (yield host.getAttribute('aria-owns')) != null;
        });
    }
    /** Opens the calendar associated with the input. */
    openCalendar() {
        return __awaiter(this, void 0, void 0, function* () {
            const [isDisabled, hasCalendar] = yield parallel(() => [this.isDisabled(), this.hasCalendar()]);
            if (!isDisabled && hasCalendar) {
                // Alt + down arrow is the combination for opening the calendar with the keyboard.
                const host = yield this.host();
                return host.sendKeys({ alt: true }, TestKey.DOWN_ARROW);
            }
        });
    }
    /** Closes the calendar associated with the input. */
    closeCalendar() {
        return __awaiter(this, void 0, void 0, function* () {
            if (yield this.isCalendarOpen()) {
                yield closeCalendar(getCalendarId(this.host()), this.documentRootLocatorFactory());
                // This is necessary so that we wait for the closing animation to finish in touch UI mode.
                yield this.forceStabilize();
            }
        });
    }
    /** Whether a calendar is associated with the input. */
    hasCalendar() {
        return __awaiter(this, void 0, void 0, function* () {
            return (yield getCalendarId(this.host())) != null;
        });
    }
    /**
     * Gets the `MatCalendarHarness` that is associated with the trigger.
     * @param filter Optionally filters which calendar is included.
     */
    getCalendar(filter = {}) {
        return __awaiter(this, void 0, void 0, function* () {
            return getCalendar(filter, this.host(), this.documentRootLocatorFactory());
        });
    }
}
MatDatepickerInputHarness.hostSelector = '.mat-datepicker-input';

/**
 * @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
 */
/** Harness for interacting with a standard Material datepicker toggle in tests. */
class MatDatepickerToggleHarness extends DatepickerTriggerHarnessBase {
    constructor() {
        super(...arguments);
        /** The clickable button inside the toggle. */
        this._button = this.locatorFor('button');
    }
    /**
     * Gets a `HarnessPredicate` that can be used to search for a `MatDatepickerToggleHarness` that
     * meets certain criteria.
     * @param options Options for filtering which datepicker toggle instances are considered a match.
     * @return a `HarnessPredicate` configured with the given options.
     */
    static with(options = {}) {
        return new HarnessPredicate(MatDatepickerToggleHarness, options);
    }
    /** Gets whether the calendar associated with the toggle is open. */
    isCalendarOpen() {
        return __awaiter(this, void 0, void 0, function* () {
            return (yield this.host()).hasClass('mat-datepicker-toggle-active');
        });
    }
    /** Whether the toggle is disabled. */
    isDisabled() {
        return __awaiter(this, void 0, void 0, function* () {
            const button = yield this._button();
            return coerceBooleanProperty(yield button.getAttribute('disabled'));
        });
    }
    _openCalendar() {
        return __awaiter(this, void 0, void 0, function* () {
            return (yield this._button()).click();
        });
    }
}
MatDatepickerToggleHarness.hostSelector = '.mat-datepicker-toggle';

/**
 * @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
 */
/** Harness for interacting with a standard Material date range start input in tests. */
class MatStartDateHarness extends MatDatepickerInputHarnessBase {
    /**
     * Gets a `HarnessPredicate` that can be used to search for a `MatStartDateHarness`
     * that meets certain criteria.
     * @param options Options for filtering which input instances are considered a match.
     * @return a `HarnessPredicate` configured with the given options.
     */
    static with(options = {}) {
        return getInputPredicate(MatStartDateHarness, options);
    }
}
MatStartDateHarness.hostSelector = '.mat-start-date';
/** Harness for interacting with a standard Material date range end input in tests. */
class MatEndDateHarness extends MatDatepickerInputHarnessBase {
    /**
     * Gets a `HarnessPredicate` that can be used to search for a `MatEndDateHarness`
     * that meets certain criteria.
     * @param options Options for filtering which input instances are considered a match.
     * @return a `HarnessPredicate` configured with the given options.
     */
    static with(options = {}) {
        return getInputPredicate(MatEndDateHarness, options);
    }
}
MatEndDateHarness.hostSelector = '.mat-end-date';
/** Harness for interacting with a standard Material date range input in tests. */
class MatDateRangeInputHarness extends DatepickerTriggerHarnessBase {
    /**
     * Gets a `HarnessPredicate` that can be used to search for a `MatDateRangeInputHarness`
     * that meets certain criteria.
     * @param options Options for filtering which input instances are considered a match.
     * @return a `HarnessPredicate` configured with the given options.
     */
    static with(options = {}) {
        return new HarnessPredicate(MatDateRangeInputHarness, options)
            .addOption('value', options.value, (harness, value) => HarnessPredicate.stringMatches(harness.getValue(), value));
    }
    /** Gets the combined value of the start and end inputs, including the separator. */
    getValue() {
        return __awaiter(this, void 0, void 0, function* () {
            const [start, end, separator] = yield parallel(() => [
                this.getStartInput().then(input => input.getValue()),
                this.getEndInput().then(input => input.getValue()),
                this.getSeparator()
            ]);
            return start + `${end ? ` ${separator} ${end}` : ''}`;
        });
    }
    /** Gets the inner start date input inside the range input. */
    getStartInput() {
        return __awaiter(this, void 0, void 0, function* () {
            // Don't pass in filters here since the start input is required and there can only be one.
            return this.locatorFor(MatStartDateHarness)();
        });
    }
    /** Gets the inner start date input inside the range input. */
    getEndInput() {
        return __awaiter(this, void 0, void 0, function* () {
            // Don't pass in filters here since the end input is required and there can only be one.
            return this.locatorFor(MatEndDateHarness)();
        });
    }
    /** Gets the separator text between the values of the two inputs. */
    getSeparator() {
        return __awaiter(this, void 0, void 0, function* () {
            return (yield this.locatorFor('.mat-date-range-input-separator')()).text();
        });
    }
    /** Gets whether the range input is disabled. */
    isDisabled() {
        return __awaiter(this, void 0, void 0, function* () {
            // We consider the input as disabled if both of the sub-inputs are disabled.
            const [startDisabled, endDisabled] = yield parallel(() => [
                this.getStartInput().then(input => input.isDisabled()),
                this.getEndInput().then(input => input.isDisabled())
            ]);
            return startDisabled && endDisabled;
        });
    }
    /** Gets whether the range input is required. */
    isRequired() {
        return __awaiter(this, void 0, void 0, function* () {
            return (yield this.host()).hasClass('mat-date-range-input-required');
        });
    }
    /** Opens the calendar associated with the input. */
    isCalendarOpen() {
        return __awaiter(this, void 0, void 0, function* () {
            // `aria-owns` is set on both inputs only if there's an
            // open range picker so we can use it as an indicator.
            const startHost = yield (yield this.getStartInput()).host();
            return (yield startHost.getAttribute('aria-owns')) != null;
        });
    }
    _openCalendar() {
        return __awaiter(this, void 0, void 0, function* () {
            // Alt + down arrow is the combination for opening the calendar with the keyboard.
            const startHost = yield (yield this.getStartInput()).host();
            return startHost.sendKeys({ alt: true }, TestKey.DOWN_ARROW);
        });
    }
}
MatDateRangeInputHarness.hostSelector = '.mat-date-range-input';

/**
 * @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
 */

/**
 * @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
 */

export { MatCalendarCellHarness, MatCalendarHarness, MatDateRangeInputHarness, MatDatepickerInputHarness, MatDatepickerToggleHarness, MatEndDateHarness, MatStartDateHarness };
//# sourceMappingURL=testing.js.map
