/** * @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.dev/license */ import {HarnessPredicate, parallel, TestKey} from '@angular/cdk/testing'; import {MatDatepickerInputHarnessBase, getInputPredicate} from './datepicker-input-harness-base'; import {DatepickerTriggerHarnessBase} from './datepicker-trigger-harness-base'; import { DatepickerInputHarnessFilters, DateRangeInputHarnessFilters, } from './datepicker-harness-filters'; /** Harness for interacting with a standard Material date range start input in tests. */ export class MatStartDateHarness extends MatDatepickerInputHarnessBase { static hostSelector = '.mat-start-date'; /** * 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: DatepickerInputHarnessFilters = {}): HarnessPredicate { return getInputPredicate(MatStartDateHarness, options); } } /** Harness for interacting with a standard Material date range end input in tests. */ export class MatEndDateHarness extends MatDatepickerInputHarnessBase { static hostSelector = '.mat-end-date'; /** * 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: DatepickerInputHarnessFilters = {}): HarnessPredicate { return getInputPredicate(MatEndDateHarness, options); } } /** Harness for interacting with a standard Material date range input in tests. */ export class MatDateRangeInputHarness extends DatepickerTriggerHarnessBase { static hostSelector = '.mat-date-range-input'; /** * 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: DateRangeInputHarnessFilters = {}, ): HarnessPredicate { 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. */ async getValue(): Promise { const [start, end, separator] = await 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. */ async getStartInput(): Promise { // 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. */ async getEndInput(): Promise { // 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. */ async getSeparator(): Promise { return (await this.locatorFor('.mat-date-range-input-separator')()).text(); } /** Gets whether the range input is disabled. */ async isDisabled(): Promise { // We consider the input as disabled if both of the sub-inputs are disabled. const [startDisabled, endDisabled] = await parallel(() => [ this.getStartInput().then(input => input.isDisabled()), this.getEndInput().then(input => input.isDisabled()), ]); return startDisabled && endDisabled; } /** Gets whether the range input is required. */ async isRequired(): Promise { return (await this.host()).hasClass('mat-date-range-input-required'); } /** Opens the calendar associated with the input. */ async isCalendarOpen(): Promise { // `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 = await (await this.getStartInput()).host(); return (await startHost.getAttribute('aria-owns')) != null; } protected async _openCalendar(): Promise { // Alt + down arrow is the combination for opening the calendar with the keyboard. const startHost = await (await this.getStartInput()).host(); return startHost.sendKeys({alt: true}, TestKey.DOWN_ARROW); } }