190 lines
5.0 KiB
TypeScript
190 lines
5.0 KiB
TypeScript
/* @vitest-environment jsdom */
|
|
|
|
import { act, type ReactNode } from "react";
|
|
import { createRoot, type Root } from "react-dom/client";
|
|
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
|
|
const instances = vi.hoisted(() => ({
|
|
chat: 0,
|
|
payment: 0,
|
|
privateZone: 0,
|
|
}));
|
|
|
|
vi.mock("@/stores/chat/chat-context", async () => {
|
|
const { createElement, useState } = await import("react");
|
|
return {
|
|
ChatProvider({
|
|
characterId,
|
|
children,
|
|
}: {
|
|
characterId: string;
|
|
children: ReactNode;
|
|
}) {
|
|
const [instanceId] = useState(() => ++instances.chat);
|
|
return createElement(
|
|
"div",
|
|
{
|
|
"data-character-id": characterId,
|
|
"data-instance-id": instanceId,
|
|
"data-testid": "chat-provider",
|
|
},
|
|
children,
|
|
);
|
|
},
|
|
};
|
|
});
|
|
|
|
vi.mock("@/stores/payment/payment-context", async () => {
|
|
const { createElement, useState } = await import("react");
|
|
return {
|
|
PaymentProvider({ children }: { children: ReactNode }) {
|
|
const [instanceId] = useState(() => ++instances.payment);
|
|
return createElement(
|
|
"div",
|
|
{
|
|
"data-instance-id": instanceId,
|
|
"data-testid": "payment-provider",
|
|
},
|
|
children,
|
|
);
|
|
},
|
|
};
|
|
});
|
|
|
|
vi.mock("@/stores/private-zone", async () => {
|
|
const { createElement, useState } = await import("react");
|
|
return {
|
|
PrivateZoneProvider({
|
|
characterId,
|
|
children,
|
|
}: {
|
|
characterId: string;
|
|
children: ReactNode;
|
|
}) {
|
|
const [instanceId] = useState(() => ++instances.privateZone);
|
|
return createElement(
|
|
"div",
|
|
{
|
|
"data-character-id": characterId,
|
|
"data-instance-id": instanceId,
|
|
"data-testid": "private-zone-provider",
|
|
},
|
|
children,
|
|
);
|
|
},
|
|
};
|
|
});
|
|
|
|
vi.mock("@/stores/sync/chat-auth-sync", () => ({ ChatAuthSync: () => null }));
|
|
vi.mock("@/stores/sync/chat-payment-success-sync", () => ({
|
|
ChatPaymentSuccessSync: () => null,
|
|
}));
|
|
vi.mock("@/stores/sync/payment-success-sync", () => ({
|
|
PaymentSuccessSync: () => null,
|
|
}));
|
|
|
|
import { ChatRouteProviders } from "@/providers/chat-route-providers";
|
|
import { PaymentRouteProvider } from "@/providers/payment-route-provider";
|
|
import { PrivateZoneRouteProvider } from "@/providers/private-zone-route-provider";
|
|
|
|
describe("character actor route providers", () => {
|
|
let container: HTMLDivElement;
|
|
let root: Root;
|
|
|
|
beforeEach(() => {
|
|
instances.chat = 0;
|
|
instances.payment = 0;
|
|
instances.privateZone = 0;
|
|
(globalThis as { IS_REACT_ACT_ENVIRONMENT?: boolean })
|
|
.IS_REACT_ACT_ENVIRONMENT = true;
|
|
container = document.createElement("div");
|
|
document.body.append(container);
|
|
root = createRoot(container);
|
|
});
|
|
|
|
afterEach(() => {
|
|
act(() => root.unmount());
|
|
container.remove();
|
|
});
|
|
|
|
it("recreates chat and chat payment actors when the character changes", () => {
|
|
renderChat("elio");
|
|
const firstChatInstance = instanceId("chat-provider");
|
|
const firstPaymentInstance = instanceId("payment-provider");
|
|
|
|
renderChat("maya-tan");
|
|
|
|
expect(instanceId("chat-provider")).not.toBe(firstChatInstance);
|
|
expect(instanceId("payment-provider")).not.toBe(firstPaymentInstance);
|
|
expect(testNode("chat-provider").dataset.characterId).toBe(
|
|
"maya-tan",
|
|
);
|
|
});
|
|
|
|
it("recreates the private-zone actor when the character changes", () => {
|
|
renderPrivateZone("elio");
|
|
const firstInstance = instanceId("private-zone-provider");
|
|
|
|
renderPrivateZone("maya-tan");
|
|
|
|
expect(instanceId("private-zone-provider")).not.toBe(firstInstance);
|
|
expect(testNode("private-zone-provider").dataset.characterId).toBe(
|
|
"maya-tan",
|
|
);
|
|
});
|
|
|
|
it("recreates the route payment actor when its character scope changes", () => {
|
|
renderPayment("elio");
|
|
const firstInstance = instanceId("payment-provider");
|
|
|
|
renderPayment("maya-tan");
|
|
|
|
expect(instanceId("payment-provider")).not.toBe(firstInstance);
|
|
});
|
|
|
|
function renderChat(characterId: string): void {
|
|
act(() => {
|
|
root.render(
|
|
<ChatRouteProviders
|
|
characterId={characterId}
|
|
emptyChatGreeting={`Hello from ${characterId}`}
|
|
>
|
|
<span>chat</span>
|
|
</ChatRouteProviders>,
|
|
);
|
|
});
|
|
}
|
|
|
|
function renderPrivateZone(characterId: string): void {
|
|
act(() => {
|
|
root.render(
|
|
<PrivateZoneRouteProvider characterId={characterId}>
|
|
<span>private zone</span>
|
|
</PrivateZoneRouteProvider>,
|
|
);
|
|
});
|
|
}
|
|
|
|
function renderPayment(scopeKey: string): void {
|
|
act(() => {
|
|
root.render(
|
|
<PaymentRouteProvider scopeKey={scopeKey}>
|
|
<span>payment</span>
|
|
</PaymentRouteProvider>,
|
|
);
|
|
});
|
|
}
|
|
|
|
function testNode(testId: string): HTMLElement {
|
|
const node = container.querySelector<HTMLElement>(
|
|
`[data-testid="${testId}"]`,
|
|
);
|
|
if (!node) throw new Error(`Missing ${testId}`);
|
|
return node;
|
|
}
|
|
|
|
function instanceId(testId: string): string | undefined {
|
|
return testNode(testId).dataset.instanceId;
|
|
}
|
|
});
|