@@ -1,5 +1,5 @@
|
||||
import { act, fireEvent, render, screen, waitFor } from "@testing-library/react"
|
||||
import { Context, Effect, HashMap, Layer, Ref } from "effect"
|
||||
import { Context, Effect, HashMap, Layer, SubscriptionRef } from "effect"
|
||||
import * as React from "react"
|
||||
import { afterEach, describe, expect, it, vi } from "vitest"
|
||||
import * as Component from "../src/Component.js"
|
||||
@@ -362,7 +362,7 @@ describe("Component", () => {
|
||||
await runtime.runtime.dispose()
|
||||
})
|
||||
|
||||
it.fails("does not commit effects or retain registered scopes for a discarded Suspense render", async () => {
|
||||
it("does not commit effects or retain registered scopes for a discarded Suspense render", async () => {
|
||||
const setup = vi.fn()
|
||||
const runtime = ReactRuntime.make(Layer.empty)
|
||||
const effectRuntime = await runtime.runtime.context()
|
||||
@@ -391,7 +391,7 @@ describe("Component", () => {
|
||||
try {
|
||||
await screen.findByText("fallback")
|
||||
expect(setup).not.toHaveBeenCalled()
|
||||
expect(HashMap.size(Effect.runSync(Ref.get(scopeRegistry.ref)))).toBe(0)
|
||||
await waitFor(() => expect(HashMap.size(Effect.runSync(SubscriptionRef.get(scopeRegistry.ref)))).toBe(0))
|
||||
}
|
||||
finally {
|
||||
view.unmount()
|
||||
@@ -399,7 +399,45 @@ describe("Component", () => {
|
||||
}
|
||||
})
|
||||
|
||||
it.fails("clears ScopeRegistry after a suspended render retries, commits, and unmounts", async () => {
|
||||
it("keeps committed scopes alive without heartbeats", async () => {
|
||||
const acquisitions = vi.fn()
|
||||
const releases = vi.fn()
|
||||
const runtime = ReactRuntime.make(Layer.empty)
|
||||
const effectRuntime = await runtime.runtime.context()
|
||||
const scopeRegistry = Context.get(effectRuntime, ScopeRegistry.ScopeRegistry)
|
||||
|
||||
const Probe = Component.makeUntraced("CommittedScopeProbe")(function*() {
|
||||
yield* Component.useOnMount(() => Effect.gen(function*() {
|
||||
yield* Effect.sync(acquisitions)
|
||||
yield* Effect.addFinalizer(() => Effect.sync(releases))
|
||||
}))
|
||||
|
||||
return <div>committed</div>
|
||||
}).pipe(
|
||||
Component.withOptions({ finalizerExecutionDebounce: "10 millis" }),
|
||||
Component.withContext(runtime.context),
|
||||
)
|
||||
|
||||
const view = render(
|
||||
<runtime.context.Provider value={effectRuntime}>
|
||||
<Probe />
|
||||
</runtime.context.Provider>
|
||||
)
|
||||
|
||||
await screen.findByText("committed")
|
||||
await waitFor(() => expect(releases).toHaveBeenCalledTimes(acquisitions.mock.calls.length - 1))
|
||||
await new Promise(resolve => setTimeout(resolve, 30))
|
||||
|
||||
expect(HashMap.size(Effect.runSync(SubscriptionRef.get(scopeRegistry.ref)))).toBe(1)
|
||||
expect(releases).toHaveBeenCalledTimes(acquisitions.mock.calls.length - 1)
|
||||
|
||||
view.unmount()
|
||||
await waitFor(() => expect(releases).toHaveBeenCalledTimes(acquisitions.mock.calls.length))
|
||||
await waitFor(() => expect(HashMap.size(Effect.runSync(SubscriptionRef.get(scopeRegistry.ref)))).toBe(0))
|
||||
await runtime.runtime.dispose()
|
||||
})
|
||||
|
||||
it("clears ScopeRegistry after a suspended render retries, commits, and unmounts", async () => {
|
||||
const lifecycle = vi.fn<(message: string) => void>()
|
||||
const runtime = ReactRuntime.make(Layer.empty)
|
||||
const effectRuntime = await runtime.runtime.context()
|
||||
@@ -441,7 +479,7 @@ describe("Component", () => {
|
||||
await waitFor(() => expect(lifecycle).toHaveBeenCalledWith("mount"))
|
||||
|
||||
view.unmount()
|
||||
await waitFor(() => expect(HashMap.size(Effect.runSync(Ref.get(scopeRegistry.ref)))).toBe(0))
|
||||
await waitFor(() => expect(HashMap.size(Effect.runSync(SubscriptionRef.get(scopeRegistry.ref)))).toBe(0))
|
||||
expect(lifecycle.mock.calls.filter(([message]) => message === "mount")).toHaveLength(2)
|
||||
expect(lifecycle.mock.calls.filter(([message]) => message === "cleanup")).toHaveLength(2)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user