import * as Clock from "../../Clock/index.js"; import * as HashMap from "../../Collections/Immutable/HashMap/index.js"; import * as List from "../../Collections/Immutable/List/index.js"; import * as SortedSet from "../../Collections/Immutable/SortedSet/index.js"; import * as Tuple from "../../Collections/Immutable/Tuple/index.js"; import * as T from "../../Effect/index.js"; import * as Fiber from "../../Fiber/index.js"; import type { Has } from "../../Has/index.js"; import * as L from "../../Layer/index.js"; import * as Promise from "../../Promise/index.js"; import * as Ref from "../../Ref/index.js"; import * as RefM from "../../RefM/index.js"; import { Annotations } from "../Annotations/index.js"; import { Live } from "../Live/index.js"; import type { Restorable } from "../Restorable/index.js"; export interface DurationBrand { readonly DurationBrand: unique symbol; } export declare type Duration = number & DurationBrand; export declare function Duration(n: number): Duration; /** * `TestClock` makes it easy to deterministically and efficiently test * effects involving the passage of time. * * Instead of waiting for actual time to pass, `sleep` and methods * implemented in terms of it schedule effects to take place at a given clock * time. Users can adjust the clock time using the `adjust` and `setTime` * methods, and all effects scheduled to take place on or before that time * will automatically be run in order. * * For example, here is how we can test `ZIO#timeout` using `TestClock: * * {{{ * import zio.ZIO * import zio.duration._ * import zio.test.environment.TestClock * * for { * fiber <- ZIO.sleep(5.minutes).timeout(1.minute).fork * _ <- TestClock.adjust(1.minute) * result <- fiber.join * } yield result == None * }}} * * Note how we forked the fiber that `sleep` was invoked on. Calls to `sleep` * and methods derived from it will semantically block until the time is set * to on or after the time they are scheduled to run. If we didn't fork the * fiber on which we called sleep we would never get to set the time on the * line below. Thus, a useful pattern when using `TestClock` is to fork the * effect being tested, then adjust the clock time, and finally verify that * the expected effects have been performed. * * For example, here is how we can test an effect that recurs with a fixed * delay: * * {{{ * import zio.Queue * import zio.duration._ * import zio.test.environment.TestClock * * for { * q <- Queue.unbounded[Unit] * _ <- q.offer(()).delay(60.minutes).forever.fork * a <- q.poll.map(_.isEmpty) * _ <- TestClock.adjust(60.minutes) * b <- q.take.as(true) * c <- q.poll.map(_.isEmpty) * _ <- TestClock.adjust(60.minutes) * d <- q.take.as(true) * e <- q.poll.map(_.isEmpty) * } yield a && b && c && d && e * }}} * * Here we verify that no effect is performed before the recurrence period, * that an effect is performed after the recurrence period, and that the * effect is performed exactly once. The key thing to note here is that after * each recurrence the next recurrence is scheduled to occur at the * appropriate time in the future, so when we adjust the clock by 60 minutes * exactly one value is placed in the queue, and when we adjust the clock by * another 60 minutes exactly one more value is placed in the queue. */ export interface TestClock extends Restorable { readonly serviceId: Clock.ClockId; readonly adjust: (duration: number) => T.UIO; readonly setTime: (duration: number) => T.UIO; readonly sleeps: T.UIO>; } export declare const TestClock: import("../../Has/index.js").Tag; declare const Data_base: import("../../Case/index.js").CaseConstructorTagged<"Data", "_tag">; /** * `Data` represents the state of the `TestClock`, including the clock time */ export declare class Data extends Data_base<{ readonly duration: Duration; readonly sleeps: List.List]>>; }> { } /** * `WarningData` describes the state of the warning message that is * displayed if a test is using time by is not advancing the `TestClock`. * The possible states are `Start` if a test has not used time, `Pending` * if a test has used time but has not adjusted the `TestClock`, and `Done` * if a test has adjusted the `TestClock` or the warning message has * already been displayed. */ export declare type WarningData = Start | Done | Pending; declare const Start_base: import("../../Case/index.js").CaseConstructorADT; export declare class Start extends Start_base<{}> { } declare const Done_base: import("../../Case/index.js").CaseConstructorADT; export declare class Done extends Done_base<{}> { } declare const Pending_base: import("../../Case/index.js").CaseConstructorADT; export declare class Pending extends Pending_base<{ readonly fiber: Fiber.Fiber; }> { } export declare class Test implements TestClock { readonly clockState: Ref.Ref; readonly live: Live; readonly annotations: Annotations; readonly warningState: RefM.RefM; readonly serviceId: Clock.ClockId; constructor(clockState: Ref.Ref, live: Live, annotations: Annotations, warningState: RefM.RefM); /** * Increments the current clock time by the specified duration. Any * effects that were scheduled to occur on or before the new time will be * run in order. */ readonly adjust: (duration: number) => T.UIO; /** * Returns the current clock time. */ readonly currentTime: T.UIO; /** * Saves the `TestClock`'s current state in an effect which, when run, * will restore the `TestClock` state to the saved state */ readonly save: T.UIO>; /** * Sets the current clock time to the specified time in terms of duration * since the epoch. Any effects that were scheduled to occur on or before * the new time will immediately be run in order. */ readonly setTime: (duration: number) => T.UIO; /** * Semantically blocks the current fiber until the clock time is equal * to or greater than the specified duration. Once the clock time is * adjusted to on or after the duration, the fiber will automatically be * resumed. */ readonly sleep: (duration: Duration) => T.UIO; /** * Returns a list of the times at which all queued effects are scheduled * to resume. */ readonly sleeps: T.UIO>; /** * The warning message that will be displayed if a test is using time but * is not advancing the `TestClock`. */ private warning; /** * Forks a fiber that will display a warning message if a test is using * time but is not advancing the `TestClock`. */ private warningStart; /** * Cancels the warning message that is displayed if a test is using time * but is not advancing the `TestClock`. */ readonly warningDone: T.UIO; /** * Returns a set of all fibers in this test. */ readonly supervisedFibers: T.UIO>>; /** * Captures a "snapshot" of the identifier and status of all fibers in * this test other than the current fiber. Fails with the `Unit` value if * any of these fibers are not done or suspended. Note that because we * cannot synchronize on the status of multiple fibers at the same time * this snapshot may not be fully consistent. */ readonly freeze: T.IO>; /** * Delays for a short period of time. */ readonly delay: T.Effect; /** * Returns whether all descendants of this fiber are done or suspended. */ readonly suspended: T.IO>; /** * Polls until all descendants of this fiber are done or suspended. */ readonly awaitSuspended: T.UIO; /** * Runs all effects scheduled to occur on or before the specified * duration, which may depend on the current time, in order. */ private run; } export declare function live(data: Data): L.Layer & Has, never, Has & Has>; export declare const defaultTestClock: L.Layer & Has, never, Has & Has>; export {}; //# sourceMappingURL=index.d.ts.map