createFakeScheduler
Стабильный · с 0.1.0
Независящий от тест-раннера виртуальный clock. После install() globalThis.setTimeout и clearTimeout подменяются, так что ни один реальный таймер не выстреливает — вместо этого advance(ms) гоняет каждый обратный вызов, который становится готов в окне. Полезно для тестов цепочек actions.debounce / throttle / defer без флака await new Promise(setTimeout, …).
Зависимости от vi.useFakeTimers() Vitest’а нет — работает одинаково в чистом node:test, Jest и обычном Vitest.
import { createFakeScheduler } from '@triggery/testing';
Сигнатура
Заголовок раздела «Сигнатура»function createFakeScheduler(): FakeScheduler;
interface FakeScheduler {
install(): void;
uninstall(): void;
now(): number;
advance(ms: number): Promise<void>;
flushAll(): Promise<void>;
pending(): number;
}| Метод | Описание |
|---|---|
install() | Подменить globalThis.setTimeout / clearTimeout на фейковый контроллер. Идемпотентно. |
uninstall() | Восстановить оригиналы, очистить ожидающие таймеры, сбросить виртуальные часы в 0. Безопасно звать многократно. |
now() | Текущее значение виртуальных часов в мс с момента install. |
advance(ms) | Сдвинуть часы вперёд на ms и прогнать каждый таймер, ставший готовым в этом окне. После — сливает микротаски. |
flushAll() | Прогнать каждый ожидающий таймер независимо от запланированного времени. Полезно для “забить на часы, посмотреть, что в итоге произойдёт”. |
pending() | Сколько таймеров ещё ожидает. |
Примеры
Заголовок раздела «Примеры»Debounce сливается после ожидания
Заголовок раздела «Debounce сливается после ожидания»import { createTrigger function createTrigger<S extends TriggerSchema>(config: CreateTriggerConfig<S>, runtime?: Runtime): Trigger<S>Imperative form. Pass the trigger config; returns a live `Trigger<S>`
registered with the runtime. The chainable builder form lives in the
`@triggery/core/builder` subpath — import from there if you want
`createTrigger<S>().require(...).handle(...)` with auto-narrowing. } from '@triggery/core';
import { createFakeScheduler function createFakeScheduler(): FakeScheduler , createTestRuntime function createTestRuntime(options?: TestRuntimeOptions): TestRuntime } from '@triggery/testing';
import { afterEach function afterEach<ExtraContext = object>(fn: AfterEachListener<ExtraContext>, timeout?: number): voidRegisters a callback function to be executed after each test within the current suite has completed.
This hook is useful for scenarios where you need to clean up or reset the test environment after each test runs, such as deleting temporary files, clearing test-specific database entries, or resetting mocked functions.
**Note:** The `afterEach` hooks are running in reverse order of their registration. You can configure this by changing the `sequence.hooks` option in the config file.@paramfn - The callback function to be executed after each test. This function receives an `TestContext` parameter if additional test context is needed.@paramtimeout - Optional timeout in milliseconds for the hook. If not provided, the default hook timeout from the runner's configuration is used.@returns@example```ts
// Example of using afterEach to delete temporary files created during a test
afterEach(async () => {
await fileSystem.deleteTempFiles();
});
``` , beforeEach function beforeEach<ExtraContext = object>(fn: BeforeEachListener<ExtraContext>, timeout?: number): voidRegisters a callback function to be executed before each test within the current suite.
This hook is useful for scenarios where you need to reset or reinitialize the test environment before each test runs, such as resetting database states, clearing caches, or reinitializing variables.
**Note:** The `beforeEach` hooks are executed in the order they are defined one after another. You can configure this by changing the `sequence.hooks` option in the config file.@paramfn - The callback function to be executed before each test. This function receives an `TestContext` parameter if additional test context is needed.@paramtimeout - Optional timeout in milliseconds for the hook. If not provided, the default hook timeout from the runner's configuration is used.@returns@example```ts
// Example of using beforeEach to reset a database state
beforeEach(async () => {
await database.reset();
});
``` , expect const expect: ExpectStatic , it const it: TestAPIDefines a test case with a given name and test function. The test function can optionally be configured with test options.@paramname - The name of the test or a function that will be used as a test name.@paramoptionsOrFn - Optional. The test options or the test function if no explicit name is provided.@paramoptionsOrTest - Optional. The test function or options, depending on the previous parameters.@throws{Error} If called inside another test function.@example```ts
// Define a simple test
it('adds two numbers', () => {
expect(add(1, 2)).toBe(3);
});
```@example```ts
// Define a test with options
it('subtracts two numbers', { retry: 3 }, () => {
expect(subtract(5, 2)).toBe(3);
});
``` , vi const vi: VitestUtils } from 'vitest';
const ft const ft: FakeScheduler = createFakeScheduler function createFakeScheduler(): FakeScheduler ();
beforeEach beforeEach<object>(fn: BeforeEachListener<object>, timeout?: number): voidRegisters a callback function to be executed before each test within the current suite.
This hook is useful for scenarios where you need to reset or reinitialize the test environment before each test runs, such as resetting database states, clearing caches, or reinitializing variables.
**Note:** The `beforeEach` hooks are executed in the order they are defined one after another. You can configure this by changing the `sequence.hooks` option in the config file.@paramfn - The callback function to be executed before each test. This function receives an `TestContext` parameter if additional test context is needed.@paramtimeout - Optional timeout in milliseconds for the hook. If not provided, the default hook timeout from the runner's configuration is used.@returns@example```ts
// Example of using beforeEach to reset a database state
beforeEach(async () => {
await database.reset();
});
``` (() => ft const ft: FakeScheduler .install FakeScheduler.install(): voidReplace globalThis.setTimeout / clearTimeout with the fake controller. ());
afterEach afterEach<object>(fn: AfterEachListener<object>, timeout?: number): voidRegisters a callback function to be executed after each test within the current suite has completed.
This hook is useful for scenarios where you need to clean up or reset the test environment after each test runs, such as deleting temporary files, clearing test-specific database entries, or resetting mocked functions.
**Note:** The `afterEach` hooks are running in reverse order of their registration. You can configure this by changing the `sequence.hooks` option in the config file.@paramfn - The callback function to be executed after each test. This function receives an `TestContext` parameter if additional test context is needed.@paramtimeout - Optional timeout in milliseconds for the hook. If not provided, the default hook timeout from the runner's configuration is used.@returns@example```ts
// Example of using afterEach to delete temporary files created during a test
afterEach(async () => {
await fileSystem.deleteTempFiles();
});
``` (() => ft const ft: FakeScheduler .uninstall FakeScheduler.uninstall(): voidRestore the real timer functions. Safe to call multiple times. ());
it it<object>(name: string | Function, fn?: TestFunction<object> | undefined, options?: number): void (+1 overload)Defines a test case with a given name and test function. The test function can optionally be configured with test options.@paramname - The name of the test or a function that will be used as a test name.@paramoptionsOrFn - Optional. The test options or the test function if no explicit name is provided.@paramoptionsOrTest - Optional. The test function or options, depending on the previous parameters.@throws{Error} If called inside another test function.@example```ts
// Define a simple test
it('adds two numbers', () => {
expect(add(1, 2)).toBe(3);
});
```@example```ts
// Define a test with options
it('subtracts two numbers', { retry: 3 }, () => {
expect(subtract(5, 2)).toBe(3);
});
``` ('debounces keystrokes', async () => {
const rt const rt: TestRuntime = createTestRuntime function createTestRuntime(options?: TestRuntimeOptions): TestRuntime ();
const t const t: Trigger<{
events: {
keystroke: string;
};
actions: {
search: string;
};
}>
= createTrigger createTrigger<{
events: {
keystroke: string;
};
actions: {
search: string;
};
}>(config: CreateTriggerConfig<{
events: {
keystroke: string;
};
actions: {
search: string;
};
}>, runtime?: Runtime): Trigger<{
events: {
keystroke: string;
};
actions: {
search: string;
};
}>
Imperative form. Pass the trigger config; returns a live `Trigger<S>`
registered with the runtime. The chainable builder form lives in the
`@triggery/core/builder` subpath — import from there if you want
`createTrigger<S>().require(...).handle(...)` with auto-narrowing. <{
events events: {
keystroke: string;
}
: { keystroke keystroke: string : string };
actions actions: {
search: string;
}
: { search search: string : string };
}>(
{
id id: string : 'demo',
events events: readonly "keystroke"[] : ['keystroke'],
handler handler: TriggerHandler<{
events: {
keystroke: string;
};
actions: {
search: string;
};
}, never>
({ event event: {
readonly name: "keystroke";
readonly payload: string;
}
, actions actions: ActionsCtx<{
search: string;
}>
}) {
actions actions: ActionsCtx<{
search: string;
}>
.debounce function debounce(ms: number): ActionsCtx<{
search: string;
}>
(300).search search?: ((payload: string) => void) | undefined ?.(event event: {
readonly name: "keystroke";
readonly payload: string;
}
.payload payload: string );
},
},
rt const rt: TestRuntime ,
);
const search const search: Mock<Procedure> = vi const vi: VitestUtils .fn VitestUtils.fn: <Procedure>(originalImplementation?: Procedure | undefined) => Mock<Procedure>Creates a spy on a function, though can be initiated without one. Every time a function is invoked, it stores its call arguments, returns, and instances. Also, you can manipulate its behavior with [methods](https://vitest.dev/api/mock).
If no function is given, mock will return `undefined`, when invoked.@example```ts
const getApples = vi.fn(() => 0)
getApples()
expect(getApples).toHaveBeenCalled()
expect(getApples).toHaveReturnedWith(0)
getApples.mockReturnValueOnce(5)
expect(getApples()).toBe(5)
expect(getApples).toHaveNthReturnedWith(2, 5)
``` ();
rt const rt: TestRuntime .mockAction mockAction<{
events: {
keystroke: string;
};
actions: {
search: string;
};
}, "search">(trigger: Trigger<{
events: {
keystroke: string;
};
actions: {
search: string;
};
}>, name: "search", handler: (payload: string) => void): RegistrationToken
Register an action handler — typically a `vi.fn()`. (t const t: Trigger<{
events: {
keystroke: string;
};
actions: {
search: string;
};
}>
, 'search', search const search: Mock<Procedure> );
rt const rt: TestRuntime .fireSync function fireSync(eventName: string, payload?: unknown): voidRun dispatch synchronously (for tests and benchmarks). ('keystroke', 'a');
rt const rt: TestRuntime .fireSync function fireSync(eventName: string, payload?: unknown): voidRun dispatch synchronously (for tests and benchmarks). ('keystroke', 'ab');
rt const rt: TestRuntime .fireSync function fireSync(eventName: string, payload?: unknown): voidRun dispatch synchronously (for tests and benchmarks). ('keystroke', 'abc');
await ft const ft: FakeScheduler .advance FakeScheduler.advance(ms: number): Promise<void>Advance the virtual clock by `ms` and run every timer that becomes due in
that window. Returns a promise that resolves after pending microtasks are
drained, so callers can `await ft.advance(N)` and then assert. (299);
expect expect<Mock<Procedure>>(actual: Mock<Procedure>, message?: string): Assertion<Mock<Procedure>> (+1 overload) (search const search: Mock<Procedure> ).not not: Assertion<Mock<Procedure>> .toHaveBeenCalled JestAssertion<Mock<Procedure>>.toHaveBeenCalled: () => voidEnsures that a mock function is called.
Also under the alias `expect.toBeCalled`.@exampleexpect(mockFunc).toHaveBeenCalled(); ();
await ft const ft: FakeScheduler .advance FakeScheduler.advance(ms: number): Promise<void>Advance the virtual clock by `ms` and run every timer that becomes due in
that window. Returns a promise that resolves after pending microtasks are
drained, so callers can `await ft.advance(N)` and then assert. (1);
expect expect<Mock<Procedure>>(actual: Mock<Procedure>, message?: string): Assertion<Mock<Procedure>> (+1 overload) (search const search: Mock<Procedure> ).toHaveBeenCalledExactlyOnceWith Assertion<Mock<Procedure>>.toHaveBeenCalledExactlyOnceWith: <[string]>(args_0: string) => voidEnsure that a mock function is called with specific arguments and called
exactly once.@exampleexpect(mockFunc).toHaveBeenCalledExactlyOnceWith('arg1', 42); ('abc');
});Окно throttle
Заголовок раздела «Окно throttle»import { createFakeScheduler function createFakeScheduler(): FakeScheduler } from '@triggery/testing';
import { expect const expect: ExpectStatic , it const it: TestAPIDefines a test case with a given name and test function. The test function can optionally be configured with test options.@paramname - The name of the test or a function that will be used as a test name.@paramoptionsOrFn - Optional. The test options or the test function if no explicit name is provided.@paramoptionsOrTest - Optional. The test function or options, depending on the previous parameters.@throws{Error} If called inside another test function.@example```ts
// Define a simple test
it('adds two numbers', () => {
expect(add(1, 2)).toBe(3);
});
```@example```ts
// Define a test with options
it('subtracts two numbers', { retry: 3 }, () => {
expect(subtract(5, 2)).toBe(3);
});
``` } from 'vitest';
it it<object>(name: string | Function, fn?: TestFunction<object> | undefined, options?: number): void (+1 overload)Defines a test case with a given name and test function. The test function can optionally be configured with test options.@paramname - The name of the test or a function that will be used as a test name.@paramoptionsOrFn - Optional. The test options or the test function if no explicit name is provided.@paramoptionsOrTest - Optional. The test function or options, depending on the previous parameters.@throws{Error} If called inside another test function.@example```ts
// Define a simple test
it('adds two numbers', () => {
expect(add(1, 2)).toBe(3);
});
```@example```ts
// Define a test with options
it('subtracts two numbers', { retry: 3 }, () => {
expect(subtract(5, 2)).toBe(3);
});
``` ('runs at most one timer per window', async () => {
const ft const ft: FakeScheduler = createFakeScheduler function createFakeScheduler(): FakeScheduler ();
ft const ft: FakeScheduler .install FakeScheduler.install(): voidReplace globalThis.setTimeout / clearTimeout with the fake controller. ();
try {
let calls let calls: number = 0;
setTimeout function setTimeout<[]>(callback: () => void, delay?: number): NodeJS.Timeout (+1 overload)[MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/setTimeout) (() => calls let calls: number ++, 100);
setTimeout function setTimeout<[]>(callback: () => void, delay?: number): NodeJS.Timeout (+1 overload)[MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/setTimeout) (() => calls let calls: number ++, 200);
setTimeout function setTimeout<[]>(callback: () => void, delay?: number): NodeJS.Timeout (+1 overload)[MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/setTimeout) (() => calls let calls: number ++, 300);
expect expect<number>(actual: number, message?: string): Assertion<number> (+1 overload) (ft const ft: FakeScheduler .pending FakeScheduler.pending(): numberNumber of timers still pending. ()).toBe JestAssertion<number>.toBe: <number>(expected: number) => voidChecks that a value is what you expect. It calls `Object.is` to compare values.
Don't use `toBe` with floating-point numbers.@exampleexpect(result).toBe(42);
expect(status).toBe(true); (3);
await ft const ft: FakeScheduler .advance FakeScheduler.advance(ms: number): Promise<void>Advance the virtual clock by `ms` and run every timer that becomes due in
that window. Returns a promise that resolves after pending microtasks are
drained, so callers can `await ft.advance(N)` and then assert. (150);
expect expect<number>(actual: number, message?: string): Assertion<number> (+1 overload) (calls let calls: number ).toBe JestAssertion<number>.toBe: <number>(expected: number) => voidChecks that a value is what you expect. It calls `Object.is` to compare values.
Don't use `toBe` with floating-point numbers.@exampleexpect(result).toBe(42);
expect(status).toBe(true); (1);
await ft const ft: FakeScheduler .flushAll FakeScheduler.flushAll(): Promise<void>Run every pending timer (regardless of its scheduled time). Useful for
"give up on the clock, just see what eventually happens". ();
expect expect<number>(actual: number, message?: string): Assertion<number> (+1 overload) (calls let calls: number ).toBe JestAssertion<number>.toBe: <number>(expected: number) => voidChecks that a value is what you expect. It calls `Object.is` to compare values.
Don't use `toBe` with floating-point numbers.@exampleexpect(result).toBe(42);
expect(status).toBe(true); (3);
expect expect<number>(actual: number, message?: string): Assertion<number> (+1 overload) (ft const ft: FakeScheduler .pending FakeScheduler.pending(): numberNumber of timers still pending. ()).toBe JestAssertion<number>.toBe: <number>(expected: number) => voidChecks that a value is what you expect. It calls `Object.is` to compare values.
Don't use `toBe` with floating-point numbers.@exampleexpect(result).toBe(42);
expect(status).toBe(true); (0);
} finally {
ft const ft: FakeScheduler .uninstall FakeScheduler.uninstall(): voidRestore the real timer functions. Safe to call multiple times. ();
}
});import { createTrigger function createTrigger<S extends TriggerSchema>(config: CreateTriggerConfig<S>, runtime?: Runtime): Trigger<S>Imperative form. Pass the trigger config; returns a live `Trigger<S>`
registered with the runtime. The chainable builder form lives in the
`@triggery/core/builder` subpath — import from there if you want
`createTrigger<S>().require(...).handle(...)` with auto-narrowing. } from '@triggery/core';
import { createFakeScheduler function createFakeScheduler(): FakeScheduler , createTestRuntime function createTestRuntime(options?: TestRuntimeOptions): TestRuntime } from '@triggery/testing';
import { expect const expect: ExpectStatic , it const it: TestAPIDefines a test case with a given name and test function. The test function can optionally be configured with test options.@paramname - The name of the test or a function that will be used as a test name.@paramoptionsOrFn - Optional. The test options or the test function if no explicit name is provided.@paramoptionsOrTest - Optional. The test function or options, depending on the previous parameters.@throws{Error} If called inside another test function.@example```ts
// Define a simple test
it('adds two numbers', () => {
expect(add(1, 2)).toBe(3);
});
```@example```ts
// Define a test with options
it('subtracts two numbers', { retry: 3 }, () => {
expect(subtract(5, 2)).toBe(3);
});
``` , vi const vi: VitestUtils } from 'vitest';
it it<object>(name: string | Function, fn?: TestFunction<object> | undefined, options?: number): void (+1 overload)Defines a test case with a given name and test function. The test function can optionally be configured with test options.@paramname - The name of the test or a function that will be used as a test name.@paramoptionsOrFn - Optional. The test options or the test function if no explicit name is provided.@paramoptionsOrTest - Optional. The test function or options, depending on the previous parameters.@throws{Error} If called inside another test function.@example```ts
// Define a simple test
it('adds two numbers', () => {
expect(add(1, 2)).toBe(3);
});
```@example```ts
// Define a test with options
it('subtracts two numbers', { retry: 3 }, () => {
expect(subtract(5, 2)).toBe(3);
});
``` ('defers an action by a fixed delay', async () => {
const ft const ft: FakeScheduler = createFakeScheduler function createFakeScheduler(): FakeScheduler ();
ft const ft: FakeScheduler .install FakeScheduler.install(): voidReplace globalThis.setTimeout / clearTimeout with the fake controller. ();
try {
const rt const rt: TestRuntime = createTestRuntime function createTestRuntime(options?: TestRuntimeOptions): TestRuntime ();
const t const t: Trigger<{
events: {
ping: void;
};
actions: {
log: void;
};
}>
= createTrigger createTrigger<{
events: {
ping: void;
};
actions: {
log: void;
};
}>(config: CreateTriggerConfig<{
events: {
ping: void;
};
actions: {
log: void;
};
}>, runtime?: Runtime): Trigger<{
events: {
ping: void;
};
actions: {
log: void;
};
}>
Imperative form. Pass the trigger config; returns a live `Trigger<S>`
registered with the runtime. The chainable builder form lives in the
`@triggery/core/builder` subpath — import from there if you want
`createTrigger<S>().require(...).handle(...)` with auto-narrowing. <{
events events: {
ping: void;
}
: { ping ping: void : void };
actions actions: {
log: void;
}
: { log log: void : void };
}>(
{
id id: string : 'demo',
events events: readonly "ping"[] : ['ping'],
handler handler: TriggerHandler<{
events: {
ping: void;
};
actions: {
log: void;
};
}, never>
({ actions actions: ActionsCtx<{
log: void;
}>
}) {
actions actions: ActionsCtx<{
log: void;
}>
.defer function defer(ms: number): ActionsCtx<{
log: void;
}>
(500).log log?: (() => void) | undefined ?.();
},
},
rt const rt: TestRuntime ,
);
const log const log: Mock<Procedure> = vi const vi: VitestUtils .fn VitestUtils.fn: <Procedure>(originalImplementation?: Procedure | undefined) => Mock<Procedure>Creates a spy on a function, though can be initiated without one. Every time a function is invoked, it stores its call arguments, returns, and instances. Also, you can manipulate its behavior with [methods](https://vitest.dev/api/mock).
If no function is given, mock will return `undefined`, when invoked.@example```ts
const getApples = vi.fn(() => 0)
getApples()
expect(getApples).toHaveBeenCalled()
expect(getApples).toHaveReturnedWith(0)
getApples.mockReturnValueOnce(5)
expect(getApples()).toBe(5)
expect(getApples).toHaveNthReturnedWith(2, 5)
``` ();
rt const rt: TestRuntime .mockAction mockAction<{
events: {
ping: void;
};
actions: {
log: void;
};
}, "log">(trigger: Trigger<{
events: {
ping: void;
};
actions: {
log: void;
};
}>, name: "log", handler: () => void): RegistrationToken
Register an action handler — typically a `vi.fn()`. (t const t: Trigger<{
events: {
ping: void;
};
actions: {
log: void;
};
}>
, 'log', log const log: Mock<Procedure> );
rt const rt: TestRuntime .fireSync function fireSync(eventName: string, payload?: unknown): voidRun dispatch synchronously (for tests and benchmarks). ('ping');
await ft const ft: FakeScheduler .advance FakeScheduler.advance(ms: number): Promise<void>Advance the virtual clock by `ms` and run every timer that becomes due in
that window. Returns a promise that resolves after pending microtasks are
drained, so callers can `await ft.advance(N)` and then assert. (499);
expect expect<Mock<Procedure>>(actual: Mock<Procedure>, message?: string): Assertion<Mock<Procedure>> (+1 overload) (log const log: Mock<Procedure> ).not not: Assertion<Mock<Procedure>> .toHaveBeenCalled JestAssertion<Mock<Procedure>>.toHaveBeenCalled: () => voidEnsures that a mock function is called.
Also under the alias `expect.toBeCalled`.@exampleexpect(mockFunc).toHaveBeenCalled(); ();
await ft const ft: FakeScheduler .advance FakeScheduler.advance(ms: number): Promise<void>Advance the virtual clock by `ms` and run every timer that becomes due in
that window. Returns a promise that resolves after pending microtasks are
drained, so callers can `await ft.advance(N)` and then assert. (1);
expect expect<Mock<Procedure>>(actual: Mock<Procedure>, message?: string): Assertion<Mock<Procedure>> (+1 overload) (log const log: Mock<Procedure> ).toHaveBeenCalledOnce Assertion<Mock<Procedure>>.toHaveBeenCalledOnce: () => voidAsserts that a mock function was called exactly once.@exampleexpect(mockFunc).toHaveBeenCalledOnce(); ();
} finally {
ft const ft: FakeScheduler .uninstall FakeScheduler.uninstall(): voidRestore the real timer functions. Safe to call multiple times. ();
}
});Опрос часов
Заголовок раздела «Опрос часов»import { createFakeScheduler function createFakeScheduler(): FakeScheduler } from '@triggery/testing';
const ft const ft: FakeScheduler = createFakeScheduler function createFakeScheduler(): FakeScheduler ();
ft const ft: FakeScheduler .install FakeScheduler.install(): voidReplace globalThis.setTimeout / clearTimeout with the fake controller. ();
setTimeout function setTimeout<[]>(callback: () => void, delay?: number): NodeJS.Timeout (+1 overload)[MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/setTimeout) (() => {}, 250);
console var console: Console .log Console.log(...data: any[]): voidThe **`console.log()`** static method outputs a message to the console.
[MDN Reference](https://developer.mozilla.org/docs/Web/API/console/log_static) (ft const ft: FakeScheduler .now FakeScheduler.now(): numberCurrent virtual clock value, in ms since install. ()); // 0
console var console: Console .log Console.log(...data: any[]): voidThe **`console.log()`** static method outputs a message to the console.
[MDN Reference](https://developer.mozilla.org/docs/Web/API/console/log_static) (ft const ft: FakeScheduler .pending FakeScheduler.pending(): numberNumber of timers still pending. ()); // 1
await ft const ft: FakeScheduler .advance FakeScheduler.advance(ms: number): Promise<void>Advance the virtual clock by `ms` and run every timer that becomes due in
that window. Returns a promise that resolves after pending microtasks are
drained, so callers can `await ft.advance(N)` and then assert. (250);
console var console: Console .log Console.log(...data: any[]): voidThe **`console.log()`** static method outputs a message to the console.
[MDN Reference](https://developer.mozilla.org/docs/Web/API/console/log_static) (ft const ft: FakeScheduler .now FakeScheduler.now(): numberCurrent virtual clock value, in ms since install. ()); // 250
console var console: Console .log Console.log(...data: any[]): voidThe **`console.log()`** static method outputs a message to the console.
[MDN Reference](https://developer.mozilla.org/docs/Web/API/console/log_static) (ft const ft: FakeScheduler .pending FakeScheduler.pending(): numberNumber of timers still pending. ()); // 0
ft const ft: FakeScheduler .uninstall FakeScheduler.uninstall(): voidRestore the real timer functions. Safe to call multiple times. ();Замечания
Заголовок раздела «Замечания»См. также
Заголовок раздела «См. также» createTestRuntime Парься с тестовым рантаймом для тестов триггеров.
flushMicrotasks Слить микротаски (без перехвата таймеров).
createScheduler Настоящий планировщик рантайма — то, что мы подменяем.
Руководство по debounce и throttle Когда использовать debounce / throttle / defer в обработчиках.