74 lines
2.7 KiB
TypeScript
74 lines
2.7 KiB
TypeScript
import { render, screen } from "@testing-library/react";
|
|
import { act } from "react";
|
|
import { describe, expect, it } from "vitest";
|
|
import { ApiError } from "../src/api/client";
|
|
import { loadLastState, saveLastState, useConnection } from "../src/state/connection";
|
|
import { fetchPlayerState } from "../src/state/player";
|
|
import { Button } from "../src/ui";
|
|
import { fakeApi, samplePlayerState } from "./render";
|
|
|
|
const networkDown = () => {
|
|
throw new TypeError("Failed to fetch");
|
|
};
|
|
|
|
describe("offline cache (Step 11.2)", () => {
|
|
it("keeps each fetched state and goes online", async () => {
|
|
const state = samplePlayerState();
|
|
await expect(fetchPlayerState(fakeApi({ getPlayerState: () => state }))).resolves.toEqual(
|
|
state,
|
|
);
|
|
expect(loadLastState()?.state).toEqual(state);
|
|
expect(useConnection.getState()).toMatchObject({ online: true });
|
|
});
|
|
|
|
it("returns the last state when the server can't be reached, and goes offline", async () => {
|
|
const state = samplePlayerState({ playerId: "cached" });
|
|
saveLastState(state, 1234);
|
|
await expect(fetchPlayerState(fakeApi({ getPlayerState: networkDown }))).resolves.toEqual(
|
|
state,
|
|
);
|
|
expect(useConnection.getState()).toEqual({ online: false, lastUpdate: 1234 });
|
|
});
|
|
|
|
it("still fails a first load offline with nothing saved", async () => {
|
|
await expect(fetchPlayerState(fakeApi({ getPlayerState: networkDown }))).rejects.toThrow();
|
|
});
|
|
|
|
it("does not fall back on a server error reply, only on no reply", async () => {
|
|
saveLastState(samplePlayerState(), 1);
|
|
const failing = fakeApi({
|
|
getPlayerState: () => {
|
|
throw new ApiError(500, "internal-error", "Boom");
|
|
},
|
|
});
|
|
await expect(fetchPlayerState(failing)).rejects.toThrow("Boom");
|
|
});
|
|
|
|
it("forgets the state when signed out, and ignores a saved state of another shape", async () => {
|
|
saveLastState(samplePlayerState(), 1);
|
|
saveLastState(null, 2);
|
|
expect(loadLastState()).toBeNull();
|
|
localStorage.setItem("deadhead:last-state", JSON.stringify({ state: { old: 1 }, savedAt: 3 }));
|
|
expect(loadLastState()).toBeNull();
|
|
});
|
|
});
|
|
|
|
describe("server actions offline", () => {
|
|
it("disables a needsServer button only while offline", () => {
|
|
render(
|
|
<>
|
|
<Button needsServer>Buy</Button>
|
|
<Button>Close</Button>
|
|
</>,
|
|
);
|
|
expect(screen.getByRole("button", { name: "Buy" })).toBeEnabled();
|
|
act(() => useConnection.setState({ online: false }));
|
|
expect(screen.getByRole("button", { name: "Buy" })).toBeDisabled();
|
|
expect(screen.getByRole("button", { name: "Buy" })).toHaveAttribute(
|
|
"title",
|
|
"Unavailable offline",
|
|
);
|
|
expect(screen.getByRole("button", { name: "Close" })).toBeEnabled();
|
|
});
|
|
});
|