|
| 1 | +import { cleanup, fireEvent, screen, waitFor, within } from "@testing-library/react"; |
| 2 | +import { afterEach, describe, expect, test } from "vitest"; |
| 3 | +import { FakeBotloft } from "../../lib/fake"; |
| 4 | +import { RpcError } from "../../lib/rpc"; |
| 5 | +import { crewOpened, renderApp } from "../../test/app"; |
| 6 | + |
| 7 | +afterEach(cleanup); |
| 8 | + |
| 9 | +/** Opens Settings on its "Archived" part. */ |
| 10 | +async function openArchived() { |
| 11 | + fireEvent.click(await screen.findByRole("button", { name: /Ana Lima/ })); |
| 12 | + fireEvent.click(screen.getByRole("menuitem", { name: "Settings" })); |
| 13 | + const dialog = screen.getByRole("dialog", { name: "Settings" }); |
| 14 | + fireEvent.click(within(dialog).getByRole("tab", { name: "Archived" })); |
| 15 | + return dialog; |
| 16 | +} |
| 17 | + |
| 18 | +/** Ops with Writer and an archived Scout, and an archived crew Docs of one bot. */ |
| 19 | +async function someArchived() { |
| 20 | + const fake = new FakeBotloft(); |
| 21 | + const ops = fake.addCrew("Ops"); |
| 22 | + const docs = fake.addCrew("Docs"); |
| 23 | + const scout = fake.addBot(ops.id, "Scout"); |
| 24 | + fake.addBot(ops.id, "Writer"); |
| 25 | + const editor = fake.addBot(docs.id, "Editor"); |
| 26 | + await fake.call("bots.archive", { botId: scout.id }); |
| 27 | + await fake.call("crews.archive", { crewId: docs.id }); |
| 28 | + renderApp(fake); |
| 29 | + await crewOpened("Ops"); |
| 30 | + return { fake, ops, docs, scout, editor }; |
| 31 | +} |
| 32 | + |
| 33 | +describe("settings, archived", () => { |
| 34 | + test("lists what was archived, which the app shows nowhere else", async () => { |
| 35 | + await someArchived(); |
| 36 | + const dialog = await openArchived(); |
| 37 | + const list = await within(dialog).findByRole("list", { name: "Archived" }); |
| 38 | + const rows = within(list).getAllByRole("listitem"); |
| 39 | + expect(rows.map((row) => row.textContent)).toEqual([ |
| 40 | + "DocsCrew · 1 bot · archived nowDelete", |
| 41 | + "ScoutBot in Ops · archived nowDelete", |
| 42 | + ]); |
| 43 | + // A bot of an archived crew goes with its crew, not on its own. |
| 44 | + expect(within(list).queryByText("Editor")).toBeNull(); |
| 45 | + expect(dialog.textContent).toContain("Botloft still keeps their conversations"); |
| 46 | + }); |
| 47 | + |
| 48 | + test("deletes an archived bot, saying it leaves rather than stops", async () => { |
| 49 | + const { fake, scout } = await someArchived(); |
| 50 | + const dialog = await openArchived(); |
| 51 | + fireEvent.click(await within(dialog).findByRole("button", { name: "Delete Scout" })); |
| 52 | + const confirm = screen.getByRole("dialog", { name: "Delete Scout?" }); |
| 53 | + expect(confirm.textContent).toContain("Scout leaves Botloft for good"); |
| 54 | + expect(confirm.textContent).not.toContain("stops now"); |
| 55 | + expect(within(confirm).getByText(scout.workspace)).toBeDefined(); |
| 56 | + fireEvent.click(within(confirm).getByRole("button", { name: "Delete bot" })); |
| 57 | + await waitFor(() => expect(within(dialog).queryByText("Scout")).toBeNull()); |
| 58 | + expect(fake.bots.has(scout.id)).toBe(false); |
| 59 | + expect(within(dialog).getByText("Docs")).toBeDefined(); |
| 60 | + }); |
| 61 | + |
| 62 | + test("deletes an archived crew with its bots, then has nothing left", async () => { |
| 63 | + const { fake, docs, scout, editor } = await someArchived(); |
| 64 | + await fake.call("bots.delete", { botId: scout.id }); |
| 65 | + const dialog = await openArchived(); |
| 66 | + fireEvent.click(await within(dialog).findByRole("button", { name: "Delete Docs" })); |
| 67 | + const confirm = screen.getByRole("dialog", { name: "Delete Docs?" }); |
| 68 | + expect(confirm.textContent).toContain("Docs and its bot leave Botloft for good"); |
| 69 | + expect(within(confirm).getByText(docs.workFolder)).toBeDefined(); |
| 70 | + fireEvent.click(within(confirm).getByRole("button", { name: "Delete crew" })); |
| 71 | + expect(await within(dialog).findByText("Nothing is archived.")).toBeDefined(); |
| 72 | + expect(fake.crews.has(docs.id)).toBe(false); |
| 73 | + expect(fake.bots.has(editor.id)).toBe(false); |
| 74 | + }); |
| 75 | + |
| 76 | + test("says so when nothing is archived, or when the list cannot be read", async () => { |
| 77 | + const fake = new FakeBotloft(); |
| 78 | + fake.addCrew("Ops"); |
| 79 | + renderApp(fake); |
| 80 | + await crewOpened("Ops"); |
| 81 | + const dialog = await openArchived(); |
| 82 | + expect(await within(dialog).findByText("Nothing is archived.")).toBeDefined(); |
| 83 | + |
| 84 | + fake.failNext("archive.list", new RpcError(-32603, "internal error")); |
| 85 | + fireEvent.click(within(dialog).getByRole("tab", { name: "About" })); |
| 86 | + fireEvent.click(within(dialog).getByRole("tab", { name: "Archived" })); |
| 87 | + const alert = await within(dialog).findByRole("alert"); |
| 88 | + expect(alert.textContent).toContain("Could not load what is archived"); |
| 89 | + }); |
| 90 | +}); |
0 commit comments