import { Directionality } from '@angular/cdk/bidi';
import * as i0 from '@angular/core';
import { signal, makeEnvironmentProviders, NgZone, EventEmitter, Injectable } from '@angular/core';
import { TestBed } from '@angular/core/testing';
import { Subject } from 'rxjs';

/**
 * Use of this source code is governed by an MIT-style license that can be
 * found in the LICENSE file at https://github.com/NG-ZORRO/ng-zorro-antd/blob/master/LICENSE
 */
class MockDirectionality {
    value = 'ltr';
    change = new Subject();
    valueSignal = signal('ltr', /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "valueSignal" }] : /* istanbul ignore next */ []));
}
function provideMockDirectionality() {
    return makeEnvironmentProviders([{ provide: Directionality, useClass: MockDirectionality }]);
}
/**
 * Creates a `describe('RTL', ...)` block that verifies the component correctly toggles
 * an RTL CSS class when `Directionality.valueSignal` changes between 'ltr' and 'rtl'.
 *
 * Must be called at the top level of a spec file (outside any `describe` that has its own
 * `beforeEach` configuring TestBed), because it configures its own TestBed internally.
 *
 * @param componentFn Thunk returning the component class. Using a thunk avoids class hoisting
 *   issues — class declarations defined below the call site would be `undefined` at registration time.
 * @param predicate A `By.directive(...)` or `By.css(...)` predicate to locate the element
 *   that carries the RTL class. Use `By.css` when the RTL class is on a child element rather
 *   than the component host.
 * @param classnamePrefix The class prefix (e.g. `'ant-alert'`). The test asserts the presence
 *   of `${classnamePrefix}-rtl`.
 * @param options.detectChangesFn Custom change detection callback for components that need
 *   imperative updates beyond `fixture.detectChanges()` (e.g. calling a private method).
 * @param options.providers Additional providers needed by the component (e.g. `provideNzIconsTesting()`).
 */
function testDirectionality(componentFn, predicate, classnamePrefix, options) {
    const rtlClass = `${classnamePrefix}-rtl`;
    describe('RTL', () => {
        let fixture;
        let dir;
        function detectChanges() {
            if (options?.detectChangesFn) {
                options.detectChangesFn(fixture);
            }
            else {
                fixture.detectChanges();
            }
        }
        beforeEach(() => {
            TestBed.configureTestingModule({
                providers: [provideMockDirectionality(), ...(options?.providers || [])]
            });
            dir = TestBed.inject(Directionality);
            fixture = TestBed.createComponent(componentFn());
        });
        it('should className correct on dir change', async () => {
            detectChanges();
            fixture.autoDetectChanges();
            await fixture.whenStable();
            const debugElement = fixture.debugElement.query(predicate);
            expect(debugElement).toBeTruthy();
            expect(debugElement.nativeElement.classList.contains(rtlClass)).toBe(false);
            dir.valueSignal.set('rtl');
            detectChanges();
            await fixture.whenStable();
            expect(debugElement.nativeElement.classList.contains(rtlClass)).toBe(true);
            dir.valueSignal.set('ltr');
            detectChanges();
            await fixture.whenStable();
            expect(debugElement.nativeElement.classList.contains(rtlClass)).toBe(false);
        });
    });
}

/**
 * Use of this source code is governed by an MIT-style license that can be
 * found in the LICENSE file at https://github.com/NG-ZORRO/ng-zorro-antd/blob/master/LICENSE
 */
/** Creates a browser MouseEvent with the specified options. */
function createMouseEvent(type, x = 0, y = 0, button = 0) {
    const event = document.createEvent('MouseEvent');
    event.initMouseEvent(type, true /* canBubble */, false /* cancelable */, window /* view */, 0 /* detail */, x /* screenX */, y /* screenY */, x /* clientX */, y /* clientY */, false /* ctrlKey */, false /* altKey */, false /* shiftKey */, false /* metaKey */, button /* button */, null /* relatedTarget */);
    // `initMouseEvent` doesn't allow us to pass the `buttons` and
    // defaults it to 0 which looks like a fake event.
    Object.defineProperty(event, 'buttons', { get: () => 1 });
    return event;
}
/** Creates a browser TouchEvent with the specified pointer coordinates. */
function createTouchEvent(type, pageX = 0, pageY = 0) {
    // In favor of creating events that work for most of the browsers, the event is created
    // as a basic UI Event. The necessary details for the event will be set manually.
    const event = new UIEvent(type, { detail: 0, view: window });
    const touchDetails = { pageX, pageY, clientX: pageX, clientY: pageY };
    // Most of the browsers don't have a "initTouchEvent" method that can be used to define
    // the touch details.
    Object.defineProperties(event, {
        touches: { value: [touchDetails] },
        targetTouches: { value: [touchDetails] },
        changedTouches: { value: [touchDetails] }
    });
    return event;
}
/** Dispatches a keydown event from an element. */
function createKeyboardEvent(type, keyCode, target, key, ctrlKey, metaKey, shiftKey) {
    const event = document.createEvent('KeyboardEvent');
    // Firefox does not support `initKeyboardEvent`, but supports `initKeyEvent`.
    if (event.initKeyEvent) {
        event.initKeyEvent(type, true, true, window, 0, 0, 0, 0, 0, keyCode);
    }
    else {
        event.initKeyboardEvent(type, true, true, window, 0, key, 0, '', false);
    }
    // Webkit Browsers don't set the keyCode when calling the init function.
    // See related bug https://bugs.webkit.org/show_bug.cgi?id=16735
    Object.defineProperties(event, {
        keyCode: { get: () => keyCode },
        key: { get: () => key },
        target: { get: () => target },
        ctrlKey: { get: () => ctrlKey },
        metaKey: { get: () => metaKey },
        shiftKey: { get: () => shiftKey }
    });
    return event;
}
/** Creates a fake event object with any desired event type. */
function createFakeEvent(type, canBubble = true, cancelable = true) {
    const event = document.createEvent('Event');
    event.initEvent(type, canBubble, cancelable);
    return event;
}

/**
 * Use of this source code is governed by an MIT-style license that can be
 * found in the LICENSE file at https://github.com/NG-ZORRO/ng-zorro-antd/blob/master/LICENSE
 */
/** Utility to dispatch any event on a Node. */
function dispatchEvent(node, event) {
    node.dispatchEvent(event);
    return event;
}
/** Shorthand to dispatch a fake event on a specified node. */
function dispatchFakeEvent(node, type, canBubble) {
    return dispatchEvent(node, createFakeEvent(type, canBubble));
}
/** Shorthand to dispatch a keyboard event with a specified key code. */
function dispatchKeyboardEvent(node, type, keyCode, target) {
    return dispatchEvent(node, createKeyboardEvent(type, keyCode, target));
}
/** Shorthand to dispatch a mouse event on the specified coordinates. */
function dispatchMouseEvent(node, type, x = 0, y = 0, event = createMouseEvent(type, x, y)) {
    return dispatchEvent(node, event);
}
/** Shorthand to dispatch a touch event on the specified coordinates. */
function dispatchTouchEvent(node, type, x = 0, y = 0) {
    return dispatchEvent(node, createTouchEvent(type, x, y));
}

/**
 * Use of this source code is governed by an MIT-style license that can be
 * found in the LICENSE file at https://github.com/NG-ZORRO/ng-zorro-antd/blob/master/LICENSE
 */
/**
 * Mock synchronous NgZone implementation that can be used
 * to flush out `onStable` subscriptions in tests.
 *
 * via: https://github.com/angular/angular/blob/master/packages/core/testing/src/ng_zone_mock.ts
 *
 * @docs-private
 */
class MockNgZone extends NgZone {
    onStable = new EventEmitter(false);
    constructor() {
        super({ enableLongStackTrace: false });
    }
    run(fn) {
        return fn();
    }
    runOutsideAngular(fn) {
        return fn();
    }
    simulateZoneExit() {
        this.onStable.emit(null);
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: MockNgZone, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
    static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: MockNgZone });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: MockNgZone, decorators: [{
            type: Injectable
        }], ctorParameters: () => [] });

/**
 * Use of this source code is governed by an MIT-style license that can be
 * found in the LICENSE file at https://github.com/NG-ZORRO/ng-zorro-antd/blob/master/LICENSE
 */
/**
 * Focuses an input, sets its value and dispatches
 * the `input` event, simulating the user typing.
 *
 * @param value Value to be set on the input.
 * @param element Element onto which to set the value.
 */
function typeInElement(value, element) {
    element.focus();
    element.value = value;
    dispatchFakeEvent(element, 'input');
}

/**
 * Use of this source code is governed by an MIT-style license that can be
 * found in the LICENSE file at https://github.com/NG-ZORRO/ng-zorro-antd/blob/master/LICENSE
 */
function sleep(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
}
function nextAnimationFrame() {
    return sleep(16);
}
async function updateNonSignalsInput(fixture, ms) {
    fixture.changeDetectorRef.markForCheck();
    if (typeof ms === 'number') {
        await sleep(ms);
    }
    await fixture.whenStable();
}

/**
 * Use of this source code is governed by an MIT-style license that can be
 * found in the LICENSE file at https://github.com/NG-ZORRO/ng-zorro-antd/blob/master/LICENSE
 */

/**
 * Generated bundle index. Do not edit.
 */

export { MockNgZone, createFakeEvent, createKeyboardEvent, createMouseEvent, createTouchEvent, dispatchEvent, dispatchFakeEvent, dispatchKeyboardEvent, dispatchMouseEvent, dispatchTouchEvent, nextAnimationFrame, provideMockDirectionality, sleep, testDirectionality, typeInElement, updateNonSignalsInput };
//# sourceMappingURL=ng-zorro-antd-core-testing.mjs.map
