{"version":3,"file":"ngx-speculoos.mjs","sources":["../../../projects/ngx-speculoos/src/lib/test-element.ts","../../../projects/ngx-speculoos/src/lib/test-html-element.ts","../../../projects/ngx-speculoos/src/lib/test-button.ts","../../../projects/ngx-speculoos/src/lib/test-select.ts","../../../projects/ngx-speculoos/src/lib/test-textarea.ts","../../../projects/ngx-speculoos/src/lib/test-input.ts","../../../projects/ngx-speculoos/src/lib/test-element-querier.ts","../../../projects/ngx-speculoos/src/lib/component-tester.ts","../../../projects/ngx-speculoos/src/lib/routing-tester.ts","../../../projects/ngx-speculoos/src/lib/route.ts","../../../projects/ngx-speculoos/src/lib/matchers.ts","../../../projects/ngx-speculoos/src/lib/mock.ts","../../../projects/ngx-speculoos/src/lib/providers.ts","../../../projects/ngx-speculoos/src/public_api.ts","../../../projects/ngx-speculoos/src/ngx-speculoos.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-unused-vars */\n/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { ComponentTester } from './component-tester';\nimport { TestButton } from './test-button';\nimport { TestSelect } from './test-select';\nimport { TestTextArea } from './test-textarea';\nimport { TestInput } from './test-input';\nimport { TestElementQuerier } from './test-element-querier';\nimport { DebugElement, ProviderToken, Type } from '@angular/core';\nimport { TestHtmlElement } from './test-html-element';\n\n/**\n * A wrapped DOM element, providing additional methods and attributes helping with writing tests\n */\nexport class TestElement<E extends Element = Element> {\n  private querier: TestElementQuerier;\n\n  constructor(\n    protected tester: ComponentTester<unknown>,\n    /**\n     * the wrapped debug element\n     */\n    readonly debugElement: DebugElement\n  ) {\n    this.querier = new TestElementQuerier(tester, debugElement);\n  }\n\n  get nativeElement(): E {\n    return this.debugElement.nativeElement;\n  }\n\n  /**\n   * the text content of this element\n   */\n  get textContent(): string | null {\n    return this.nativeElement.textContent;\n  }\n\n  /**\n   * dispatches an event of the given type from the wrapped element, then triggers a change detection\n   */\n  async dispatchEventOfType(type: string): Promise<void> {\n    this.nativeElement.dispatchEvent(new Event(type));\n    await this.tester.change();\n  }\n\n  /**\n   * dispatches the given event from the wrapped element, then triggers a change detection\n   */\n  async dispatchEvent(event: Event): Promise<void> {\n    this.nativeElement.dispatchEvent(event);\n    await this.tester.change();\n  }\n\n  /**\n   * Gets the CSS classes of the wrapped element, as an array\n   */\n  get classes(): Array<string> {\n    return Array.prototype.slice.call(this.nativeElement.classList);\n  }\n\n  /**\n   * Gets the attribute of the wrapped element with the given name\n   * @param name the name of the attribute to get\n   */\n  attr(name: string): string | null {\n    return this.nativeElement.getAttribute(name);\n  }\n\n  /**\n   * Gets the first element matching the given CSS selector and wraps it into a TestElement. The actual type\n   * of the returned value is the TestElement subclass matching the type of the found element. So, if the\n   * matched element is an input for example, the method will return a TestInput.\n   * <p>Usage:</p>\n   * <code>\n   * const testElement: TestHtmlElement&lt;HTMLDivElement> | null = tester.element('div');\n   * </code>\n   * @param selector a CSS selector\n   * @returns the wrapped element, or null if no element matches the selector.\n   */\n  element<K extends keyof HTMLElementTagNameMap>(selector: K): TestHtmlElement<HTMLElementTagNameMap[K]> | null;\n  /**\n   * Gets the first element matching the given CSS selector and wraps it into a TestElement. The actual type\n   * of the returned value is the TestElement subclass matching the type of the found element. So, if the\n   * matched element is an input for example, the method will return a TestInput.\n   * <p>Usage:</p>\n   * <code>\n   * const testElement: TestElement&lt;SVGLineElement> | null = tester.element('line');\n   * </code>\n   * @param selector a CSS selector\n   * @returns the wrapped element, or null if no element matches the selector.\n   */\n  element<K extends keyof SVGElementTagNameMap>(selector: K): TestElement<SVGElementTagNameMap[K]> | null;\n  /**\n   * Gets the first element matching the given CSS selector and wraps it into a TestElement. The actual type\n   * of the returned value is the TestElement subclass matching the type of the found element. So, if the\n   * matched element is an input for example, the method will return a TestInput.\n   * <p>Usage:</p>\n   * <code>\n   * const testElement: TestElement | null = tester.element('.selector');\n   * </code>\n   * @param selector a CSS or directive selector\n   * @returns the wrapped element, or null if no element matches the selector.\n   */\n  element(selector: string | Type<any>): TestElement | null;\n  /**\n   * Gets the first element matching the given selector and wraps it into a TestElement. The actual type\n   * of the returned value is the TestElement subclass matching the type of the found element. So, if the\n   * matched element is an input for example, the method will return a TestInput.\n   * <p>Usage:</p>\n   * <code>\n   * const testElement: TestInput | null = tester.element&lt;HTMLInputElement>('.selector');\n   * </code>\n   * @param selector a CSS or directive selector\n   * @returns the wrapped element, or null if no element matches the selector.\n   */\n  element<T extends HTMLInputElement>(selector: string | Type<any>): TestInput | null;\n  /**\n   * Gets the first element matching the given selector and wraps it into a TestElement. The actual type\n   * of the returned value is the TestElement subclass matching the type of the found element. So, if the\n   * matched element is an input for example, the method will return a TestInput.\n   * <p>Usage:</p>\n   * <code>\n   * const testElement: TestTextArea | null = tester.element&lt;HTMLTextAreaElement>('.selector');\n   * </code>\n   * @param selector a CSS or directive selector\n   * @returns the wrapped element, or null if no element matches the selector.\n   */\n  element<T extends HTMLTextAreaElement>(selector: string | Type<any>): TestTextArea | null;\n  /**\n   * Gets the first element matching the given selector and wraps it into a TestElement. The actual type\n   * of the returned value is the TestElement subclass matching the type of the found element. So, if the\n   * matched element is an input for example, the method will return a TestInput.\n   * <p>Usage:</p>\n   * <code>\n   * const testElement: TestSelect | null = tester.element&lt;HTMLSelectElement>('.selector');\n   * </code>\n   * @param selector a CSS or directive selector\n   * @returns the wrapped element, or null if no element matches the selector.\n   */\n  element<T extends HTMLSelectElement>(selector: string | Type<any>): TestSelect | null;\n  /**\n   * Gets the first element matching the given selector and wraps it into a TestElement. The actual type\n   * of the returned value is the TestElement subclass matching the type of the found element. So, if the\n   * matched element is an input for example, the method will return a TestInput.\n   * <p>Usage:</p>\n   * <code>\n   * const testElement: TestButton | null = tester.element&lt;HTMLButtonElement>('.selector');\n   * </code>\n   * @param selector a CSS or directive selector\n   * @returns the wrapped element, or null if no element matches the selector.\n   */\n  element<T extends HTMLButtonElement>(selector: string | Type<any>): TestButton | null;\n  /**\n   * Gets the first element matching the given selector and wraps it into a TestElement. The actual type\n   * of the returned value is the TestElement subclass matching the type of the found element. So, if the\n   * matched element is an input for example, the method will return a TestInput.\n   * <p>Usage:</p>\n   * <code>\n   * const testElement: TestHtmlElement&lt;HTMLDivElement> | null = tester.element&lt;HTMLDivElement>('.selector');\n   * </code>\n   * @param selector a CSS or directive selector\n   * @returns the wrapped element, or null if no element matches the selector.\n   */\n  element<T extends HTMLElement>(selector: string | Type<any>): TestHtmlElement<T> | null;\n  /**\n   * Gets the first element matching the given selector and wraps it into a TestElement. The actual type\n   * of the returned value is the TestElement subclass matching the type of the found element. So, if the\n   * matched element is an input for example, the method will return a TestInput.\n   * <p>Usage:</p>\n   * <code>\n   * const testElement: TestElement&lt;SVGLineElement> | null = tester.element&lt;SVGLineElement>('.selector');\n   * </code>\n   * @param selector a CSS or directive selector\n   * @returns the wrapped element, or null if no element matches the selector.\n   */\n  element<T extends Element>(selector: string | Type<any>): TestElement<T> | null;\n  element(selector: string | Type<any>): TestElement | null {\n    return this.querier.element(selector);\n  }\n\n  /**\n   * Gets all the elements matching the given CSS selector and wraps them into a TestElement. The actual type\n   * of the returned elements is the TestElement subclass matching the type of the found element. So, if the\n   * matched elements are inputs for example, the method will return an array of TestInput.\n   * <p>Usage:</p>\n   * <code>\n   * const testElements: Array&lt;TestHtmlElement&lt;HTMLDivElement>> = tester.elements('div');\n   * </code>\n   * @param selector a CSS selector\n   * @returns the array of matched elements, empty if no element was matched\n   */\n  elements<K extends keyof HTMLElementTagNameMap>(selector: K): Array<TestHtmlElement<HTMLElementTagNameMap[K]>>;\n  /**\n   * Gets all the elements matching the given CSS selector and wraps them into a TestElement. The actual type\n   * of the returned elements is the TestElement subclass matching the type of the found element. So, if the\n   * matched elements are inputs for example, the method will return an array of TestInput.\n   * <p>Usage:</p>\n   * <code>\n   * const testElements: Array&lt;TestElement&lt;SVGLineElement>> = tester.elements('line');\n   * </code>\n   * @param selector a CSS selector\n   * @returns the array of matched elements, empty if no element was matched\n   */\n  elements<K extends keyof SVGElementTagNameMap>(selector: K): Array<TestElement<SVGElementTagNameMap[K]>>;\n  /**\n   * Gets all the elements matching the given selector and wraps them into a TestElement. The actual type\n   * of the returned elements is the TestElement subclass matching the type of the found element. So, if the\n   * matched elements are inputs for example, the method will return an array of TestInput.\n   * <p>Usage:</p>\n   * <code>\n   * const testElements: Array&lt;TestElement> = tester.elements('.selector');\n   * </code>\n   * @param selector a CSS or directive selector\n   * @returns the array of matched elements, empty if no element was matched\n   */\n  elements(selector: string | Type<any>): Array<TestElement>;\n  /**\n   * Gets all the elements matching the given selector and wraps them into a TestElement. The actual type\n   * of the returned elements is the TestElement subclass matching the type of the found element. So, if the\n   * matched elements are inputs for example, the method will return an array of TestInput.\n   * <p>Usage:</p>\n   * <code>\n   * const testElements: Array&lt;TestInput> = tester.elements&lt;HTMLInputElement>('.selector');\n   * </code>\n   * @param selector a CSS or directive selector\n   * @returns the array of matched elements, empty if no element was matched\n   */\n  elements<T extends HTMLInputElement>(selector: string | Type<any>): Array<TestInput>;\n  /**\n   * Gets all the elements matching the given selector and wraps them into a TestElement. The actual type\n   * of the returned elements is the TestElement subclass matching the type of the found element. So, if the\n   * matched elements are inputs for example, the method will return an array of TestInput.\n   * <p>Usage:</p>\n   * <code>\n   * const testElements: Array&lt;TestTextArea> = tester.elements&lt;HTMLTextAreaElement>('.selector');\n   * </code>\n   * @param selector a CSS or directive selector\n   * @returns the array of matched elements, empty if no element was matched\n   */\n  elements<T extends HTMLTextAreaElement>(selector: string | Type<any>): Array<TestTextArea>;\n  /**\n   * Gets all the elements matching the given CSS selector and wraps them into a TestElement. The actual type\n   * of the returned elements is the TestElement subclass matching the type of the found element. So, if the\n   * matched elements are inputs for example, the method will return an array of TestInput.\n   * <p>Usage:</p>\n   * <code>\n   * const testElements: Array&lt;TestButton> = tester.elements&lt;HTMLButtonElement>('.selector');\n   * </code>\n   * @param selector a CSS or directive selector\n   * @returns the array of matched elements, empty if no element was matched\n   */\n  elements<T extends HTMLButtonElement>(selector: string | Type<any>): Array<TestButton>;\n  /**\n   * Gets all the elements matching the given selector and wraps them into a TestElement. The actual type\n   * of the returned elements is the TestElement subclass matching the type of the found element. So, if the\n   * matched elements are inputs for example, the method will return an array of TestInput.\n   * <p>Usage:</p>\n   * <code>\n   * const testElements: Array&lt;TestSelect> = tester.elements<HTMLSelectElement>('.selector');\n   * </code>\n   * @param selector a CSS or directive selector\n   * @returns the array of matched elements, empty if no element was matched\n   */\n  elements<T extends HTMLSelectElement>(selector: string | Type<any>): Array<TestSelect>;\n  /**\n   * Gets all the elements matching the given selector and wraps them into a TestElement. The actual type\n   * of the returned elements is the TestElement subclass matching the type of the found element. So, if the\n   * matched elements are inputs for example, the method will return an array of TestInput.\n   * <p>Usage:</p>\n   * <code>\n   * const testElements: Array&lt;TestHtmlElement&lt;HTMLDivElement>> = tester.elements&lt;HTMLDivElement>('.selector');\n   * </code>\n   * @param selector a CSS or directive selector\n   * @returns the array of matched elements, empty if no element was matched\n   */\n  elements<T extends HTMLElement>(selector: string | Type<any>): Array<TestHtmlElement<T>>;\n  /**\n   * Gets all the elements matching the given selector and wraps them into a TestElement. The actual type\n   * of the returned elements is the TestElement subclass matching the type of the found element. So, if the\n   * matched elements are inputs for example, the method will return an array of TestInput.\n   * <p>Usage:</p>\n   * <code>\n   * const testElements: Array&lt;TestElement&lt;SVGLineElement>> = tester.elements&lt;SVGLineElement>('.selector');\n   * </code>\n   * @param selector a CSS or directive selector\n   * @returns the array of matched elements, empty if no element was matched\n   */\n  elements<T extends Element>(selector: string | Type<any>): Array<TestElement<T>>;\n  elements(selector: string | Type<any>): Array<TestElement> {\n    return this.querier.elements(selector);\n  }\n\n  /**\n   * Gets the first input matched by the given selector. Throws an Error if the matched element isn't actually an input.\n   * @param selector a CSS or directive selector\n   * @returns the wrapped input, or null if no element was matched\n   */\n  input(selector: string | Type<any>): TestInput | null {\n    return this.querier.input(selector);\n  }\n\n  /**\n   * Gets the first select matched by the given selector. Throws an Error if the matched element isn't actually a select.\n   * @param selector a CSS or directive selector\n   * @returns the wrapped select, or null if no element was matched\n   */\n  select(selector: string | Type<any>): TestSelect | null {\n    return this.querier.select(selector);\n  }\n\n  /**\n   * Gets the first textarea matched by the given selector\n   * @param selector a CSS or directive selector\n   * @returns the wrapped textarea, or null if no element was matched. Throws an Error if the matched element isn't actually a textarea.\n   * @throws {Error} if the matched element isn't actually a textarea\n   */\n  textarea(selector: string | Type<any>): TestTextArea | null {\n    return this.querier.textarea(selector);\n  }\n\n  /**\n   * Gets the first button matched by the given selector. Throws an Error if the matched element isn't actually a button.\n   * @param selector a CSS or directive selector\n   * @returns the wrapped button, or null if no element was matched\n   */\n  button(selector: string | Type<any>): TestButton | null {\n    return this.querier.button(selector);\n  }\n\n  /**\n   * Gets the first directive matching the given component directive selector and returns its component instance\n   * @param selector the selector of a component directive\n   */\n  component<R>(selector: Type<R>): R {\n    return this.querier.element(selector)?.debugElement?.componentInstance ?? null;\n  }\n\n  /**\n   * Gets the directives matching the given component directive selector and returns their component instance\n   * @param selector the selector of a component directive\n   */\n  components<R>(selector: Type<R>): Array<R> {\n    return this.querier.elements(selector).map(e => e.debugElement.componentInstance);\n  }\n\n  /**\n   * Gets the first element matching the given selector, then gets the given token from its injector, or null if there is no such token\n   * @param selector a CSS or directive selector\n   * @param token the token to get from the matched element injector\n   */\n  token<R>(selector: string | Type<any>, token: ProviderToken<R>): R | null {\n    return this.querier.element(selector)?.debugElement?.injector?.get(token, null) ?? null;\n  }\n\n  /**\n   * Gets the elements matching the given selector, then gets their given token from their injector, or null if there is no such token\n   * @param selector a CSS or directive selector\n   * @param token the token to get from the matched element injector\n   */\n  tokens<R>(selector: string | Type<any>, token: ProviderToken<R>): Array<R | null> {\n    return this.querier.elements(selector).map(e => e.debugElement.injector.get(token, null) ?? null);\n  }\n\n  /**\n   * Gets the element matching the given selector, and if found, creates and returns a custom TestElement of the provided\n   * type. This is useful to create custom higher-level abstractions similar to TestInput, TestSelect, etc. for\n   * custom elements or components.\n   * @param selector a CSS or directive selector\n   * @param customTestElementType the type of the TestElement subclass that will wrap the found element\n   */\n  custom<E extends TestElement>(selector: string | Type<any>, customTestElementType: Type<E>): E | null {\n    const element = this.querier.element(selector);\n    return element && new customTestElementType(this.tester, element.debugElement);\n  }\n\n  /**\n   * Gets the elements matching the given selector, and creates and returns custom TestElements of the provided\n   * type. This is useful to create custom higher-level abstractions similar to TestInput, TestSelect, etc. for\n   * custom elements or components.\n   * @param selector a CSS or directive selector\n   * @param customTestElementType the type of the TestElement subclass that will wrap the found elements\n   */\n  customs<E extends TestElement>(selector: string | Type<any>, customTestElementType: Type<E>): Array<E> {\n    return this.querier.elements(selector).map(element => new customTestElementType(this.tester, element.debugElement));\n  }\n}\n","import { ComponentTester } from './component-tester';\nimport { TestElement } from './test-element';\nimport { DebugElement } from '@angular/core';\n\n/**\n * A wrapped DOM HTML element, providing additional methods and attributes helping with writing tests\n */\nexport class TestHtmlElement<E extends HTMLElement> extends TestElement<E> {\n  constructor(tester: ComponentTester<unknown>, debugElement: DebugElement) {\n    super(tester, debugElement);\n  }\n\n  /**\n   * Clicks on the wrapped element, then triggers a change detection\n   */\n  async click(): Promise<void> {\n    this.nativeElement.click();\n    await this.tester.change();\n  }\n\n  /**\n   * Tests if the element is visible, in the same meaning (and implementation) as in jQuery, i.e.\n   * present anywhere in the DOM, and visible.\n   * An element is not visible typically, if its display style or any of its ancestors display style is none.\n   */\n  get visible(): boolean {\n    return !!(this.nativeElement.offsetWidth || this.nativeElement.offsetHeight || this.nativeElement.getClientRects().length);\n  }\n}\n","import { ComponentTester } from './component-tester';\nimport { TestHtmlElement } from './test-html-element';\nimport { DebugElement } from '@angular/core';\n\n/**\n * A wrapped button element, providing additional methods and attributes helping with writing tests\n */\nexport class TestButton extends TestHtmlElement<HTMLButtonElement> {\n  constructor(tester: ComponentTester<unknown>, debugElement: DebugElement) {\n    super(tester, debugElement);\n  }\n\n  /**\n   * the disabled flag of the button\n   */\n  get disabled(): boolean {\n    return this.nativeElement.disabled;\n  }\n}\n","import { ComponentTester } from './component-tester';\nimport { TestHtmlElement } from './test-html-element';\nimport { DebugElement } from '@angular/core';\n\n/**\n * A wrapped DOM HTML select element, providing additional methods and attributes helping with writing tests\n */\nexport class TestSelect extends TestHtmlElement<HTMLSelectElement> {\n  constructor(tester: ComponentTester<unknown>, debugElement: DebugElement) {\n    super(tester, debugElement);\n  }\n\n  /**\n   * Selects the option at the given index, then dispatches an event of type change and triggers a change detection.\n   * If the index is out of bounds and is not -1, then throws an error.\n   */\n  selectIndex(index: number): Promise<void> {\n    if (index < -1 || index >= this.nativeElement.options.length) {\n      throw new Error(`The index ${index} is out of bounds`);\n    }\n    this.nativeElement.selectedIndex = index;\n    return this.dispatchEventOfType('change');\n  }\n\n  /**\n   * Selects the first option with the given value, then dispatches an event of type change and triggers a change detection.\n   * If there is no option with the given value, then throws an error.\n   */\n  selectValue(value: string): Promise<void> {\n    const index = this.optionValues.indexOf(value);\n    if (index >= 0) {\n      return this.selectIndex(index);\n    } else {\n      throw new Error(`The value ${value} is not part of the option values (${this.optionValues.join(', ')})`);\n    }\n  }\n\n  /**\n   * Selects the first option with the given label (or text), then dispatches an event of type change and triggers a change detection.\n   * If there is no option with the given label, then throws an error.\n   */\n  selectLabel(label: string): Promise<void> {\n    const index = this.optionLabels.indexOf(label);\n    if (index >= 0) {\n      return this.selectIndex(index);\n    } else {\n      throw new Error(`The label ${label} is not part of the option labels (${this.optionLabels.join(', ')})`);\n    }\n  }\n\n  /**\n   * the selected index of the wrapped select\n   */\n  get selectedIndex(): number {\n    return this.nativeElement.selectedIndex;\n  }\n\n  /**\n   * the value of the selected option of the wrapped select, or null if there is no selected option\n   */\n  get selectedValue(): string | null {\n    if (this.selectedIndex < 0) {\n      return null;\n    }\n    return this.nativeElement.options[this.selectedIndex].value;\n  }\n\n  /**\n   * the label (or text if no label) of the selected option of the wrapped select, or null if there is no selected option\n   */\n  get selectedLabel(): string | null {\n    if (this.selectedIndex < 0) {\n      return null;\n    }\n    return this.nativeElement.options[this.selectedIndex].label;\n  }\n\n  /**\n   * the values of the options, as an array\n   */\n  get optionValues(): Array<string> {\n    return (Array.prototype.slice.call(this.nativeElement.options) as Array<HTMLOptionElement>).map(option => option.value);\n  }\n\n  /**\n   * the labels (or texts if no label) of the options, as an array\n   */\n  get optionLabels(): Array<string> {\n    return (Array.prototype.slice.call(this.nativeElement.options) as Array<HTMLOptionElement>).map(option => option.label);\n  }\n\n  /**\n   * the number of options in the select\n   */\n  get size(): number {\n    return this.nativeElement.options.length;\n  }\n\n  /**\n   * the disabled property of the wrapped select\n   */\n  get disabled(): boolean {\n    return this.nativeElement.disabled;\n  }\n}\n","import { ComponentTester } from './component-tester';\nimport { TestHtmlElement } from './test-html-element';\nimport { DebugElement } from '@angular/core';\n\n/**\n * A wrapped DOM HTML textarea element, providing additional methods and attributes helping with writing tests\n */\nexport class TestTextArea extends TestHtmlElement<HTMLTextAreaElement> {\n  constructor(tester: ComponentTester<unknown>, debugElement: DebugElement) {\n    super(tester, debugElement);\n  }\n\n  /**\n   * Sets the value of the wrapped textarea, then dispatches an event of type input and triggers a change detection\n   * @param value the new value of the textarea\n   */\n  async fillWith(value: string): Promise<void> {\n    this.nativeElement.value = value;\n    await this.dispatchEventOfType('input');\n  }\n\n  /**\n   * the value of the wrapped textarea\n   */\n  get value(): string {\n    return this.nativeElement.value;\n  }\n\n  /**\n   * the disabled property of the wrapped textarea\n   */\n  get disabled(): boolean {\n    return this.nativeElement.disabled;\n  }\n}\n","import { ComponentTester } from './component-tester';\nimport { TestHtmlElement } from './test-html-element';\nimport { DebugElement } from '@angular/core';\n\n/**\n * A wrapped DOM HTML input element, providing additional methods and attributes helping with writing tests\n */\nexport class TestInput extends TestHtmlElement<HTMLInputElement> {\n  constructor(tester: ComponentTester<unknown>, debugElement: DebugElement) {\n    super(tester, debugElement);\n  }\n\n  /**\n   * Sets the value of the wrapped input, then dispatches an event of type input and triggers a change detection\n   * @param value the new value of the input\n   */\n  async fillWith(value: string): Promise<void> {\n    this.nativeElement.value = value;\n    await this.dispatchEventOfType('input');\n  }\n\n  /**\n   * the value of the wrapped input\n   */\n  get value(): string {\n    return this.nativeElement.value;\n  }\n\n  /**\n   * the checked property of the wrapped input\n   */\n  get checked(): boolean {\n    return this.nativeElement.checked;\n  }\n\n  /**\n   * the disabled property of the wrapped input\n   */\n  get disabled(): boolean {\n    return this.nativeElement.disabled;\n  }\n\n  /**\n   * Checks the wrapped input, then dispatches an event of type change and triggers a change detection\n   */\n  async check(): Promise<void> {\n    this.nativeElement.checked = true;\n    await this.dispatchEventOfType('change');\n  }\n\n  /**\n   * Unchecks the wrapped input, then dispatches an event of type change and triggers a change detection\n   */\n  async uncheck(): Promise<void> {\n    this.nativeElement.checked = false;\n    await this.dispatchEventOfType('change');\n  }\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { TestButton } from './test-button';\nimport { TestSelect } from './test-select';\nimport { TestElement } from './test-element';\nimport { TestTextArea } from './test-textarea';\nimport { TestInput } from './test-input';\nimport { TestHtmlElement } from './test-html-element';\nimport { ComponentTester } from './component-tester';\nimport { DebugElement, Type } from '@angular/core';\nimport { By } from '@angular/platform-browser';\n\n/**\n * @internal\n */\nexport class TestElementQuerier {\n  constructor(\n    private tester: ComponentTester<unknown>,\n    private root: DebugElement\n  ) {}\n\n  static wrap(childDebugElement: DebugElement, tester: ComponentTester<unknown>): TestElement {\n    const childElement = childDebugElement.nativeElement;\n    if (childElement instanceof HTMLButtonElement) {\n      return new TestButton(tester, childDebugElement);\n    } else if (childElement instanceof HTMLInputElement) {\n      return new TestInput(tester, childDebugElement);\n    } else if (childElement instanceof HTMLSelectElement) {\n      return new TestSelect(tester, childDebugElement);\n    } else if (childElement instanceof HTMLTextAreaElement) {\n      return new TestTextArea(tester, childDebugElement);\n    } else if (childElement instanceof HTMLElement) {\n      return new TestHtmlElement(tester, childDebugElement);\n    } else {\n      return new TestElement(tester, childDebugElement);\n    }\n  }\n\n  /**\n   * Gets the first element matching the given selector and wraps it into a TestElement. The actual type\n   * of the returned value is the TestElement subclass matching the type of the found element. So, if the\n   * matched element is an input for example, the method will return a TestInput. You can thus use\n   * `tester.element('#some-input') as TestInput`.\n   * @param selector a CSS or directive selector\n   * @returns the wrapped element, or null if no element matches the selector.\n   */\n  element(selector: string | Type<any>): TestElement | null {\n    const childElement = this.query(selector);\n    return childElement && TestElementQuerier.wrap(childElement, this.tester);\n  }\n\n  /**\n   * Gets all the elements matching the given selector and wraps them into a TestElement. The actual type\n   * of the returned elements is the TestElement subclass matching the type of the found element. So, if the\n   * matched elements are inputs for example, the method will return an array of TestInput. You can thus use\n   * `tester.elements('input') as Array<TestInput>`.\n   * @param selector a CSS or directive selector\n   * @returns the array of matched elements, empty if no element was matched\n   */\n  elements(selector: string | Type<any>): Array<TestElement> {\n    const childElements = this.queryAll(selector);\n    return childElements.map(debugElement => TestElementQuerier.wrap(debugElement, this.tester));\n  }\n\n  /**\n   * Gets the first input matched by the given selector. Throws an Error if the matched element isn't actually an input.\n   * @param selector a CSS or directive selector\n   * @returns the wrapped input, or null if no element was matched\n   */\n  input(selector: string | Type<any>): TestInput | null {\n    const childElement = this.query(selector);\n    if (!childElement) {\n      return null;\n    } else if (!(childElement.nativeElement instanceof HTMLInputElement)) {\n      throw new Error(`Element with selector ${selector} is not an HTMLInputElement`);\n    }\n    return new TestInput(this.tester, childElement);\n  }\n\n  /**\n   * Gets the first select matched by the given selector. Throws an Error if the matched element isn't actually a select.\n   * @param selector a CSS or directive selector\n   * @returns the wrapped select, or null if no element was matched\n   */\n  select(selector: string | Type<any>): TestSelect | null {\n    const childElement = this.query(selector);\n    if (!childElement) {\n      return null;\n    } else if (!(childElement.nativeElement instanceof HTMLSelectElement)) {\n      throw new Error(`Element with selector ${selector} is not an HTMLSelectElement`);\n    }\n    return new TestSelect(this.tester, childElement);\n  }\n\n  /**\n   * Gets the first textarea matched by the given selector\n   * @param selector a CSS or directive selector\n   * @returns the wrapped textarea, or null if no element was matched. Throws an Error if the matched element isn't actually a textarea.\n   * @throws {Error} if the matched element isn't actually a textarea\n   */\n  textarea(selector: string | Type<any>): TestTextArea | null {\n    const childElement = this.query(selector);\n    if (!childElement) {\n      return null;\n    } else if (!(childElement.nativeElement instanceof HTMLTextAreaElement)) {\n      throw new Error(`Element with selector ${selector} is not an HTMLTextAreaElement`);\n    }\n    return new TestTextArea(this.tester, childElement);\n  }\n\n  /**\n   * Gets the first button matched by the given selector. Throws an Error if the matched element isn't actually a button.\n   * @param selector a CSS or directive selector\n   * @returns the wrapped button, or null if no element was matched\n   */\n  button(selector: string | Type<any>): TestButton | null {\n    const childElement = this.query(selector);\n    if (!childElement) {\n      return null;\n    } else if (!(childElement.nativeElement instanceof HTMLButtonElement)) {\n      throw new Error(`Element with selector ${selector} is not an HTMLButtonElement`);\n    }\n    return new TestButton(this.tester, childElement);\n  }\n\n  private query(selector: string | Type<any>): DebugElement | null {\n    if (typeof selector === 'string') {\n      return this.root.query(By.css(selector));\n    } else {\n      return this.root.query(By.directive(selector));\n    }\n  }\n\n  private queryAll(selector: string | Type<any>): Array<DebugElement> {\n    if (typeof selector === 'string') {\n      return this.root.queryAll(By.css(selector));\n    } else {\n      return this.root.queryAll(By.directive(selector));\n    }\n  }\n}\n","/* eslint-disable @typescript-eslint/no-unused-vars */\n/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { ComponentFixture, ComponentFixtureAutoDetect, TestBed } from '@angular/core/testing';\nimport { DebugElement, NgZone, ProviderToken, Type } from '@angular/core';\nimport { TestTextArea } from './test-textarea';\nimport { TestElement } from './test-element';\nimport { TestInput } from './test-input';\nimport { TestSelect } from './test-select';\nimport { TestButton } from './test-button';\nimport { TestElementQuerier } from './test-element-querier';\nimport { TestHtmlElement } from './test-html-element';\n\n/**\n * The main entry point of the API. It wraps an Angular ComponentFixture<T>, and gives access to its\n * most used properties and methods. It also allows getting elements wrapped in TestElement (and its subclasses)\n * @param <C> the type of the component to test\n */\nexport class ComponentTester<C> {\n  /**\n   * The test element of the component\n   */\n  readonly testElement: TestElement<HTMLElement>;\n\n  /**\n   * The component fixture of the component\n   */\n  readonly fixture: ComponentFixture<C>;\n\n  /**\n   * The mode used by the ComponentTester\n   */\n  readonly mode: 'imperative' | 'automatic';\n\n  /**\n   * Creates a component fixture of the given type with the TestBed and wraps it into a ComponentTester\n   */\n  static create<C>(componentType: Type<C>): ComponentTester<C> {\n    const fixture = TestBed.createComponent(componentType);\n    return new ComponentTester(fixture);\n  }\n\n  /**\n   * Creates a ComponentFixture for the given component type using the TestBed, and creates a ComponentTester\n   * wrapping (and delegating) to this fixture. If a fixture is passed, then delegates to this fixture directly.\n   *\n   * Note that no `detectChanges()` call is made by this constructor. It's up to the subclass constructor,\n   * or to the user of the created ComponentTester, to call `detectChanges()` at least once to trigger change\n   * detection. This is necessary because some component templates can only be evaluated once inputs\n   * have been set on the component instance.\n   *\n   * @param arg the type of the component to wrap, or a component fixture to wrap\n   */\n  constructor(arg: Type<C> | ComponentFixture<C>) {\n    this.fixture = arg instanceof ComponentFixture ? arg : TestBed.createComponent(arg);\n    const autoDetect = TestBed.inject(ComponentFixtureAutoDetect, false);\n    const zoneless = !(TestBed.inject(NgZone) instanceof NgZone);\n    this.testElement = TestElementQuerier.wrap(this.debugElement, this) as TestElement<HTMLElement>;\n    this.mode = autoDetect || zoneless ? 'automatic' : 'imperative';\n  }\n\n  /**\n   * The native DOM host element of the component\n   */\n  get nativeElement(): HTMLElement {\n    return this.fixture.nativeElement;\n  }\n\n  /**\n   * Gets the instance of the tested component from the wrapped fixture\n   */\n  get componentInstance(): C {\n    return this.fixture.componentInstance;\n  }\n\n  /**\n   * Gets the debug element from the wrapped fixture\n   */\n  get debugElement(): DebugElement {\n    return this.fixture.debugElement;\n  }\n\n  /**\n   * Gets the first element matching the given CSS selector and wraps it into a TestElement. The actual type\n   * of the returned value is the TestElement subclass matching the type of the found element. So, if the\n   * matched element is an input for example, the method will return a TestInput.\n   * <p>Usage:</p>\n   * <code>\n   * const testElement: TestHtmlElement&lt;HTMLDivElement> | null = tester.element('div');\n   * </code>\n   * @param selector a CSS selector\n   * @returns the wrapped element, or null if no element matches the selector.\n   */\n  element<K extends keyof HTMLElementTagNameMap>(selector: K): TestHtmlElement<HTMLElementTagNameMap[K]> | null;\n  /**\n   * Gets the first element matching the given CSS selector and wraps it into a TestElement. The actual type\n   * of the returned value is the TestElement subclass matching the type of the found element. So, if the\n   * matched element is an input for example, the method will return a TestInput.\n   * <p>Usage:</p>\n   * <code>\n   * const testElement: TestElement&lt;SVGLineElement> | null = tester.element('line');\n   * </code>\n   * @param selector a CSS selector\n   * @returns the wrapped element, or null if no element matches the selector.\n   */\n  element<K extends keyof SVGElementTagNameMap>(selector: K): TestElement<SVGElementTagNameMap[K]> | null;\n  /**\n   * Gets the first element matching the given CSS selector and wraps it into a TestElement. The actual type\n   * of the returned value is the TestElement subclass matching the type of the found element. So, if the\n   * matched element is an input for example, the method will return a TestInput.\n   * <p>Usage:</p>\n   * <code>\n   * const testElement: TestElement | null = tester.element('.selector');\n   * </code>\n   * @param selector a CSS or directive selector\n   * @returns the wrapped element, or null if no element matches the selector.\n   */\n  element(selector: string | Type<any>): TestElement | null;\n  /**\n   * Gets the first element matching the given selector and wraps it into a TestElement. The actual type\n   * of the returned value is the TestElement subclass matching the type of the found element. So, if the\n   * matched element is an input for example, the method will return a TestInput.\n   * <p>Usage:</p>\n   * <code>\n   * const testElement: TestInput | null = tester.element&lt;HTMLInputElement>('.selector');\n   * </code>\n   * @param selector a CSS or directive selector\n   * @returns the wrapped element, or null if no element matches the selector.\n   */\n  element<T extends HTMLInputElement>(selector: string | Type<any>): TestInput | null;\n  /**\n   * Gets the first element matching the given selector and wraps it into a TestElement. The actual type\n   * of the returned value is the TestElement subclass matching the type of the found element. So, if the\n   * matched element is an input for example, the method will return a TestInput.\n   * <p>Usage:</p>\n   * <code>\n   * const testElement: TestTextArea | null = tester.element&lt;HTMLTextAreaElement>('.selector');\n   * </code>\n   * @param selector a CSS or directive selector\n   * @returns the wrapped element, or null if no element matches the selector.\n   */\n  element<T extends HTMLTextAreaElement>(selector: string | Type<any>): TestTextArea | null;\n  /**\n   * Gets the first element matching the given selector and wraps it into a TestElement. The actual type\n   * of the returned value is the TestElement subclass matching the type of the found element. So, if the\n   * matched element is an input for example, the method will return a TestInput.\n   * <p>Usage:</p>\n   * <code>\n   * const testElement: TestSelect | null = tester.element&lt;HTMLSelectElement>('.selector');\n   * </code>\n   * @param selector a CSS or directive selector\n   * @returns the wrapped element, or null if no element matches the selector.\n   */\n  element<T extends HTMLSelectElement>(selector: string | Type<any>): TestSelect | null;\n  /**\n   * Gets the first element matching the given selector and wraps it into a TestElement. The actual type\n   * of the returned value is the TestElement subclass matching the type of the found element. So, if the\n   * matched element is an input for example, the method will return a TestInput.\n   * <p>Usage:</p>\n   * <code>\n   * const testElement: TestButton | null = tester.element&lt;HTMLButtonElement>('.selector');\n   * </code>\n   * @param selector a CSS or directive selector\n   * @returns the wrapped element, or null if no element matches the selector.\n   */\n  element<T extends HTMLButtonElement>(selector: string | Type<any>): TestButton | null;\n  /**\n   * Gets the first element matching the given selector and wraps it into a TestElement. The actual type\n   * of the returned value is the TestElement subclass matching the type of the found element. So, if the\n   * matched element is an input for example, the method will return a TestInput.\n   * <p>Usage:</p>\n   * <code>\n   * const testElement: TestHtmlElement&lt;HTMLDivElement> | null = tester.element&lt;HTMLDivElement>('.selector');\n   * </code>\n   * @param selector a CSS or directive selector\n   * @returns the wrapped element, or null if no element matches the selector.\n   */\n  element<T extends HTMLElement>(selector: string | Type<any>): TestHtmlElement<T> | null;\n  /**\n   * Gets the first element matching the given selector and wraps it into a TestElement. The actual type\n   * of the returned value is the TestElement subclass matching the type of the found element. So, if the\n   * matched element is an input for example, the method will return a TestInput.\n   * <p>Usage:</p>\n   * <code>\n   * const testElement: TestElement&lt;SVGLineElement> | null = tester.element&lt;SVGLineElement>('.selector');\n   * </code>\n   * @param selector a CSS or directive selector\n   * @returns the wrapped element, or null if no element matches the selector.\n   */\n  element<T extends Element>(selector: string | Type<any>): TestElement<T> | null;\n  element(selector: string | Type<any>): TestElement | null {\n    return this.testElement.element(selector);\n  }\n\n  /**\n   * Gets all the elements matching the given CSS selector and wraps them into a TestElement. The actual type\n   * of the returned elements is the TestElement subclass matching the type of the found element. So, if the\n   * matched elements are inputs for example, the method will return an array of TestInput.\n   * <p>Usage:</p>\n   * <code>\n   * const testElements: Array&lt;TestHtmlElement&lt;HTMLDivElement>> = tester.elements('div');\n   * </code>\n   * @param selector a CSS selector\n   * @returns the array of matched elements, empty if no element was matched\n   */\n  elements<K extends keyof HTMLElementTagNameMap>(selector: K): Array<TestHtmlElement<HTMLElementTagNameMap[K]>>;\n  /**\n   * Gets all the elements matching the given CSS selector and wraps them into a TestElement. The actual type\n   * of the returned elements is the TestElement subclass matching the type of the found element. So, if the\n   * matched elements are inputs for example, the method will return an array of TestInput.\n   * <p>Usage:</p>\n   * <code>\n   * const testElements: Array&lt;TestElement&lt;SVGLineElement>> = tester.elements('line');\n   * </code>\n   * @param selector a CSS selector\n   * @returns the array of matched elements, empty if no element was matched\n   */\n  elements<K extends keyof SVGElementTagNameMap>(selector: K): Array<TestElement<SVGElementTagNameMap[K]>>;\n  /**\n   * Gets all the elements matching the given selector and wraps them into a TestElement. The actual type\n   * of the returned elements is the TestElement subclass matching the type of the found element. So, if the\n   * matched elements are inputs for example, the method will return an array of TestInput.\n   * <p>Usage:</p>\n   * <code>\n   * const testElements: Array&lt;TestElement> = tester.elements('.selector');\n   * </code>\n   * @param selector a CSS or directive selector\n   * @returns the array of matched elements, empty if no element was matched\n   */\n  elements(selector: string | Type<any>): Array<TestElement>;\n  /**\n   * Gets all the elements matching the given selector and wraps them into a TestElement. The actual type\n   * of the returned elements is the TestElement subclass matching the type of the found element. So, if the\n   * matched elements are inputs for example, the method will return an array of TestInput.\n   * <p>Usage:</p>\n   * <code>\n   * const testElements: Array&lt;TestInput> = tester.elements&lt;HTMLInputElement>('.selector');\n   * </code>\n   * @param selector a CSS or directive selector\n   * @returns the array of matched elements, empty if no element was matched\n   */\n  elements<T extends HTMLInputElement>(selector: string | Type<any>): Array<TestInput>;\n  /**\n   * Gets all the elements matching the given selector and wraps them into a TestElement. The actual type\n   * of the returned elements is the TestElement subclass matching the type of the found element. So, if the\n   * matched elements are inputs for example, the method will return an array of TestInput.\n   * <p>Usage:</p>\n   * <code>\n   * const testElements: Array&lt;TestTextArea> = tester.elements&lt;HTMLTextAreaElement>('.selector');\n   * </code>\n   * @param selector a CSS or directive selector\n   * @returns the array of matched elements, empty if no element was matched\n   */\n  elements<T extends HTMLTextAreaElement>(selector: string | Type<any>): Array<TestTextArea>;\n  /**\n   * Gets all the elements matching the given CSS selector and wraps them into a TestElement. The actual type\n   * of the returned elements is the TestElement subclass matching the type of the found element. So, if the\n   * matched elements are inputs for example, the method will return an array of TestInput.\n   * <p>Usage:</p>\n   * <code>\n   * const testElements: Array&lt;TestButton> = tester.elements&lt;HTMLButtonElement>('.selector');\n   * </code>\n   * @param selector a CSS or directive selector\n   * @returns the array of matched elements, empty if no element was matched\n   */\n  elements<T extends HTMLButtonElement>(selector: string | Type<any>): Array<TestButton>;\n  /**\n   * Gets all the elements matching the given selector and wraps them into a TestElement. The actual type\n   * of the returned elements is the TestElement subclass matching the type of the found element. So, if the\n   * matched elements are inputs for example, the method will return an array of TestInput.\n   * <p>Usage:</p>\n   * <code>\n   * const testElements: Array&lt;TestSelect> = tester.elements<HTMLSelectElement>('.selector');\n   * </code>\n   * @param selector a CSS or directive selector\n   * @returns the array of matched elements, empty if no element was matched\n   */\n  elements<T extends HTMLSelectElement>(selector: string | Type<any>): Array<TestSelect>;\n  /**\n   * Gets all the elements matching the given selector and wraps them into a TestElement. The actual type\n   * of the returned elements is the TestElement subclass matching the type of the found element. So, if the\n   * matched elements are inputs for example, the method will return an array of TestInput.\n   * <p>Usage:</p>\n   * <code>\n   * const testElements: Array&lt;TestHtmlElement&lt;HTMLDivElement>> = tester.elements&lt;HTMLDivElement>('.selector');\n   * </code>\n   * @param selector a CSS or directive selector\n   * @returns the array of matched elements, empty if no element was matched\n   */\n  elements<T extends HTMLElement>(selector: string | Type<any>): Array<TestHtmlElement<T>>;\n  /**\n   * Gets all the elements matching the given selector and wraps them into a TestElement. The actual type\n   * of the returned elements is the TestElement subclass matching the type of the found element. So, if the\n   * matched elements are inputs for example, the method will return an array of TestInput.\n   * <p>Usage:</p>\n   * <code>\n   * const testElements: Array&lt;TestElement&lt;SVGLineElement>> = tester.elements&lt;SVGLineElement>('.selector');\n   * </code>\n   * @param selector a CSS or directive selector\n   * @returns the array of matched elements, empty if no element was matched\n   */\n  elements<T extends Element>(selector: string | Type<any>): Array<TestElement<T>>;\n  elements(selector: string | Type<any>): Array<TestElement> {\n    return this.testElement.elements(selector);\n  }\n\n  /**\n   * Gets the first input matched by the given selector. Throws an Error if the matched element isn't actually an input.\n   * @param selector a CSS or directive selector\n   * @returns the wrapped input, or null if no element was matched\n   */\n  input(selector: string | Type<any>): TestInput | null {\n    return this.testElement.input(selector);\n  }\n\n  /**\n   * Gets the first select matched by the given selector. Throws an Error if the matched element isn't actually a select.\n   * @param selector a CSS or directive selector\n   * @returns the wrapped select, or null if no element was matched\n   */\n  select(selector: string | Type<any>): TestSelect | null {\n    return this.testElement.select(selector);\n  }\n\n  /**\n   * Gets the first textarea matched by the given selector\n   * @param selector a CSS or directive selector\n   * @returns the wrapped textarea, or null if no element was matched. Throws an Error if the matched element isn't actually a textarea.\n   * @throws {Error} if the matched element isn't actually a textarea\n   */\n  textarea(selector: string | Type<any>): TestTextArea | null {\n    return this.testElement.textarea(selector);\n  }\n\n  /**\n   * Gets the first button matched by the given selector. Throws an Error if the matched element isn't actually a button.\n   * @param selector a CSS or directive selector\n   * @returns the wrapped button, or null if no element was matched\n   */\n  button(selector: string | Type<any>): TestButton | null {\n    return this.testElement.button(selector);\n  }\n\n  /**\n   * Gets the first directive matching the given component directive selector and returns its component instance\n   * @param selector the selector of a component directive\n   */\n  component<R>(selector: Type<R>): R {\n    return this.testElement.component(selector);\n  }\n\n  /**\n   * Gets the directives matching the given component directive selector and returns their component instance\n   * @param selector the selector of a component directive\n   */\n  components<R>(selector: Type<R>): Array<R> {\n    return this.testElement.components(selector);\n  }\n\n  /**\n   * Gets the first element matching the given selector, then gets the given token from its injector, or null if there is no such token\n   * @param selector a CSS or directive selector\n   * @param token the token to get from the matched element injector\n   */\n  token<R>(selector: string | Type<any>, token: ProviderToken<R>): R | null {\n    return this.testElement.token(selector, token);\n  }\n\n  /**\n   * Gets the elements matching the given selector, then gets their given token from their injector, or null if there is no such token\n   * @param selector a CSS or directive selector\n   * @param token the token to get from the matched element injector\n   */\n  tokens<R>(selector: string | Type<any>, token: ProviderToken<R>): Array<R | null> {\n    return this.testElement.tokens(selector, token);\n  }\n\n  /**\n   * Gets the element matching the given selector, and if found, creates and returns a custom TestElement of the provided\n   * type. This is useful to create custom higher-level abstractions similar to TestInput, TestSelect, etc. for\n   * custom elements or components.\n   * @param selector a CSS or directive selector\n   * @param customTestElementType the type of the TestElement subclass that will wrap the found element\n   */\n  custom<E extends TestElement>(selector: string | Type<any>, customTestElementType: Type<E>): E | null {\n    return this.testElement.custom(selector, customTestElementType);\n  }\n\n  /**\n   * Gets the elements matching the given selector, and creates and returns custom TestElements of the provided\n   * type. This is useful to create custom higher-level abstractions similar to TestInput, TestSelect, etc. for\n   * custom elements or components.\n   * @param selector a CSS or directive selector\n   * @param customTestElementType the type of the TestElement subclass that will wrap the found elements\n   */\n  customs<E extends TestElement>(selector: string | Type<any>, customTestElementType: Type<E>): Array<E> {\n    return this.testElement.customs(selector, customTestElementType);\n  }\n\n  /**\n   * Triggers a change detection using the wrapped fixture in imperative mode.\n   * Throws an error in autodetection mode.\n   * You should generally prever\n   */\n  detectChanges(checkNoChanges?: boolean): void {\n    if (this.mode === 'automatic') {\n      throw new Error('In automatic mode, you should not call detectChanges');\n    }\n    this.fixture.detectChanges(checkNoChanges);\n  }\n\n  /**\n   * In imperative mode, runs change detection.\n   * In automatic mode, awaits stability.\n   */\n  async change() {\n    if (this.mode === 'automatic') {\n      await this.stable();\n    } else {\n      this.fixture.detectChanges();\n    }\n  }\n\n  /**\n   * Delegates to the wrapped fixture whenStable and, in imperative mode, detect changes\n   */\n  async stable(): Promise<void> {\n    await this.fixture.whenStable();\n    if (this.mode === 'imperative') {\n      this.detectChanges();\n    }\n  }\n}\n","import { ComponentTester } from './component-tester';\nimport { RouterTestingHarness } from '@angular/router/testing';\nimport { Router, UrlTree } from '@angular/router';\nimport { TestBed } from '@angular/core/testing';\n\n/**\n * A thin wrapper around Angular RouterTestingHarness which helps testing routed components.\n * It allows, based on a configured testing module where the router is provided, to initially navigate\n * to a given route, then test the routed component. It's then possible to either navigate again with\n * the wrapped harness, or to use the component to trigger navigation, and test that the URL has changed\n * for example.\n */\nexport class RoutingTester extends ComponentTester<unknown> {\n  constructor(readonly harness: RouterTestingHarness) {\n    super(harness.fixture);\n  }\n\n  /**\n   * Creates a RouterTestngHarness and uses it to navigate to the given URL\n   * @param url the URL to initially navigate to.\n   * @return a promise which resolves to a RoutingTester which wraps the harness\n   * and its fixture.\n   */\n  static async forUrl(url: string) {\n    const harness = await RouterTestingHarness.create(url);\n    return new RoutingTester(harness);\n  }\n\n  /**\n   * Gets the current URL of the Router service as a string\n   */\n  get url(): string {\n    const router = TestBed.inject(Router);\n    return router.url;\n  }\n\n  /**\n   * Gets the current URL of the Router service as an UrlTree, to be able to test its\n   * elements (query params, etc.)\n   */\n  get urlTree(): UrlTree {\n    const router = TestBed.inject(Router);\n    return router.parseUrl(router.url);\n  }\n}\n","import { ActivatedRoute, ActivatedRouteSnapshot, convertToParamMap, Data, ParamMap, Params, Route, UrlSegment } from '@angular/router';\nimport { BehaviorSubject } from 'rxjs';\n\n/**\n * The options that are passed when creating an ActivatedRouteStub.\n */\nexport interface ActivatedRouteStubOptions {\n  /**\n   * The initial values of the parameters of the route\n   */\n  params?: Params;\n  /**\n   * The initial values of the query parameters of the route\n   */\n  queryParams?: Params;\n  /**\n   * The initial values of the data of the route\n   */\n  data?: Data;\n  /**\n   * The initial values of the title of the route\n   */\n  title?: string;\n  /**\n   * The initial fragment of the route\n   */\n  fragment?: string | null;\n  /**\n   * The initial url of the route\n   */\n  url?: Array<UrlSegment>;\n  /**\n   * The parent of the route\n   */\n  parent?: ActivatedRouteStub | null;\n  /**\n   * The first child of the route\n   */\n  firstChild?: ActivatedRouteStub | null;\n  /**\n   * The children of the route\n   */\n  children?: Array<ActivatedRouteStub> | null;\n  /**\n   * The configuration of the route\n   */\n  routeConfig?: Route | null;\n}\n\nclass ActivatedRouteSnapshotStub extends ActivatedRouteSnapshot {\n  private _parent: ActivatedRouteSnapshot | null = null;\n  private _root: ActivatedRouteSnapshot;\n  private _firstChild: ActivatedRouteSnapshot | null = null;\n  private _children: Array<ActivatedRouteSnapshot> = [];\n  private _pathFromRoot: Array<ActivatedRouteSnapshot> = [];\n  private _title: string | undefined;\n\n  get parent(): ActivatedRouteSnapshot | null {\n    return this._parent;\n  }\n\n  set parent(value: ActivatedRouteSnapshot | null) {\n    this._parent = value;\n  }\n\n  get root(): ActivatedRouteSnapshot {\n    return this._root;\n  }\n\n  set root(value: ActivatedRouteSnapshot) {\n    this._root = value;\n  }\n\n  get firstChild(): ActivatedRouteSnapshot | null {\n    return this._firstChild;\n  }\n\n  set firstChild(value: ActivatedRouteSnapshot | null) {\n    this._firstChild = value;\n  }\n\n  get children(): Array<ActivatedRouteSnapshot> {\n    return this._children;\n  }\n\n  set children(value: Array<ActivatedRouteSnapshot>) {\n    this._children = value;\n  }\n\n  get pathFromRoot(): Array<ActivatedRouteSnapshot> {\n    return this._pathFromRoot;\n  }\n\n  set pathFromRoot(value: Array<ActivatedRouteSnapshot>) {\n    this._pathFromRoot = value;\n  }\n\n  get title(): string | undefined {\n    return this._title;\n  }\n\n  set title(value: string | undefined) {\n    this._title = value;\n  }\n\n  get paramMap(): ParamMap {\n    return convertToParamMap(this.params);\n  }\n\n  get queryParamMap(): ParamMap {\n    return convertToParamMap(this.queryParams);\n  }\n\n  constructor() {\n    super();\n    this._root = this;\n  }\n}\n\n/**\n * A stub for ActivatedRoute. It behaves almost the same way as the actual ActivatedRoute, exposing a snapshot\n * and observables for the params, query params etc., which are kept in sync.\n *\n * In addition, this stub allows simulating a navigation by changing the params, the query params, the fragment, etc.\n * When that happens, the snapshot is modified, then the relevant observables emit the new values.\n *\n * There are some things that don't really work the same way as the real ActivatedRoute though:\n * - the handling of the firstChild and of the children is entirely under the tester's responsibility. Setting the parent\n *   of a route stub does not add this route to the children of its parent, for example.\n * - when changing the params, query params, fragment, etc., their associated observable emits unconditionally, instead of\n *   first checking if the value is actually different from before. It's thus the responsibility of the tester to not\n *   change the values if they're the same as before.\n * - the params, paramMap, queryParams and queryParamMap objects of the route snapshot change when params or query params are set\n *   on the stub route. So if the code keeps a reference to params or paramMaps, it won't see the changes.\n */\nexport class ActivatedRouteStub extends ActivatedRoute {\n  private _firstChild: ActivatedRouteStub | null;\n  private _children: Array<ActivatedRouteStub>;\n\n  private readonly paramsSubject: BehaviorSubject<Params>;\n  private readonly queryParamsSubject: BehaviorSubject<Params>;\n  private readonly dataSubject: BehaviorSubject<Data>;\n  private readonly fragmentSubject: BehaviorSubject<string | null>;\n  private readonly urlSubject: BehaviorSubject<Array<UrlSegment>>;\n  private readonly titleSubject: BehaviorSubject<string | undefined>;\n\n  private _parent: ActivatedRouteStub | null;\n  private _root: ActivatedRouteStub;\n  private _pathFromRoot: Array<ActivatedRouteStub>;\n\n  /**\n   * Constructs a new instance, based on the given options.\n   * If an option is not provided (or if no option is provided at all), then the route has a default value for this option\n   * (empty parameters for example, null fragment, etc.)\n   * If no parent is passed, then this route has no parent and is thus set as the root. Otherwise, the root and the path\n   * from root are created based on the root and path from root of the given parent route.\n   */\n  constructor(options?: ActivatedRouteStubOptions) {\n    super();\n\n    const snapshot = new ActivatedRouteSnapshotStub();\n    this.snapshot = snapshot;\n\n    this._firstChild = options?.firstChild ?? null;\n    this._children = options?.children ?? [];\n    this._parent = options?.parent ?? null;\n    this._root = this.parent?.root ?? this;\n    this._pathFromRoot = this.parent ? [...this.parent.pathFromRoot, this] : [this];\n\n    snapshot.params = options?.params ?? {};\n    snapshot.queryParams = options?.queryParams ?? {};\n    snapshot.data = options?.data ?? {};\n    snapshot.title = options?.title;\n    snapshot.fragment = options?.fragment ?? null;\n    snapshot.url = options?.url ?? [];\n    // @ts-expect-error the routeConfig is readonly, but we need to overwrite it here\n    snapshot.routeConfig = options?.routeConfig ?? null;\n\n    snapshot.firstChild = this.firstChild?.snapshot ?? null;\n    snapshot.children = this.children?.map(route => route.snapshot) ?? [];\n    snapshot.parent = this.parent?.snapshot ?? null;\n    snapshot.root = this.root.snapshot;\n    snapshot.pathFromRoot = this.pathFromRoot.map(route => route.snapshot);\n\n    this.paramsSubject = new BehaviorSubject<Params>(this.snapshot.params);\n    this.queryParamsSubject = new BehaviorSubject<Params>(this.snapshot.queryParams);\n    this.dataSubject = new BehaviorSubject<Data>(this.snapshot.data);\n    this.titleSubject = new BehaviorSubject<string | undefined>(this.snapshot.title);\n    this.fragmentSubject = new BehaviorSubject<string | null>(this.snapshot.fragment);\n    this.urlSubject = new BehaviorSubject<Array<UrlSegment>>(this.snapshot.url);\n\n    this.params = this.paramsSubject.asObservable();\n    this.queryParams = this.queryParamsSubject.asObservable();\n    this.data = this.dataSubject.asObservable();\n    this.fragment = this.fragmentSubject.asObservable();\n    this.url = this.urlSubject.asObservable();\n    // @ts-expect-error the title is readonly, but we need to be able to initialize it  here\n    this.title = this.titleSubject.asObservable();\n  }\n\n  get root() {\n    return this._root;\n  }\n\n  get parent(): ActivatedRouteStub | null {\n    return this._parent;\n  }\n\n  get pathFromRoot(): Array<ActivatedRouteStub> {\n    return this._pathFromRoot;\n  }\n\n  get firstChild(): ActivatedRouteStub | null {\n    return this._firstChild;\n  }\n\n  get children(): Array<ActivatedRouteStub> {\n    return this._children;\n  }\n\n  get routeConfig(): Route | null {\n    return this.snapshot.routeConfig;\n  }\n\n  /**\n   * Triggers a navigation with the given new parameters. All the other parts (query params etc.) stay as they are.\n   * This is a shortcut to `triggerNavigation` that can be used to only change the parameters.\n   */\n  public setParams(params: Params): void {\n    this.triggerNavigation({ params });\n  }\n\n  /**\n   * Triggers a navigation with the given new parameter. The other parameters, as well as all the other parts (query params etc.)\n   * stay as they are.\n   * This is a shortcut to `triggerNavigation` that can be used to only change one parameter.\n   */\n  public setParam(name: string, value: string): void {\n    this.setParams({ ...this.snapshot.params, [name]: value });\n  }\n\n  /**\n   * Triggers a navigation with the given new query parameters. All the other parts (params etc.) stay as the are.\n   * This is a shortcut to `triggerNavigation` that can be used to only change the query parameters.\n   */\n  public setQueryParams(queryParams: Params): void {\n    this.triggerNavigation({ queryParams });\n  }\n\n  /**\n   * Triggers a navigation with the given new parameter. The other query parameters, as well as all the other parts (params etc.)\n   * stay as the are.\n   * This is a shortcut to `triggerNavigation` that can be used to only change one query parameter.\n   */\n  public setQueryParam(name: string, value: string): void {\n    this.setQueryParams({ ...this.snapshot.queryParams, [name]: value });\n  }\n\n  /**\n   * Triggers a navigation with the given new data. The other parameters, as well as all the other parts (params etc.)\n   * stay as the are.\n   * This is a shortcut to `triggerNavigation` that can be used to only change the data.\n   */\n  public setData(data: Data): void {\n    this.triggerNavigation({ data });\n  }\n\n  /**\n   * Triggers a navigation with the given new data item. The other data, as well as all the other parts (params etc.)\n   * stay as the are.\n   * This is a shortcut to `triggerNavigation` that can be used to only change one data item.\n   */\n  public setDataItem(name: string, value: unknown): void {\n    this.setData({ ...this.snapshot.data, [name]: value });\n  }\n\n  /**\n   * Triggers a navigation with the given new title. The other parameters, as well as all the other parts (params etc.)\n   * stay as the are.\n   * This is a shortcut to `triggerNavigation` that can be used to only change the title.\n   */\n  public setTitle(title: string | undefined): void {\n    this.triggerNavigation({ title: { value: title } });\n  }\n\n  /**\n   * Triggers a navigation with the given new fragment. The other parts (params etc.)  stay as the are.\n   * This is a shortcut to `triggerNavigation` that can be used to only change the fragment.\n   */\n  public setFragment(fragment: string | null): void {\n    this.triggerNavigation({ fragment });\n  }\n\n  /**\n   * Triggers a navigation with the given new url. The other parts (params etc.)  stay as the are.\n   * This is a shortcut to `triggerNavigation` that can be used to only change the url.\n   */\n  public setUrl(url: Array<UrlSegment>): void {\n    this.triggerNavigation({ url });\n  }\n\n  /**\n   * Triggers a navigation based on the given options. If an option is undefined or null, it's ignored. Except for fragment, which is only\n   * ignored if it's undefined, because null is a valid value for a fragment.\n   *\n   * The non-ignored values are used to change the snapshot of the route. Once the snapshot has been modified,\n   * the observables corresponding to the updated parts emit the new value.\n   *\n   * So, setting params and query params will make the params and queryParams observables emit, but not the fragment, data and\n   * url observables for example. This is consistent to how the router behaves.\n   *\n   * Note: since the title of a route can become undefined, in order to be able to distinguish between a navigation which leaves the title\n   * as it is and a navigation that sets the title to undefined, a wrapper object is used for the title. So\n   *\n   * - `triggerNavigation({ params:... })` leaves the title as is because it's undefined in the options\n   * - `triggerNavigation({ title: { value: 'test' } })` sets the title to 'test'\n   * - `triggerNavigation({ title: { value: undefined } })` sets the title to undefined\n   */\n  public triggerNavigation(options: {\n    params?: Params;\n    queryParams?: Params;\n    fragment?: string | null;\n    data?: Data | null;\n    title?: { value: string | undefined } | null;\n    url?: Array<UrlSegment> | null;\n  }): void {\n    // set the snapshot first\n    if (options.params) {\n      this.snapshot.params = options.params;\n    }\n    if (options.queryParams) {\n      this.snapshot.queryParams = options.queryParams;\n    }\n    if (options.fragment !== undefined) {\n      this.snapshot.fragment = options.fragment;\n    }\n    if (options.data) {\n      this.snapshot.data = options.data;\n    }\n    if (options.title) {\n      // @ts-expect-error the title is readonly, but we need to be able to overwrite it here\n      this.snapshot.title = options.title.value;\n    }\n    if (options.url) {\n      this.snapshot.url = options.url;\n    }\n\n    // then emit everything that has changed\n    if (options.params) {\n      this.paramsSubject.next(this.snapshot.params);\n    }\n    if (options.queryParams) {\n      this.queryParamsSubject.next(this.snapshot.queryParams);\n    }\n    if (options.fragment !== undefined) {\n      this.fragmentSubject.next(this.snapshot.fragment);\n    }\n    if (options.data) {\n      this.dataSubject.next(this.snapshot.data);\n    }\n    if (options.title) {\n      this.titleSubject.next(this.snapshot.title);\n    }\n    if (options.url) {\n      this.urlSubject.next(this.snapshot.url);\n    }\n  }\n\n  public toString(): string {\n    return 'ActivatedRouteStub';\n  }\n}\n\n/**\n * Creates a new ActivatedRouteStub, by calling its constructor.\n */\nexport function stubRoute(options?: ActivatedRouteStubOptions): ActivatedRouteStub {\n  return new ActivatedRouteStub(options);\n}\n","import { TestTextArea } from './test-textarea';\nimport { TestInput } from './test-input';\nimport { TestElement } from './test-element';\nimport { TestSelect } from './test-select';\nimport { TestHtmlElement } from './test-html-element';\n\nconst speculoosMatchers: jasmine.CustomMatcherFactories = {\n  /**\n   * Checks that the receiver is a TestElement wrapping a DOM element and as the given CSS class\n   */\n  toHaveClass(): jasmine.CustomMatcher {\n    const assert = (isNegative: boolean, el: unknown, expected: string) => {\n      if (!el) {\n        return { pass: false, message: `Expected to check class '${expected}' on element, but element was falsy` };\n      }\n      if (!(el instanceof TestElement)) {\n        return { pass: false, message: `Expected to check class '${expected}' on element, but element was not a TestElement` };\n      }\n      const actual = el.classes;\n      const pass = actual.indexOf(expected) !== -1;\n      const message =\n        `Expected element to ${isNegative ? 'not ' : ''}have class '${expected}', ` +\n        `but had ${actual.length ? \"'\" + actual.join(', ') + \"'\" : 'none'}`;\n      return { pass: isNegative ? !pass : pass, message };\n    };\n    return {\n      compare(el: unknown, expected: string): jasmine.CustomMatcherResult {\n        return assert(false, el, expected);\n      },\n      negativeCompare(el: unknown, expected: string): jasmine.CustomMatcherResult {\n        return assert(true, el, expected);\n      }\n    };\n  },\n\n  /**\n   * Checks that the receiver is a TestInput or a TestTextArea and has the given value\n   */\n  toHaveValue(): jasmine.CustomMatcher {\n    const assert = (isNegative: boolean, el: unknown, expected: string) => {\n      if (!el) {\n        return { pass: false, message: `Expected to check value '${expected}' on element, but element was falsy` };\n      }\n      if (!(el instanceof TestInput) && !(el instanceof TestTextArea)) {\n        return {\n          pass: false,\n          message: `Expected to check value '${expected}' on element, but element was neither a TestInput nor a TestTextArea`\n        };\n      }\n      const actual = el.value;\n      const pass = actual === expected;\n      const message = `Expected element to ${isNegative ? 'not ' : ''}have value '${expected}', but had value '${actual}'`;\n      return { pass: isNegative ? !pass : pass, message };\n    };\n    return {\n      compare(el: unknown, expected: string): jasmine.CustomMatcherResult {\n        return assert(false, el, expected);\n      },\n      negativeCompare(el: unknown, expected: string): jasmine.CustomMatcherResult {\n        return assert(true, el, expected);\n      }\n    };\n  },\n\n  /**\n   * Checks that the receiver is a TestElement wrapping a DOM element and has the exact given textContent\n   */\n  toHaveText(): jasmine.CustomMatcher {\n    const assert = (isNegative: boolean, el: unknown, expected: string) => {\n      if (!el) {\n        return { pass: false, message: `Expected to check text '${expected}' on element, but element was falsy` };\n      }\n      if (!(el instanceof TestElement)) {\n        return { pass: false, message: `Expected to check text '${expected}' on element, but element was not a TestElement` };\n      }\n      const actual = el.textContent;\n      const pass = actual === expected;\n      const message = `Expected element to ${isNegative ? 'not ' : ''}have text '${expected}', but had '${actual}'`;\n      return { pass: isNegative ? !pass : pass, message };\n    };\n    return {\n      compare(el: unknown, expected: string): jasmine.CustomMatcherResult {\n        return assert(false, el, expected);\n      },\n      negativeCompare(el: unknown, expected: string): jasmine.CustomMatcherResult {\n        return assert(true, el, expected);\n      }\n    };\n  },\n\n  /**\n   * Checks that the receiver is a TestElement wrapping a DOM element and has the given textContent, after both have been trimmed.\n   * So, An element such as\n   * ```\n   * <h1>\n   *   Some title\n   * </h1>\n   * ```\n   * will pass the test\n   * ```\n   * expect(tester.title).toHaveTrimmedText('Some title')\n   * ```\n   */\n  toHaveTrimmedText(): jasmine.CustomMatcher {\n    const assert = (isNegative: boolean, el: unknown, expected: string) => {\n      const trimmedExpected = expected.trim();\n      if (!el) {\n        return { pass: false, message: `Expected to check trimmed text '${trimmedExpected}' on element, but element was falsy` };\n      }\n      if (!(el instanceof TestElement)) {\n        return {\n          pass: false,\n          message: `Expected to check trimmed text '${trimmedExpected}' on element, but element was not a TestElement`\n        };\n      }\n      const actual = el.textContent?.trim();\n      const pass = actual === trimmedExpected;\n      const message = `Expected element to ${isNegative ? 'not ' : ''}have trimmed text '${trimmedExpected}', but had '${actual}'`;\n      return { pass: isNegative ? !pass : pass, message };\n    };\n    return {\n      compare(el: unknown, expected: string): jasmine.CustomMatcherResult {\n        return assert(false, el, expected);\n      },\n      negativeCompare(el: unknown, expected: string): jasmine.CustomMatcherResult {\n        return assert(true, el, expected);\n      }\n    };\n  },\n\n  /**\n   * Checks that the receiver is a TestElement wrapping a DOM element and contains the given textContent\n   */\n  toContainText(): jasmine.CustomMatcher {\n    const assert = (isNegative: boolean, el: unknown, expected: string) => {\n      if (!el) {\n        return { pass: false, message: `Expected to check text '${expected}' on element, but element was falsy` };\n      }\n      if (!(el instanceof TestElement)) {\n        return { pass: false, message: `Expected to check text '${expected}' on element, but element was not a TestElement` };\n      }\n      const actual = el.textContent;\n      if (!actual) {\n        return {\n          pass: isNegative,\n          message: `Expected element to ${isNegative ? 'not ' : ''}contain text '${expected}', but had no text`\n        };\n      }\n      const pass = actual.indexOf(expected) !== -1;\n      const message = `Expected element to ${isNegative ? 'not ' : ''}contain text '${expected}', but had text '${actual}'`;\n      return { pass: isNegative ? !pass : pass, message };\n    };\n    return {\n      compare(el: unknown, expected: string): jasmine.CustomMatcherResult {\n        return assert(false, el, expected);\n      },\n      negativeCompare(el: unknown, expected: string): jasmine.CustomMatcherResult {\n        return assert(true, el, expected);\n      }\n    };\n  },\n\n  /**\n   * Checks that the receiver is a TestElement wrapping a DOM element and contains the given textContent\n   */\n  toBeChecked(): jasmine.CustomMatcher {\n    const assert = (isNegative: boolean, el: unknown) => {\n      if (!el) {\n        return { pass: false, message: `Expected to check if element was checked, but element was falsy` };\n      }\n      if (!(el instanceof TestInput)) {\n        return { pass: false, message: `Expected to check if element was checked, but element was not a TestInput` };\n      }\n      const pass = el.checked;\n      const message = `Expected element to be ${isNegative ? 'not ' : ''}checked, but was${!isNegative ? ' not' : ''}`;\n      return { pass: isNegative ? !pass : pass, message };\n    };\n    return {\n      compare(el: unknown): jasmine.CustomMatcherResult {\n        return assert(false, el);\n      },\n      negativeCompare(el: unknown): jasmine.CustomMatcherResult {\n        return assert(true, el);\n      }\n    };\n  },\n\n  /**\n   * Checks that the receiver is a TestSelect wrapping a DOM element and has the given selected index\n   */\n  toHaveSelectedIndex(): jasmine.CustomMatcher {\n    const assert = (isNegative: boolean, el: unknown, expected: number) => {\n      if (!el) {\n        return { pass: false, message: `Expected to check selected index ${expected} on element, but element was falsy` };\n      }\n      if (!(el instanceof TestSelect)) {\n        return { pass: false, message: `Expected to check selected index ${expected} on element, but element was not a TestSelect` };\n      }\n      const actual = el.selectedIndex;\n      const pass = actual === expected;\n      const message = `Expected element to ${isNegative ? 'not ' : ''}have selected index ${expected}, but had ${actual}`;\n      return { pass: isNegative ? !pass : pass, message };\n    };\n    return {\n      compare(el: unknown, expected: number): jasmine.CustomMatcherResult {\n        return assert(false, el, expected);\n      },\n      negativeCompare(el: unknown, expected: number): jasmine.CustomMatcherResult {\n        return assert(true, el, expected);\n      }\n    };\n  },\n\n  /**\n   * Checks that the receiver is a TestSelect wrapping a DOM element with the selected option's value equal to the given value\n   */\n  toHaveSelectedValue(): jasmine.CustomMatcher {\n    const assert = (isNegative: boolean, el: unknown, expected: string) => {\n      if (!el) {\n        return { pass: false, message: `Expected to check selected value '${expected}' on element, but element was falsy` };\n      }\n      if (!(el instanceof TestSelect)) {\n        return { pass: false, message: `Expected to check selected value '${expected}' on element, but element was not a TestSelect` };\n      }\n      const actual = el.selectedValue;\n      const pass = actual === expected;\n      const message = `Expected element to ${isNegative ? 'not ' : ''}have selected value '${expected}', but had '${actual}'`;\n      return { pass: isNegative ? !pass : pass, message };\n    };\n    return {\n      compare(el: unknown, expected: string): jasmine.CustomMatcherResult {\n        return assert(false, el, expected);\n      },\n      negativeCompare(el: unknown, expected: string): jasmine.CustomMatcherResult {\n        return assert(true, el, expected);\n      }\n    };\n  },\n\n  /**\n   * Checks that the receiver is a TestSelect wrapping a DOM element with the selected option's label equal to the given label\n   */\n  toHaveSelectedLabel(): jasmine.CustomMatcher {\n    const assert = (isNegative: boolean, el: unknown, expected: string) => {\n      if (!el) {\n        return { pass: false, message: `Expected to check selected label '${expected}' on element, but element was falsy` };\n      }\n      if (!(el instanceof TestSelect)) {\n        return { pass: false, message: `Expected to check selected label '${expected}' on element, but element was not a TestSelect` };\n      }\n      const actual = el.selectedLabel;\n      const pass = actual === expected;\n      const message = `Expected element to ${isNegative ? 'not ' : ''}have selected label '${expected}', but had '${actual}'`;\n      return { pass: isNegative ? !pass : pass, message };\n    };\n    return {\n      compare(el: unknown, expected: string): jasmine.CustomMatcherResult {\n        return assert(false, el, expected);\n      },\n      negativeCompare(el: unknown, expected: string): jasmine.CustomMatcherResult {\n        return assert(true, el, expected);\n      }\n    };\n  },\n\n  /**\n   * Checks that the receiver is a TestHtmlElement which is visible\n   */\n  toBeVisible(): jasmine.CustomMatcher {\n    const assert = (isNegative: boolean, el: unknown) => {\n      const expectedState = `${isNegative ? 'in' : ''}visible`;\n      const inverseState = `${isNegative ? '' : 'in'}visible`;\n      if (!el) {\n        return { pass: false, message: `Expected to check if element was ${expectedState}, but element was falsy` };\n      }\n      if (!(el instanceof TestHtmlElement)) {\n        return { pass: false, message: `Expected to check if element was ${expectedState}, but element was not a TestHtmlElement` };\n      }\n      const pass = el.visible;\n      const message = `Expected element to be ${expectedState}, but was ${inverseState}`;\n      return { pass: isNegative ? !pass : pass, message };\n    };\n    return {\n      compare(el: unknown): jasmine.CustomMatcherResult {\n        return assert(false, el);\n      },\n      negativeCompare(el: unknown): jasmine.CustomMatcherResult {\n        return assert(true, el);\n      }\n    };\n  }\n};\n\nexport { speculoosMatchers };\n","import { Type } from '@angular/core';\n\nfunction collectMethodNames(proto: unknown): Array<string> {\n  if (!proto || proto === Object.prototype) {\n    return [];\n  }\n  const methodNames: Array<string> = [];\n  for (const key of Object.getOwnPropertyNames(proto)) {\n    const descriptor = Object.getOwnPropertyDescriptor(proto, key);\n    if (descriptor && typeof descriptor.value === 'function' && key !== 'constructor') {\n      methodNames.push(key);\n    }\n  }\n  return [...methodNames, ...collectMethodNames(Object.getPrototypeOf(proto))];\n}\n\n/**\n * Creates a spy object for a class where all the methods of the class (and of its superclasses) are spies.\n * I.e., for a class `UserService` with methods `get()`, `create()`, `update()` and `delete()`, calling\n * `createMock(UserService)` is equivalent to calling\n * `jasmine.createSpyObj<UserService>('UserService', ['get', 'create', 'update', 'delete'])`.\n * @param type the type to mock (usually a service class)\n */\nexport function createMock<T>(type: Type<T>): jasmine.SpyObj<T> {\n  return jasmine.createSpyObj<T>(type.name, collectMethodNames(type.prototype) as unknown as jasmine.SpyObjMethodNames<T>);\n}\n","import { EnvironmentProviders, makeEnvironmentProviders } from '@angular/core';\nimport { ComponentFixtureAutoDetect } from '@angular/core/testing';\n\nconst COMPONENT_FIXTURE_AUTO_DETECTION: EnvironmentProviders = makeEnvironmentProviders([\n  { provide: ComponentFixtureAutoDetect, useValue: true }\n]);\n\n/**\n * Provide function which returns the provider `{ provide: ComponentFixtureAutoDetect, useValue: true }`.\n * This provider can be added to the testing module to configure the component testers\n * (and the underlying ComponentFixture) in automatic mode:\n *\n * ```\n * TestBed.configureTestingModule({ providers: [provideAutomaticChangeDetection()] });\n * ```\n */\nexport function provideAutomaticChangeDetection(): EnvironmentProviders {\n  return COMPONENT_FIXTURE_AUTO_DETECTION;\n}\n","/*\n * Public API Surface of ngx-speculoos\n */\nimport './jasmine-matchers';\n\nexport * from './lib/component-tester';\nexport * from './lib/routing-tester';\nexport * from './lib/test-element';\nexport * from './lib/test-html-element';\nexport * from './lib/test-input';\nexport * from './lib/test-button';\nexport * from './lib/test-select';\nexport * from './lib/test-textarea';\nexport * from './lib/route';\nexport * from './lib/matchers';\nexport * from './lib/mock';\nexport * from './lib/providers';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public_api';\n"],"names":[],"mappings":"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"}