Skip to content

Commit e0a264a

Browse files
committed
test(web): reuse scheduled task coverage for creation permissions
1 parent 89f8f39 commit e0a264a

2 files changed

Lines changed: 68 additions & 179 deletions

File tree

‎apps/web/src/components/settings/ScheduledTasksSettings.browser.test.tsx‎

Lines changed: 68 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { RegistryContext } from "@effect/atom-react";
2+
import { Atom, AtomRegistry } from "effect/reactivity";
13
import {
24
DEFAULT_UNIFIED_SETTINGS,
35
EnvironmentId,
@@ -10,7 +12,7 @@ import { describe, expect, it, vi } from "vite-plus/test";
1012
import { page, userEvent } from "vite-plus/test/browser";
1113

1214
import "~/index.css";
13-
import { render } from "../../../test/render";
15+
import { act, render } from "../../../test/render";
1416
import { ScheduledTasksSettings } from "./ScheduledTasksSettings";
1517

1618
const environmentId = EnvironmentId.make("laptop");
@@ -38,7 +40,23 @@ const task: ScheduledTask = {
3840
runCount: 0,
3941
};
4042

41-
const state = vi.hoisted(() => ({ connected: true, tasksLoaded: true }));
43+
const state = vi.hoisted(() => ({ connected: true, tasksLoaded: true, secondary: false }));
44+
const secondaryId = EnvironmentId.make("secondary");
45+
const permissions = new Map<string, Atom.Writable<boolean>>();
46+
47+
function setup() {
48+
state.connected = true;
49+
state.tasksLoaded = true;
50+
state.secondary = false;
51+
permissions.clear();
52+
permissions.set(environmentId, Atom.make(true));
53+
permissions.set(secondaryId, Atom.make(true));
54+
permissions.set("", Atom.make(false));
55+
}
56+
57+
function secondaryEnvironment() {
58+
return { ...environment(), environmentId: secondaryId, label: "Secondary" };
59+
}
4260

4361
function environment() {
4462
return {
@@ -54,8 +72,12 @@ vi.mock(import("./SettingsScopeContext"), async (original) => {
5472
const entry = environment();
5573
return {
5674
scope: { kind: "all", label: "All", members: [], environmentIds: [environmentId] },
57-
environments: [entry],
58-
connectedEnvironments: state.connected ? [entry] : [],
75+
environments: state.secondary ? [entry, secondaryEnvironment()] : [entry],
76+
connectedEnvironments: state.connected
77+
? state.secondary
78+
? [entry, secondaryEnvironment()]
79+
: [entry]
80+
: [],
5981
environment: entry,
6082
target: null,
6183
targets: [],
@@ -68,15 +90,14 @@ vi.mock(import("./SettingsScopeContext"), async (original) => {
6890
});
6991
vi.mock(import("../../state/server"), async (original) => {
7092
const actual = await original();
71-
const { Atom } = await import("effect/reactivity");
72-
const allowed = Atom.make(true);
93+
7394
return {
7495
...actual,
7596
serverEnvironment: {
7697
...actual.serverEnvironment,
7798
upsertScheduledTask: {
7899
...actual.serverEnvironment.upsertScheduledTask,
79-
permissionAtom: () => allowed,
100+
permissionAtom: (id: string | null) => permissions.get(id ?? "")!,
80101
},
81102
},
82103
};
@@ -93,7 +114,8 @@ vi.mock(import("../../state/query"), async (original) => ({
93114
}));
94115
vi.mock(import("../../state/environments"), async (original) => ({
95116
...(await original()),
96-
useEnvironment: (() => environment()) as never,
117+
useEnvironment: ((id: EnvironmentId) =>
118+
id === secondaryId ? secondaryEnvironment() : environment()) as never,
97119
}));
98120
vi.mock(import("../../state/entities"), async (original) => ({
99121
...(await original()),
@@ -105,9 +127,44 @@ vi.mock(import("../../hooks/useSettings"), async (original) => ({
105127
}));
106128

107129
describe("ScheduledTasksSettings", () => {
130+
it("creates on a permitted secondary and reacts to permission changes", async () => {
131+
setup();
132+
state.secondary = true;
133+
const registry = AtomRegistry.make();
134+
using _registry = { [Symbol.dispose]: () => registry.dispose() };
135+
registry.set(permissions.get(environmentId)!, false);
136+
await using screen = await render(
137+
<RegistryContext.Provider value={registry}>
138+
<ScheduledTasksSettings />
139+
</RegistryContext.Provider>,
140+
);
141+
const create = screen.getByRole("button", { name: "New task" });
142+
await expect.element(create).toBeEnabled();
143+
await act(() => registry.set(permissions.get(secondaryId)!, false));
144+
await expect.element(create).toBeDisabled();
145+
await act(() => registry.set(permissions.get(secondaryId)!, true));
146+
await expect.element(create).toBeEnabled();
147+
await create.click();
148+
await expect.element(page.getByLabelText("Runs on")).toHaveTextContent("Secondary");
149+
});
150+
151+
it("keeps the permitted representative as the creation target", async () => {
152+
setup();
153+
state.secondary = true;
154+
await using screen = await render(<ScheduledTasksSettings />);
155+
await screen.getByRole("button", { name: "New task" }).click();
156+
await expect.element(page.getByLabelText("Runs on")).toHaveTextContent("Laptop");
157+
});
158+
159+
it("disables creation without a connected target", async () => {
160+
setup();
161+
state.connected = false;
162+
await using screen = await render(<ScheduledTasksSettings />);
163+
await expect.element(screen.getByRole("button", { name: "New task" })).toBeDisabled();
164+
});
165+
108166
it("keeps a linked task's unsaved edits across a disconnect and reconnect", async () => {
109-
state.connected = true;
110-
state.tasksLoaded = true;
167+
setup();
111168
await using screen = await render(<ScheduledTasksSettings taskId={task.id} />);
112169
const name = page.getByRole("dialog").getByRole("textbox", { name: "Name" });
113170
await expect.element(name).toHaveValue("Review issues");
@@ -124,7 +181,7 @@ describe("ScheduledTasksSettings", () => {
124181
});
125182

126183
it("keeps an editor the user opened when the linked task loads later", async () => {
127-
state.connected = true;
184+
setup();
128185
state.tasksLoaded = false;
129186
await using screen = await render(<ScheduledTasksSettings taskId={task.id} />);
130187
await userEvent.click(page.getByRole("button", { name: "New task" }));

‎apps/web/src/components/settings/ScheduledTasksSettings.permissions.browser.test.tsx‎

Lines changed: 0 additions & 168 deletions
This file was deleted.

0 commit comments

Comments
 (0)