summaryrefslogtreecommitdiffhomepage
path: root/src/features/workspaces/ui/WorkspaceDetails.test.ts
blob: 913874243c6fcef27c84d2a0d2639f797341233a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
import type { ComputerEntry, WorkspaceEntry } from "@dispatch/wire";
import { render, screen } from "@testing-library/svelte";
import userEvent from "@testing-library/user-event";
import { describe, expect, it, vi } from "vitest";
import type { WorkspaceResult } from "../adapter/http";
import type { WorkspaceStore } from "../store.svelte";
import WorkspaceDetails from "./WorkspaceDetails.svelte";

function fakeEntry(overrides: Partial<WorkspaceEntry> = {}): WorkspaceEntry {
  return {
    id: "my-ws",
    title: "My Workspace",
    defaultCwd: null,
    defaultComputerId: null,
    starred: false,
    archived: false,
    createdAt: 1,
    lastActivityAt: 2,
    conversationCount: 0,
    ...overrides,
  };
}

function fakeStore(): WorkspaceStore {
  return {
    setDefaultCwd: vi.fn(
      async (id: string, defaultCwd: string | null): Promise<WorkspaceResult<WorkspaceEntry>> => ({
        ok: true,
        value: fakeEntry({ id, defaultCwd }),
      }),
    ),
    setDefaultComputer: vi.fn(
      async (
        id: string,
        defaultComputerId: string | null,
      ): Promise<WorkspaceResult<WorkspaceEntry>> => ({
        ok: true,
        value: fakeEntry({ id, defaultComputerId }),
      }),
    ),
  } as unknown as WorkspaceStore;
}

describe("WorkspaceDetails", () => {
  it("renders the title, slug, cwd input, and computer select", () => {
    render(WorkspaceDetails, {
      props: { ws: fakeEntry(), store: fakeStore(), computers: [], onClose: () => {} },
    });
    expect(screen.getByText("My Workspace")).toBeInTheDocument();
    expect(screen.getByText("/my-ws")).toBeInTheDocument();
    expect(screen.getByLabelText("Default working directory")).toBeInTheDocument();
    expect(screen.getByLabelText("Computer")).toBeInTheDocument();
  });

  it("saves the cwd via the store; an empty value clears to null", async () => {
    const user = userEvent.setup();
    const store = fakeStore();
    const onClose = vi.fn();
    render(WorkspaceDetails, {
      props: { ws: fakeEntry({ defaultCwd: "/old" }), store, computers: [], onClose },
    });

    const input = screen.getByLabelText("Default working directory");
    await user.clear(input);
    await user.click(screen.getByRole("button", { name: "Set" }));
    expect(store.setDefaultCwd).toHaveBeenCalledWith("my-ws", null);
  });

  it("a failed cwd save surfaces the error", async () => {
    const user = userEvent.setup();
    const store = fakeStore();
    store.setDefaultCwd = vi.fn(
      async (): Promise<WorkspaceResult<WorkspaceEntry>> => ({ ok: false, error: "nope" }),
    );
    render(WorkspaceDetails, {
      props: { ws: fakeEntry({ defaultCwd: "/old" }), store, computers: [], onClose: () => {} },
    });

    await user.type(screen.getByLabelText("Default working directory"), "!{Enter}");
    expect(await screen.findByText("nope")).toBeInTheDocument();
  });

  it("picking a computer saves it via the store", async () => {
    const user = userEvent.setup();
    const store = fakeStore();
    const computers: ComputerEntry[] = [
      {
        alias: "lab",
        hostName: "lab.example",
        port: 22,
        user: "me",
        identityFile: null,
        knownHost: true,
        usageCount: 0,
      },
    ];
    render(WorkspaceDetails, {
      props: { ws: fakeEntry(), store, computers, onClose: () => {} },
    });

    await user.selectOptions(screen.getByLabelText("Computer"), "lab");
    expect(store.setDefaultComputer).toHaveBeenCalledWith("my-ws", "lab");
  });

  it("the close button dismisses the dialog", async () => {
    const user = userEvent.setup();
    const onClose = vi.fn();
    render(WorkspaceDetails, {
      props: { ws: fakeEntry(), store: fakeStore(), computers: [], onClose },
    });

    await user.click(screen.getByRole("button", { name: "Close details" }));
    expect(onClose).toHaveBeenCalledTimes(1);
  });
});