import { Clock } from "@effect/core/io/Clock/definition"; import { Duration } from "@tsplus/stdlib/data/Duration"; import { Effect } from "@effect/core/io/Effect/definition"; import { List } from "@tsplus/stdlib/collections/List/definition"; import { Tag } from "@tsplus/stdlib/service/Tag"; import type * as D from "@effect/core/testing/TestClock/Data"; import type * as S from "@effect/core/testing/TestClock/Sleep"; /** * A `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.test.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.test.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. * * @tsplus type effect/core/testing/TestClock */ export interface TestClock extends Clock { readonly adjust: (duration: Duration) => Effect; readonly adjustWith: (duration: Duration) => (effect: Effect) => Effect; readonly setTime: (time: number) => Effect; readonly save: Effect>; readonly sleeps: Effect>; } export declare namespace TestClock { type Data = D.Data; type Sleep = S.Sleep; } /** * @tsplus type effect/core/testing/TestClock.Ops */ export interface TestClockOps { readonly Tag: Tag; } export declare const TestClock: TestClockOps; //# sourceMappingURL=definition.d.ts.map