Files
effect-view/packages/effect-fc-next/test/Async.test.tsx
T
Julien Valverdé faac021527
Lint / lint (push) Failing after 42s
Fix Async
2026-07-23 04:58:41 +02:00

64 lines
2.3 KiB
TypeScript

import { act, fireEvent, render, screen } from "@testing-library/react"
import { Effect, Layer } from "effect"
import * as React from "react"
import { describe, expect, it, vi } from "vitest"
import * as Async from "../src/Async.js"
import * as Component from "../src/Component.js"
import * as Memoized from "../src/Memoized.js"
import * as ReactRuntime from "../src/ReactRuntime.js"
describe("Async", () => {
it("does not rerun for an unrelated parent state update", async () => {
const load = vi.fn((_id: number) => Effect.never)
const renderPost = vi.fn()
const runtime = ReactRuntime.make(Layer.empty)
const context = await runtime.runtime.context()
const Post = Component.make("Post")(function*(props: { readonly id: number }) {
renderPost()
const value = yield* Component.useOnChange(() => load(props.id), [props.id])
return <div>{value}</div>
}).pipe(
Async.async,
Memoized.memoized,
)
const Parent = Component.make("Parent")(function*() {
const [text, setText] = React.useState("")
const AsyncPost = yield* Post.use
return <>
<input
aria-label="text"
value={text}
onChange={event => setText(event.currentTarget.value)}
/>
<AsyncPost id={1} fallback={<div>loading</div>} />
</>
}).pipe(Component.withContext(runtime.context))
let view!: ReturnType<typeof render>
await act(async () => {
view = render(
<runtime.context.Provider value={context}>
<Parent />
</runtime.context.Provider>,
)
})
expect(screen.getByText("loading")).toBeTruthy()
expect(load).toHaveBeenCalledTimes(2)
const callsAfterLoad = load.mock.calls.length
const rendersAfterLoad = renderPost.mock.calls.length
await act(async () => {
fireEvent.change(screen.getByLabelText("text"), { target: { value: "a" } })
})
expect(load).toHaveBeenCalledTimes(callsAfterLoad)
expect(renderPost).toHaveBeenCalledTimes(rendersAfterLoad)
view.unmount()
await runtime.runtime.dispose()
})
})