import { keyEnter, keyArrowDown, keyArrowUp } from '@ni/fast-web-utilities';
import { listOptionTag } from '../../list-option';
import { waitForUpdatesAsync } from '../../testing/async-helpers';
import { waitForEvent, waitAnimationFrame } from '../../utilities/testing/component';
import { slotTextContent } from '../../utilities/models/slot-text-content';
/**
 * Page object for the `nimble-combobox` component to provide consistent ways
 * of querying and interacting with the component during tests.
 */
export class ComboboxPageObject {
    constructor(comboboxElement) {
        this.comboboxElement = comboboxElement;
        this.regionLoadedListener = waitForEvent(this.comboboxElement, 'loaded');
    }
    /**
     * Gets the selectable options in the drop-down. Does not include options that are disabled or filtered out.
     */
    getFilteredOptions() {
        return this.comboboxElement.filteredOptions.map(x => x.text);
    }
    /**
     * Sets the input text and commits the value by pressing Enter. Will emit a 'change' event.
     */
    async commitValue(text) {
        await this.waitForAnchoredRegionLoaded();
        this.setInputText(text);
        this.pressEnterKey();
    }
    /**
     * Gets the label text of the element
     * @returns The current slotted label text, if any
     */
    getLabelText() {
        const labelSlot = this.comboboxElement.shadowRoot.querySelector('label > slot');
        return slotTextContent(labelSlot);
    }
    /**
     * @internal
     *
     * The Selection API currently isn't supported properly or consistently in shadow DOM,
     * so unfortunately our delete API has to be passed the post-deletion text.
     */
    setInputText(text, asDelete = false) {
        this.comboboxElement.control.value = text;
        const inputEvent = new InputEvent('input', {
            data: text,
            inputType: asDelete ? 'deleteContentForward' : 'insertText'
        });
        this.comboboxElement.control.dispatchEvent(inputEvent);
    }
    /**
     * @internal
     *
     * Either opens or closes the dropdown depending on its current state
     */
    clickCombobox() {
        this.comboboxElement.click();
    }
    /**
     * @internal
     */
    async clickAndWaitForOpen() {
        this.clickCombobox();
        await this.waitForAnchoredRegionLoaded();
        await waitForUpdatesAsync();
        await waitAnimationFrame(); // necessary because scrolling is queued with requestAnimationFrame
    }
    /**
     * @internal
     *
     * Either opens or closes the dropdown depending on its current state
     */
    clickDropdownButton() {
        this.comboboxElement.dropdownButton.control.click();
    }
    /**
     * @internal
     */
    async clickDropdownButtonAndWaitForOpen() {
        this.clickDropdownButton();
        await this.waitForAnchoredRegionLoaded();
        await waitAnimationFrame(); // necessary because scrolling is queued with requestAnimationFrame
    }
    /**
     * @internal
     */
    isDropdownButtonChecked() {
        return this.comboboxElement.dropdownButton.checked;
    }
    /**
     * @internal
     */
    isDropdownButtonDisabled() {
        return this.comboboxElement.dropdownButton.disabled;
    }
    /**
     * @internal
     *
     * Either opens or closes the dropdown depending on its current state
     */
    clickInput() {
        this.comboboxElement.control.click();
    }
    /**
     * @internal
     */
    getInputTitle() {
        return this.comboboxElement.control.getAttribute('title');
    }
    /**
     * @internal
     */
    getInputAriaLabel() {
        return this.comboboxElement.control.getAttribute('aria-label');
    }
    /**
     * @internal
     */
    async mouseoverInput() {
        this.comboboxElement.control.dispatchEvent(new MouseEvent('mouseover'));
        await waitForUpdatesAsync();
    }
    /**
     * @internal
     */
    async mouseoutInput() {
        this.comboboxElement.control.dispatchEvent(new MouseEvent('mouseout'));
        await waitForUpdatesAsync();
    }
    /**
     * @internal
     */
    async prependOption(value, label) {
        this.comboboxElement.insertAdjacentHTML('afterbegin', `<${listOptionTag} value="${value}">${label}</${listOptionTag}>`);
        await waitForUpdatesAsync();
    }
    /**
     * @internal
     */
    async clickAway() {
        this.comboboxElement.dispatchEvent(new Event('focusout'));
        await waitForUpdatesAsync();
    }
    /**
     * @internal
     */
    pressEnterKey() {
        this.comboboxElement.dispatchEvent(new KeyboardEvent('keydown', { key: keyEnter }));
    }
    /**
     * @internal
     */
    pressArrowDownKey() {
        this.comboboxElement.dispatchEvent(new KeyboardEvent('keydown', { key: keyArrowDown }));
    }
    /**
     * @internal
     */
    pressArrowUpKey() {
        this.comboboxElement.dispatchEvent(new KeyboardEvent('keydown', { key: keyArrowUp }));
    }
    /**
     * @internal
     */
    hideAllOptions() {
        this.comboboxElement.options.forEach(o => {
            o.hidden = true;
        });
        this.comboboxElement.filterOptions();
    }
    /**
     * @internal
     */
    isNoResultsLabelVisible() {
        return (this.comboboxElement.shadowRoot?.querySelector('.no-results-label') !== null);
    }
    async waitForAnchoredRegionLoaded() {
        await this.regionLoadedListener;
    }
}
//# sourceMappingURL=combobox.pageobject.js.map