import { ComponentFixture } from '@angular/core/testing';
import { DebugElement, Type, ProviderToken, EnvironmentProviders } from '@angular/core';
import { RouterTestingHarness } from '@angular/router/testing';
import { UrlTree, Params, Data, UrlSegment, ActivatedRoute, Route } from '@angular/router';

declare global {
    namespace jasmine {
        interface Matchers<T> {
            /**
             * Checks that the receiver is a TestElement wrapping a DOM element and has the given CSS class
             */
            toHaveClass(className: string): boolean;
            /**
             * Checks that the receiver is a TestInput or a TestTextArea and has the given value
             */
            toHaveValue(value: string): boolean;
            /**
             * Checks that the receiver is a TestElement wrapping a DOM element and has the exact given textContent
             */
            toHaveText(textContent: string): boolean;
            /**
             * Checks that the receiver is a TestElement wrapping a DOM element and has the given textContent
             * after both have been trimmed.
             */
            toHaveTrimmedText(textContent: string): boolean;
            /**
             * Checks that the receiver is a TestElement wrapping a DOM element and contains the given textContent
             */
            toContainText(textContent: string): boolean;
            /**
             * Checks that the receiver is a TestInput and is checked
             */
            toBeChecked(): boolean;
            /**
             * Checks that the receiver is a TestSelect wrapping a DOM element and has the given selected index
             */
            toHaveSelectedIndex(index: number): boolean;
            /**
             * Checks that the receiver is a TestSelect wrapping a DOM element with the selected option's value equal to the given value
             */
            toHaveSelectedValue(value: string): boolean;
            /**
             * Checks that the receiver is a TestSelect wrapping a DOM element with the selected option's label equal to the given label
             */
            toHaveSelectedLabel(label: string): boolean;
            /**
             * Checks that the receiver is a TestHtmlElement which is visible.
             */
            toBeVisible(): boolean;
        }
    }
}

/**
 * A wrapped button element, providing additional methods and attributes helping with writing tests
 */
declare class TestButton extends TestHtmlElement<HTMLButtonElement> {
    constructor(tester: ComponentTester<unknown>, debugElement: DebugElement);
    /**
     * the disabled flag of the button
     */
    get disabled(): boolean;
}

/**
 * A wrapped DOM HTML select element, providing additional methods and attributes helping with writing tests
 */
declare class TestSelect extends TestHtmlElement<HTMLSelectElement> {
    constructor(tester: ComponentTester<unknown>, debugElement: DebugElement);
    /**
     * Selects the option at the given index, then dispatches an event of type change and triggers a change detection.
     * If the index is out of bounds and is not -1, then throws an error.
     */
    selectIndex(index: number): Promise<void>;
    /**
     * Selects the first option with the given value, then dispatches an event of type change and triggers a change detection.
     * If there is no option with the given value, then throws an error.
     */
    selectValue(value: string): Promise<void>;
    /**
     * Selects the first option with the given label (or text), then dispatches an event of type change and triggers a change detection.
     * If there is no option with the given label, then throws an error.
     */
    selectLabel(label: string): Promise<void>;
    /**
     * the selected index of the wrapped select
     */
    get selectedIndex(): number;
    /**
     * the value of the selected option of the wrapped select, or null if there is no selected option
     */
    get selectedValue(): string | null;
    /**
     * the label (or text if no label) of the selected option of the wrapped select, or null if there is no selected option
     */
    get selectedLabel(): string | null;
    /**
     * the values of the options, as an array
     */
    get optionValues(): Array<string>;
    /**
     * the labels (or texts if no label) of the options, as an array
     */
    get optionLabels(): Array<string>;
    /**
     * the number of options in the select
     */
    get size(): number;
    /**
     * the disabled property of the wrapped select
     */
    get disabled(): boolean;
}

/**
 * A wrapped DOM HTML input element, providing additional methods and attributes helping with writing tests
 */
declare class TestInput extends TestHtmlElement<HTMLInputElement> {
    constructor(tester: ComponentTester<unknown>, debugElement: DebugElement);
    /**
     * Sets the value of the wrapped input, then dispatches an event of type input and triggers a change detection
     * @param value the new value of the input
     */
    fillWith(value: string): Promise<void>;
    /**
     * the value of the wrapped input
     */
    get value(): string;
    /**
     * the checked property of the wrapped input
     */
    get checked(): boolean;
    /**
     * the disabled property of the wrapped input
     */
    get disabled(): boolean;
    /**
     * Checks the wrapped input, then dispatches an event of type change and triggers a change detection
     */
    check(): Promise<void>;
    /**
     * Unchecks the wrapped input, then dispatches an event of type change and triggers a change detection
     */
    uncheck(): Promise<void>;
}

/**
 * A wrapped DOM element, providing additional methods and attributes helping with writing tests
 */
declare class TestElement<E extends Element = Element> {
    protected tester: ComponentTester<unknown>;
    /**
     * the wrapped debug element
     */
    readonly debugElement: DebugElement;
    private querier;
    constructor(tester: ComponentTester<unknown>, 
    /**
     * the wrapped debug element
     */
    debugElement: DebugElement);
    get nativeElement(): E;
    /**
     * the text content of this element
     */
    get textContent(): string | null;
    /**
     * dispatches an event of the given type from the wrapped element, then triggers a change detection
     */
    dispatchEventOfType(type: string): Promise<void>;
    /**
     * dispatches the given event from the wrapped element, then triggers a change detection
     */
    dispatchEvent(event: Event): Promise<void>;
    /**
     * Gets the CSS classes of the wrapped element, as an array
     */
    get classes(): Array<string>;
    /**
     * Gets the attribute of the wrapped element with the given name
     * @param name the name of the attribute to get
     */
    attr(name: string): string | null;
    /**
     * Gets the first element matching the given CSS selector and wraps it into a TestElement. The actual type
     * of the returned value is the TestElement subclass matching the type of the found element. So, if the
     * matched element is an input for example, the method will return a TestInput.
     * <p>Usage:</p>
     * <code>
     * const testElement: TestHtmlElement&lt;HTMLDivElement> | null = tester.element('div');
     * </code>
     * @param selector a CSS selector
     * @returns the wrapped element, or null if no element matches the selector.
     */
    element<K extends keyof HTMLElementTagNameMap>(selector: K): TestHtmlElement<HTMLElementTagNameMap[K]> | null;
    /**
     * Gets the first element matching the given CSS selector and wraps it into a TestElement. The actual type
     * of the returned value is the TestElement subclass matching the type of the found element. So, if the
     * matched element is an input for example, the method will return a TestInput.
     * <p>Usage:</p>
     * <code>
     * const testElement: TestElement&lt;SVGLineElement> | null = tester.element('line');
     * </code>
     * @param selector a CSS selector
     * @returns the wrapped element, or null if no element matches the selector.
     */
    element<K extends keyof SVGElementTagNameMap>(selector: K): TestElement<SVGElementTagNameMap[K]> | null;
    /**
     * Gets the first element matching the given CSS selector and wraps it into a TestElement. The actual type
     * of the returned value is the TestElement subclass matching the type of the found element. So, if the
     * matched element is an input for example, the method will return a TestInput.
     * <p>Usage:</p>
     * <code>
     * const testElement: TestElement | null = tester.element('.selector');
     * </code>
     * @param selector a CSS or directive selector
     * @returns the wrapped element, or null if no element matches the selector.
     */
    element(selector: string | Type<any>): TestElement | null;
    /**
     * Gets the first element matching the given selector and wraps it into a TestElement. The actual type
     * of the returned value is the TestElement subclass matching the type of the found element. So, if the
     * matched element is an input for example, the method will return a TestInput.
     * <p>Usage:</p>
     * <code>
     * const testElement: TestInput | null = tester.element&lt;HTMLInputElement>('.selector');
     * </code>
     * @param selector a CSS or directive selector
     * @returns the wrapped element, or null if no element matches the selector.
     */
    element<T extends HTMLInputElement>(selector: string | Type<any>): TestInput | null;
    /**
     * Gets the first element matching the given selector and wraps it into a TestElement. The actual type
     * of the returned value is the TestElement subclass matching the type of the found element. So, if the
     * matched element is an input for example, the method will return a TestInput.
     * <p>Usage:</p>
     * <code>
     * const testElement: TestTextArea | null = tester.element&lt;HTMLTextAreaElement>('.selector');
     * </code>
     * @param selector a CSS or directive selector
     * @returns the wrapped element, or null if no element matches the selector.
     */
    element<T extends HTMLTextAreaElement>(selector: string | Type<any>): TestTextArea | null;
    /**
     * Gets the first element matching the given selector and wraps it into a TestElement. The actual type
     * of the returned value is the TestElement subclass matching the type of the found element. So, if the
     * matched element is an input for example, the method will return a TestInput.
     * <p>Usage:</p>
     * <code>
     * const testElement: TestSelect | null = tester.element&lt;HTMLSelectElement>('.selector');
     * </code>
     * @param selector a CSS or directive selector
     * @returns the wrapped element, or null if no element matches the selector.
     */
    element<T extends HTMLSelectElement>(selector: string | Type<any>): TestSelect | null;
    /**
     * Gets the first element matching the given selector and wraps it into a TestElement. The actual type
     * of the returned value is the TestElement subclass matching the type of the found element. So, if the
     * matched element is an input for example, the method will return a TestInput.
     * <p>Usage:</p>
     * <code>
     * const testElement: TestButton | null = tester.element&lt;HTMLButtonElement>('.selector');
     * </code>
     * @param selector a CSS or directive selector
     * @returns the wrapped element, or null if no element matches the selector.
     */
    element<T extends HTMLButtonElement>(selector: string | Type<any>): TestButton | null;
    /**
     * Gets the first element matching the given selector and wraps it into a TestElement. The actual type
     * of the returned value is the TestElement subclass matching the type of the found element. So, if the
     * matched element is an input for example, the method will return a TestInput.
     * <p>Usage:</p>
     * <code>
     * const testElement: TestHtmlElement&lt;HTMLDivElement> | null = tester.element&lt;HTMLDivElement>('.selector');
     * </code>
     * @param selector a CSS or directive selector
     * @returns the wrapped element, or null if no element matches the selector.
     */
    element<T extends HTMLElement>(selector: string | Type<any>): TestHtmlElement<T> | null;
    /**
     * Gets the first element matching the given selector and wraps it into a TestElement. The actual type
     * of the returned value is the TestElement subclass matching the type of the found element. So, if the
     * matched element is an input for example, the method will return a TestInput.
     * <p>Usage:</p>
     * <code>
     * const testElement: TestElement&lt;SVGLineElement> | null = tester.element&lt;SVGLineElement>('.selector');
     * </code>
     * @param selector a CSS or directive selector
     * @returns the wrapped element, or null if no element matches the selector.
     */
    element<T extends Element>(selector: string | Type<any>): TestElement<T> | null;
    /**
     * Gets all the elements matching the given CSS selector and wraps them into a TestElement. The actual type
     * of the returned elements is the TestElement subclass matching the type of the found element. So, if the
     * matched elements are inputs for example, the method will return an array of TestInput.
     * <p>Usage:</p>
     * <code>
     * const testElements: Array&lt;TestHtmlElement&lt;HTMLDivElement>> = tester.elements('div');
     * </code>
     * @param selector a CSS selector
     * @returns the array of matched elements, empty if no element was matched
     */
    elements<K extends keyof HTMLElementTagNameMap>(selector: K): Array<TestHtmlElement<HTMLElementTagNameMap[K]>>;
    /**
     * Gets all the elements matching the given CSS selector and wraps them into a TestElement. The actual type
     * of the returned elements is the TestElement subclass matching the type of the found element. So, if the
     * matched elements are inputs for example, the method will return an array of TestInput.
     * <p>Usage:</p>
     * <code>
     * const testElements: Array&lt;TestElement&lt;SVGLineElement>> = tester.elements('line');
     * </code>
     * @param selector a CSS selector
     * @returns the array of matched elements, empty if no element was matched
     */
    elements<K extends keyof SVGElementTagNameMap>(selector: K): Array<TestElement<SVGElementTagNameMap[K]>>;
    /**
     * Gets all the elements matching the given selector and wraps them into a TestElement. The actual type
     * of the returned elements is the TestElement subclass matching the type of the found element. So, if the
     * matched elements are inputs for example, the method will return an array of TestInput.
     * <p>Usage:</p>
     * <code>
     * const testElements: Array&lt;TestElement> = tester.elements('.selector');
     * </code>
     * @param selector a CSS or directive selector
     * @returns the array of matched elements, empty if no element was matched
     */
    elements(selector: string | Type<any>): Array<TestElement>;
    /**
     * Gets all the elements matching the given selector and wraps them into a TestElement. The actual type
     * of the returned elements is the TestElement subclass matching the type of the found element. So, if the
     * matched elements are inputs for example, the method will return an array of TestInput.
     * <p>Usage:</p>
     * <code>
     * const testElements: Array&lt;TestInput> = tester.elements&lt;HTMLInputElement>('.selector');
     * </code>
     * @param selector a CSS or directive selector
     * @returns the array of matched elements, empty if no element was matched
     */
    elements<T extends HTMLInputElement>(selector: string | Type<any>): Array<TestInput>;
    /**
     * Gets all the elements matching the given selector and wraps them into a TestElement. The actual type
     * of the returned elements is the TestElement subclass matching the type of the found element. So, if the
     * matched elements are inputs for example, the method will return an array of TestInput.
     * <p>Usage:</p>
     * <code>
     * const testElements: Array&lt;TestTextArea> = tester.elements&lt;HTMLTextAreaElement>('.selector');
     * </code>
     * @param selector a CSS or directive selector
     * @returns the array of matched elements, empty if no element was matched
     */
    elements<T extends HTMLTextAreaElement>(selector: string | Type<any>): Array<TestTextArea>;
    /**
     * Gets all the elements matching the given CSS selector and wraps them into a TestElement. The actual type
     * of the returned elements is the TestElement subclass matching the type of the found element. So, if the
     * matched elements are inputs for example, the method will return an array of TestInput.
     * <p>Usage:</p>
     * <code>
     * const testElements: Array&lt;TestButton> = tester.elements&lt;HTMLButtonElement>('.selector');
     * </code>
     * @param selector a CSS or directive selector
     * @returns the array of matched elements, empty if no element was matched
     */
    elements<T extends HTMLButtonElement>(selector: string | Type<any>): Array<TestButton>;
    /**
     * Gets all the elements matching the given selector and wraps them into a TestElement. The actual type
     * of the returned elements is the TestElement subclass matching the type of the found element. So, if the
     * matched elements are inputs for example, the method will return an array of TestInput.
     * <p>Usage:</p>
     * <code>
     * const testElements: Array&lt;TestSelect> = tester.elements<HTMLSelectElement>('.selector');
     * </code>
     * @param selector a CSS or directive selector
     * @returns the array of matched elements, empty if no element was matched
     */
    elements<T extends HTMLSelectElement>(selector: string | Type<any>): Array<TestSelect>;
    /**
     * Gets all the elements matching the given selector and wraps them into a TestElement. The actual type
     * of the returned elements is the TestElement subclass matching the type of the found element. So, if the
     * matched elements are inputs for example, the method will return an array of TestInput.
     * <p>Usage:</p>
     * <code>
     * const testElements: Array&lt;TestHtmlElement&lt;HTMLDivElement>> = tester.elements&lt;HTMLDivElement>('.selector');
     * </code>
     * @param selector a CSS or directive selector
     * @returns the array of matched elements, empty if no element was matched
     */
    elements<T extends HTMLElement>(selector: string | Type<any>): Array<TestHtmlElement<T>>;
    /**
     * Gets all the elements matching the given selector and wraps them into a TestElement. The actual type
     * of the returned elements is the TestElement subclass matching the type of the found element. So, if the
     * matched elements are inputs for example, the method will return an array of TestInput.
     * <p>Usage:</p>
     * <code>
     * const testElements: Array&lt;TestElement&lt;SVGLineElement>> = tester.elements&lt;SVGLineElement>('.selector');
     * </code>
     * @param selector a CSS or directive selector
     * @returns the array of matched elements, empty if no element was matched
     */
    elements<T extends Element>(selector: string | Type<any>): Array<TestElement<T>>;
    /**
     * Gets the first input matched by the given selector. Throws an Error if the matched element isn't actually an input.
     * @param selector a CSS or directive selector
     * @returns the wrapped input, or null if no element was matched
     */
    input(selector: string | Type<any>): TestInput | null;
    /**
     * Gets the first select matched by the given selector. Throws an Error if the matched element isn't actually a select.
     * @param selector a CSS or directive selector
     * @returns the wrapped select, or null if no element was matched
     */
    select(selector: string | Type<any>): TestSelect | null;
    /**
     * Gets the first textarea matched by the given selector
     * @param selector a CSS or directive selector
     * @returns the wrapped textarea, or null if no element was matched. Throws an Error if the matched element isn't actually a textarea.
     * @throws {Error} if the matched element isn't actually a textarea
     */
    textarea(selector: string | Type<any>): TestTextArea | null;
    /**
     * Gets the first button matched by the given selector. Throws an Error if the matched element isn't actually a button.
     * @param selector a CSS or directive selector
     * @returns the wrapped button, or null if no element was matched
     */
    button(selector: string | Type<any>): TestButton | null;
    /**
     * Gets the first directive matching the given component directive selector and returns its component instance
     * @param selector the selector of a component directive
     */
    component<R>(selector: Type<R>): R;
    /**
     * Gets the directives matching the given component directive selector and returns their component instance
     * @param selector the selector of a component directive
     */
    components<R>(selector: Type<R>): Array<R>;
    /**
     * Gets the first element matching the given selector, then gets the given token from its injector, or null if there is no such token
     * @param selector a CSS or directive selector
     * @param token the token to get from the matched element injector
     */
    token<R>(selector: string | Type<any>, token: ProviderToken<R>): R | null;
    /**
     * Gets the elements matching the given selector, then gets their given token from their injector, or null if there is no such token
     * @param selector a CSS or directive selector
     * @param token the token to get from the matched element injector
     */
    tokens<R>(selector: string | Type<any>, token: ProviderToken<R>): Array<R | null>;
    /**
     * Gets the element matching the given selector, and if found, creates and returns a custom TestElement of the provided
     * type. This is useful to create custom higher-level abstractions similar to TestInput, TestSelect, etc. for
     * custom elements or components.
     * @param selector a CSS or directive selector
     * @param customTestElementType the type of the TestElement subclass that will wrap the found element
     */
    custom<E extends TestElement>(selector: string | Type<any>, customTestElementType: Type<E>): E | null;
    /**
     * Gets the elements matching the given selector, and creates and returns custom TestElements of the provided
     * type. This is useful to create custom higher-level abstractions similar to TestInput, TestSelect, etc. for
     * custom elements or components.
     * @param selector a CSS or directive selector
     * @param customTestElementType the type of the TestElement subclass that will wrap the found elements
     */
    customs<E extends TestElement>(selector: string | Type<any>, customTestElementType: Type<E>): Array<E>;
}

/**
 * A wrapped DOM HTML element, providing additional methods and attributes helping with writing tests
 */
declare class TestHtmlElement<E extends HTMLElement> extends TestElement<E> {
    constructor(tester: ComponentTester<unknown>, debugElement: DebugElement);
    /**
     * Clicks on the wrapped element, then triggers a change detection
     */
    click(): Promise<void>;
    /**
     * Tests if the element is visible, in the same meaning (and implementation) as in jQuery, i.e.
     * present anywhere in the DOM, and visible.
     * An element is not visible typically, if its display style or any of its ancestors display style is none.
     */
    get visible(): boolean;
}

/**
 * A wrapped DOM HTML textarea element, providing additional methods and attributes helping with writing tests
 */
declare class TestTextArea extends TestHtmlElement<HTMLTextAreaElement> {
    constructor(tester: ComponentTester<unknown>, debugElement: DebugElement);
    /**
     * Sets the value of the wrapped textarea, then dispatches an event of type input and triggers a change detection
     * @param value the new value of the textarea
     */
    fillWith(value: string): Promise<void>;
    /**
     * the value of the wrapped textarea
     */
    get value(): string;
    /**
     * the disabled property of the wrapped textarea
     */
    get disabled(): boolean;
}

/**
 * The main entry point of the API. It wraps an Angular ComponentFixture<T>, and gives access to its
 * most used properties and methods. It also allows getting elements wrapped in TestElement (and its subclasses)
 * @param <C> the type of the component to test
 */
declare class ComponentTester<C> {
    /**
     * The test element of the component
     */
    readonly testElement: TestElement<HTMLElement>;
    /**
     * The component fixture of the component
     */
    readonly fixture: ComponentFixture<C>;
    /**
     * The mode used by the ComponentTester
     */
    readonly mode: 'imperative' | 'automatic';
    /**
     * Creates a component fixture of the given type with the TestBed and wraps it into a ComponentTester
     */
    static create<C>(componentType: Type<C>): ComponentTester<C>;
    /**
     * Creates a ComponentFixture for the given component type using the TestBed, and creates a ComponentTester
     * wrapping (and delegating) to this fixture. If a fixture is passed, then delegates to this fixture directly.
     *
     * Note that no `detectChanges()` call is made by this constructor. It's up to the subclass constructor,
     * or to the user of the created ComponentTester, to call `detectChanges()` at least once to trigger change
     * detection. This is necessary because some component templates can only be evaluated once inputs
     * have been set on the component instance.
     *
     * @param arg the type of the component to wrap, or a component fixture to wrap
     */
    constructor(arg: Type<C> | ComponentFixture<C>);
    /**
     * The native DOM host element of the component
     */
    get nativeElement(): HTMLElement;
    /**
     * Gets the instance of the tested component from the wrapped fixture
     */
    get componentInstance(): C;
    /**
     * Gets the debug element from the wrapped fixture
     */
    get debugElement(): DebugElement;
    /**
     * Gets the first element matching the given CSS selector and wraps it into a TestElement. The actual type
     * of the returned value is the TestElement subclass matching the type of the found element. So, if the
     * matched element is an input for example, the method will return a TestInput.
     * <p>Usage:</p>
     * <code>
     * const testElement: TestHtmlElement&lt;HTMLDivElement> | null = tester.element('div');
     * </code>
     * @param selector a CSS selector
     * @returns the wrapped element, or null if no element matches the selector.
     */
    element<K extends keyof HTMLElementTagNameMap>(selector: K): TestHtmlElement<HTMLElementTagNameMap[K]> | null;
    /**
     * Gets the first element matching the given CSS selector and wraps it into a TestElement. The actual type
     * of the returned value is the TestElement subclass matching the type of the found element. So, if the
     * matched element is an input for example, the method will return a TestInput.
     * <p>Usage:</p>
     * <code>
     * const testElement: TestElement&lt;SVGLineElement> | null = tester.element('line');
     * </code>
     * @param selector a CSS selector
     * @returns the wrapped element, or null if no element matches the selector.
     */
    element<K extends keyof SVGElementTagNameMap>(selector: K): TestElement<SVGElementTagNameMap[K]> | null;
    /**
     * Gets the first element matching the given CSS selector and wraps it into a TestElement. The actual type
     * of the returned value is the TestElement subclass matching the type of the found element. So, if the
     * matched element is an input for example, the method will return a TestInput.
     * <p>Usage:</p>
     * <code>
     * const testElement: TestElement | null = tester.element('.selector');
     * </code>
     * @param selector a CSS or directive selector
     * @returns the wrapped element, or null if no element matches the selector.
     */
    element(selector: string | Type<any>): TestElement | null;
    /**
     * Gets the first element matching the given selector and wraps it into a TestElement. The actual type
     * of the returned value is the TestElement subclass matching the type of the found element. So, if the
     * matched element is an input for example, the method will return a TestInput.
     * <p>Usage:</p>
     * <code>
     * const testElement: TestInput | null = tester.element&lt;HTMLInputElement>('.selector');
     * </code>
     * @param selector a CSS or directive selector
     * @returns the wrapped element, or null if no element matches the selector.
     */
    element<T extends HTMLInputElement>(selector: string | Type<any>): TestInput | null;
    /**
     * Gets the first element matching the given selector and wraps it into a TestElement. The actual type
     * of the returned value is the TestElement subclass matching the type of the found element. So, if the
     * matched element is an input for example, the method will return a TestInput.
     * <p>Usage:</p>
     * <code>
     * const testElement: TestTextArea | null = tester.element&lt;HTMLTextAreaElement>('.selector');
     * </code>
     * @param selector a CSS or directive selector
     * @returns the wrapped element, or null if no element matches the selector.
     */
    element<T extends HTMLTextAreaElement>(selector: string | Type<any>): TestTextArea | null;
    /**
     * Gets the first element matching the given selector and wraps it into a TestElement. The actual type
     * of the returned value is the TestElement subclass matching the type of the found element. So, if the
     * matched element is an input for example, the method will return a TestInput.
     * <p>Usage:</p>
     * <code>
     * const testElement: TestSelect | null = tester.element&lt;HTMLSelectElement>('.selector');
     * </code>
     * @param selector a CSS or directive selector
     * @returns the wrapped element, or null if no element matches the selector.
     */
    element<T extends HTMLSelectElement>(selector: string | Type<any>): TestSelect | null;
    /**
     * Gets the first element matching the given selector and wraps it into a TestElement. The actual type
     * of the returned value is the TestElement subclass matching the type of the found element. So, if the
     * matched element is an input for example, the method will return a TestInput.
     * <p>Usage:</p>
     * <code>
     * const testElement: TestButton | null = tester.element&lt;HTMLButtonElement>('.selector');
     * </code>
     * @param selector a CSS or directive selector
     * @returns the wrapped element, or null if no element matches the selector.
     */
    element<T extends HTMLButtonElement>(selector: string | Type<any>): TestButton | null;
    /**
     * Gets the first element matching the given selector and wraps it into a TestElement. The actual type
     * of the returned value is the TestElement subclass matching the type of the found element. So, if the
     * matched element is an input for example, the method will return a TestInput.
     * <p>Usage:</p>
     * <code>
     * const testElement: TestHtmlElement&lt;HTMLDivElement> | null = tester.element&lt;HTMLDivElement>('.selector');
     * </code>
     * @param selector a CSS or directive selector
     * @returns the wrapped element, or null if no element matches the selector.
     */
    element<T extends HTMLElement>(selector: string | Type<any>): TestHtmlElement<T> | null;
    /**
     * Gets the first element matching the given selector and wraps it into a TestElement. The actual type
     * of the returned value is the TestElement subclass matching the type of the found element. So, if the
     * matched element is an input for example, the method will return a TestInput.
     * <p>Usage:</p>
     * <code>
     * const testElement: TestElement&lt;SVGLineElement> | null = tester.element&lt;SVGLineElement>('.selector');
     * </code>
     * @param selector a CSS or directive selector
     * @returns the wrapped element, or null if no element matches the selector.
     */
    element<T extends Element>(selector: string | Type<any>): TestElement<T> | null;
    /**
     * Gets all the elements matching the given CSS selector and wraps them into a TestElement. The actual type
     * of the returned elements is the TestElement subclass matching the type of the found element. So, if the
     * matched elements are inputs for example, the method will return an array of TestInput.
     * <p>Usage:</p>
     * <code>
     * const testElements: Array&lt;TestHtmlElement&lt;HTMLDivElement>> = tester.elements('div');
     * </code>
     * @param selector a CSS selector
     * @returns the array of matched elements, empty if no element was matched
     */
    elements<K extends keyof HTMLElementTagNameMap>(selector: K): Array<TestHtmlElement<HTMLElementTagNameMap[K]>>;
    /**
     * Gets all the elements matching the given CSS selector and wraps them into a TestElement. The actual type
     * of the returned elements is the TestElement subclass matching the type of the found element. So, if the
     * matched elements are inputs for example, the method will return an array of TestInput.
     * <p>Usage:</p>
     * <code>
     * const testElements: Array&lt;TestElement&lt;SVGLineElement>> = tester.elements('line');
     * </code>
     * @param selector a CSS selector
     * @returns the array of matched elements, empty if no element was matched
     */
    elements<K extends keyof SVGElementTagNameMap>(selector: K): Array<TestElement<SVGElementTagNameMap[K]>>;
    /**
     * Gets all the elements matching the given selector and wraps them into a TestElement. The actual type
     * of the returned elements is the TestElement subclass matching the type of the found element. So, if the
     * matched elements are inputs for example, the method will return an array of TestInput.
     * <p>Usage:</p>
     * <code>
     * const testElements: Array&lt;TestElement> = tester.elements('.selector');
     * </code>
     * @param selector a CSS or directive selector
     * @returns the array of matched elements, empty if no element was matched
     */
    elements(selector: string | Type<any>): Array<TestElement>;
    /**
     * Gets all the elements matching the given selector and wraps them into a TestElement. The actual type
     * of the returned elements is the TestElement subclass matching the type of the found element. So, if the
     * matched elements are inputs for example, the method will return an array of TestInput.
     * <p>Usage:</p>
     * <code>
     * const testElements: Array&lt;TestInput> = tester.elements&lt;HTMLInputElement>('.selector');
     * </code>
     * @param selector a CSS or directive selector
     * @returns the array of matched elements, empty if no element was matched
     */
    elements<T extends HTMLInputElement>(selector: string | Type<any>): Array<TestInput>;
    /**
     * Gets all the elements matching the given selector and wraps them into a TestElement. The actual type
     * of the returned elements is the TestElement subclass matching the type of the found element. So, if the
     * matched elements are inputs for example, the method will return an array of TestInput.
     * <p>Usage:</p>
     * <code>
     * const testElements: Array&lt;TestTextArea> = tester.elements&lt;HTMLTextAreaElement>('.selector');
     * </code>
     * @param selector a CSS or directive selector
     * @returns the array of matched elements, empty if no element was matched
     */
    elements<T extends HTMLTextAreaElement>(selector: string | Type<any>): Array<TestTextArea>;
    /**
     * Gets all the elements matching the given CSS selector and wraps them into a TestElement. The actual type
     * of the returned elements is the TestElement subclass matching the type of the found element. So, if the
     * matched elements are inputs for example, the method will return an array of TestInput.
     * <p>Usage:</p>
     * <code>
     * const testElements: Array&lt;TestButton> = tester.elements&lt;HTMLButtonElement>('.selector');
     * </code>
     * @param selector a CSS or directive selector
     * @returns the array of matched elements, empty if no element was matched
     */
    elements<T extends HTMLButtonElement>(selector: string | Type<any>): Array<TestButton>;
    /**
     * Gets all the elements matching the given selector and wraps them into a TestElement. The actual type
     * of the returned elements is the TestElement subclass matching the type of the found element. So, if the
     * matched elements are inputs for example, the method will return an array of TestInput.
     * <p>Usage:</p>
     * <code>
     * const testElements: Array&lt;TestSelect> = tester.elements<HTMLSelectElement>('.selector');
     * </code>
     * @param selector a CSS or directive selector
     * @returns the array of matched elements, empty if no element was matched
     */
    elements<T extends HTMLSelectElement>(selector: string | Type<any>): Array<TestSelect>;
    /**
     * Gets all the elements matching the given selector and wraps them into a TestElement. The actual type
     * of the returned elements is the TestElement subclass matching the type of the found element. So, if the
     * matched elements are inputs for example, the method will return an array of TestInput.
     * <p>Usage:</p>
     * <code>
     * const testElements: Array&lt;TestHtmlElement&lt;HTMLDivElement>> = tester.elements&lt;HTMLDivElement>('.selector');
     * </code>
     * @param selector a CSS or directive selector
     * @returns the array of matched elements, empty if no element was matched
     */
    elements<T extends HTMLElement>(selector: string | Type<any>): Array<TestHtmlElement<T>>;
    /**
     * Gets all the elements matching the given selector and wraps them into a TestElement. The actual type
     * of the returned elements is the TestElement subclass matching the type of the found element. So, if the
     * matched elements are inputs for example, the method will return an array of TestInput.
     * <p>Usage:</p>
     * <code>
     * const testElements: Array&lt;TestElement&lt;SVGLineElement>> = tester.elements&lt;SVGLineElement>('.selector');
     * </code>
     * @param selector a CSS or directive selector
     * @returns the array of matched elements, empty if no element was matched
     */
    elements<T extends Element>(selector: string | Type<any>): Array<TestElement<T>>;
    /**
     * Gets the first input matched by the given selector. Throws an Error if the matched element isn't actually an input.
     * @param selector a CSS or directive selector
     * @returns the wrapped input, or null if no element was matched
     */
    input(selector: string | Type<any>): TestInput | null;
    /**
     * Gets the first select matched by the given selector. Throws an Error if the matched element isn't actually a select.
     * @param selector a CSS or directive selector
     * @returns the wrapped select, or null if no element was matched
     */
    select(selector: string | Type<any>): TestSelect | null;
    /**
     * Gets the first textarea matched by the given selector
     * @param selector a CSS or directive selector
     * @returns the wrapped textarea, or null if no element was matched. Throws an Error if the matched element isn't actually a textarea.
     * @throws {Error} if the matched element isn't actually a textarea
     */
    textarea(selector: string | Type<any>): TestTextArea | null;
    /**
     * Gets the first button matched by the given selector. Throws an Error if the matched element isn't actually a button.
     * @param selector a CSS or directive selector
     * @returns the wrapped button, or null if no element was matched
     */
    button(selector: string | Type<any>): TestButton | null;
    /**
     * Gets the first directive matching the given component directive selector and returns its component instance
     * @param selector the selector of a component directive
     */
    component<R>(selector: Type<R>): R;
    /**
     * Gets the directives matching the given component directive selector and returns their component instance
     * @param selector the selector of a component directive
     */
    components<R>(selector: Type<R>): Array<R>;
    /**
     * Gets the first element matching the given selector, then gets the given token from its injector, or null if there is no such token
     * @param selector a CSS or directive selector
     * @param token the token to get from the matched element injector
     */
    token<R>(selector: string | Type<any>, token: ProviderToken<R>): R | null;
    /**
     * Gets the elements matching the given selector, then gets their given token from their injector, or null if there is no such token
     * @param selector a CSS or directive selector
     * @param token the token to get from the matched element injector
     */
    tokens<R>(selector: string | Type<any>, token: ProviderToken<R>): Array<R | null>;
    /**
     * Gets the element matching the given selector, and if found, creates and returns a custom TestElement of the provided
     * type. This is useful to create custom higher-level abstractions similar to TestInput, TestSelect, etc. for
     * custom elements or components.
     * @param selector a CSS or directive selector
     * @param customTestElementType the type of the TestElement subclass that will wrap the found element
     */
    custom<E extends TestElement>(selector: string | Type<any>, customTestElementType: Type<E>): E | null;
    /**
     * Gets the elements matching the given selector, and creates and returns custom TestElements of the provided
     * type. This is useful to create custom higher-level abstractions similar to TestInput, TestSelect, etc. for
     * custom elements or components.
     * @param selector a CSS or directive selector
     * @param customTestElementType the type of the TestElement subclass that will wrap the found elements
     */
    customs<E extends TestElement>(selector: string | Type<any>, customTestElementType: Type<E>): Array<E>;
    /**
     * Triggers a change detection using the wrapped fixture in imperative mode.
     * Throws an error in autodetection mode.
     * You should generally prever
     */
    detectChanges(checkNoChanges?: boolean): void;
    /**
     * In imperative mode, runs change detection.
     * In automatic mode, awaits stability.
     */
    change(): Promise<void>;
    /**
     * Delegates to the wrapped fixture whenStable and, in imperative mode, detect changes
     */
    stable(): Promise<void>;
}

/**
 * A thin wrapper around Angular RouterTestingHarness which helps testing routed components.
 * It allows, based on a configured testing module where the router is provided, to initially navigate
 * to a given route, then test the routed component. It's then possible to either navigate again with
 * the wrapped harness, or to use the component to trigger navigation, and test that the URL has changed
 * for example.
 */
declare class RoutingTester extends ComponentTester<unknown> {
    readonly harness: RouterTestingHarness;
    constructor(harness: RouterTestingHarness);
    /**
     * Creates a RouterTestngHarness and uses it to navigate to the given URL
     * @param url the URL to initially navigate to.
     * @return a promise which resolves to a RoutingTester which wraps the harness
     * and its fixture.
     */
    static forUrl(url: string): Promise<RoutingTester>;
    /**
     * Gets the current URL of the Router service as a string
     */
    get url(): string;
    /**
     * Gets the current URL of the Router service as an UrlTree, to be able to test its
     * elements (query params, etc.)
     */
    get urlTree(): UrlTree;
}

/**
 * The options that are passed when creating an ActivatedRouteStub.
 */
interface ActivatedRouteStubOptions {
    /**
     * The initial values of the parameters of the route
     */
    params?: Params;
    /**
     * The initial values of the query parameters of the route
     */
    queryParams?: Params;
    /**
     * The initial values of the data of the route
     */
    data?: Data;
    /**
     * The initial values of the title of the route
     */
    title?: string;
    /**
     * The initial fragment of the route
     */
    fragment?: string | null;
    /**
     * The initial url of the route
     */
    url?: Array<UrlSegment>;
    /**
     * The parent of the route
     */
    parent?: ActivatedRouteStub | null;
    /**
     * The first child of the route
     */
    firstChild?: ActivatedRouteStub | null;
    /**
     * The children of the route
     */
    children?: Array<ActivatedRouteStub> | null;
    /**
     * The configuration of the route
     */
    routeConfig?: Route | null;
}
/**
 * A stub for ActivatedRoute. It behaves almost the same way as the actual ActivatedRoute, exposing a snapshot
 * and observables for the params, query params etc., which are kept in sync.
 *
 * In addition, this stub allows simulating a navigation by changing the params, the query params, the fragment, etc.
 * When that happens, the snapshot is modified, then the relevant observables emit the new values.
 *
 * There are some things that don't really work the same way as the real ActivatedRoute though:
 * - the handling of the firstChild and of the children is entirely under the tester's responsibility. Setting the parent
 *   of a route stub does not add this route to the children of its parent, for example.
 * - when changing the params, query params, fragment, etc., their associated observable emits unconditionally, instead of
 *   first checking if the value is actually different from before. It's thus the responsibility of the tester to not
 *   change the values if they're the same as before.
 * - the params, paramMap, queryParams and queryParamMap objects of the route snapshot change when params or query params are set
 *   on the stub route. So if the code keeps a reference to params or paramMaps, it won't see the changes.
 */
declare class ActivatedRouteStub extends ActivatedRoute {
    private _firstChild;
    private _children;
    private readonly paramsSubject;
    private readonly queryParamsSubject;
    private readonly dataSubject;
    private readonly fragmentSubject;
    private readonly urlSubject;
    private readonly titleSubject;
    private _parent;
    private _root;
    private _pathFromRoot;
    /**
     * Constructs a new instance, based on the given options.
     * If an option is not provided (or if no option is provided at all), then the route has a default value for this option
     * (empty parameters for example, null fragment, etc.)
     * If no parent is passed, then this route has no parent and is thus set as the root. Otherwise, the root and the path
     * from root are created based on the root and path from root of the given parent route.
     */
    constructor(options?: ActivatedRouteStubOptions);
    get root(): ActivatedRouteStub;
    get parent(): ActivatedRouteStub | null;
    get pathFromRoot(): Array<ActivatedRouteStub>;
    get firstChild(): ActivatedRouteStub | null;
    get children(): Array<ActivatedRouteStub>;
    get routeConfig(): Route | null;
    /**
     * Triggers a navigation with the given new parameters. All the other parts (query params etc.) stay as they are.
     * This is a shortcut to `triggerNavigation` that can be used to only change the parameters.
     */
    setParams(params: Params): void;
    /**
     * Triggers a navigation with the given new parameter. The other parameters, as well as all the other parts (query params etc.)
     * stay as they are.
     * This is a shortcut to `triggerNavigation` that can be used to only change one parameter.
     */
    setParam(name: string, value: string): void;
    /**
     * Triggers a navigation with the given new query parameters. All the other parts (params etc.) stay as the are.
     * This is a shortcut to `triggerNavigation` that can be used to only change the query parameters.
     */
    setQueryParams(queryParams: Params): void;
    /**
     * Triggers a navigation with the given new parameter. The other query parameters, as well as all the other parts (params etc.)
     * stay as the are.
     * This is a shortcut to `triggerNavigation` that can be used to only change one query parameter.
     */
    setQueryParam(name: string, value: string): void;
    /**
     * Triggers a navigation with the given new data. The other parameters, as well as all the other parts (params etc.)
     * stay as the are.
     * This is a shortcut to `triggerNavigation` that can be used to only change the data.
     */
    setData(data: Data): void;
    /**
     * Triggers a navigation with the given new data item. The other data, as well as all the other parts (params etc.)
     * stay as the are.
     * This is a shortcut to `triggerNavigation` that can be used to only change one data item.
     */
    setDataItem(name: string, value: unknown): void;
    /**
     * Triggers a navigation with the given new title. The other parameters, as well as all the other parts (params etc.)
     * stay as the are.
     * This is a shortcut to `triggerNavigation` that can be used to only change the title.
     */
    setTitle(title: string | undefined): void;
    /**
     * Triggers a navigation with the given new fragment. The other parts (params etc.)  stay as the are.
     * This is a shortcut to `triggerNavigation` that can be used to only change the fragment.
     */
    setFragment(fragment: string | null): void;
    /**
     * Triggers a navigation with the given new url. The other parts (params etc.)  stay as the are.
     * This is a shortcut to `triggerNavigation` that can be used to only change the url.
     */
    setUrl(url: Array<UrlSegment>): void;
    /**
     * Triggers a navigation based on the given options. If an option is undefined or null, it's ignored. Except for fragment, which is only
     * ignored if it's undefined, because null is a valid value for a fragment.
     *
     * The non-ignored values are used to change the snapshot of the route. Once the snapshot has been modified,
     * the observables corresponding to the updated parts emit the new value.
     *
     * So, setting params and query params will make the params and queryParams observables emit, but not the fragment, data and
     * url observables for example. This is consistent to how the router behaves.
     *
     * Note: since the title of a route can become undefined, in order to be able to distinguish between a navigation which leaves the title
     * as it is and a navigation that sets the title to undefined, a wrapper object is used for the title. So
     *
     * - `triggerNavigation({ params:... })` leaves the title as is because it's undefined in the options
     * - `triggerNavigation({ title: { value: 'test' } })` sets the title to 'test'
     * - `triggerNavigation({ title: { value: undefined } })` sets the title to undefined
     */
    triggerNavigation(options: {
        params?: Params;
        queryParams?: Params;
        fragment?: string | null;
        data?: Data | null;
        title?: {
            value: string | undefined;
        } | null;
        url?: Array<UrlSegment> | null;
    }): void;
    toString(): string;
}
/**
 * Creates a new ActivatedRouteStub, by calling its constructor.
 */
declare function stubRoute(options?: ActivatedRouteStubOptions): ActivatedRouteStub;

declare const speculoosMatchers: jasmine.CustomMatcherFactories;

/**
 * Creates a spy object for a class where all the methods of the class (and of its superclasses) are spies.
 * I.e., for a class `UserService` with methods `get()`, `create()`, `update()` and `delete()`, calling
 * `createMock(UserService)` is equivalent to calling
 * `jasmine.createSpyObj<UserService>('UserService', ['get', 'create', 'update', 'delete'])`.
 * @param type the type to mock (usually a service class)
 */
declare function createMock<T>(type: Type<T>): jasmine.SpyObj<T>;

/**
 * Provide function which returns the provider `{ provide: ComponentFixtureAutoDetect, useValue: true }`.
 * This provider can be added to the testing module to configure the component testers
 * (and the underlying ComponentFixture) in automatic mode:
 *
 * ```
 * TestBed.configureTestingModule({ providers: [provideAutomaticChangeDetection()] });
 * ```
 */
declare function provideAutomaticChangeDetection(): EnvironmentProviders;

export { ActivatedRouteStub, ComponentTester, RoutingTester, TestButton, TestElement, TestHtmlElement, TestInput, TestSelect, TestTextArea, createMock, provideAutomaticChangeDetection, speculoosMatchers, stubRoute };
export type { ActivatedRouteStubOptions };
