the universal sandbox runtime for agents and humans.
pocketenv.io
sandbox
openclaw
agent
claude-code
vercel-sandbox
deno-sandbox
cloudflare-sandbox
atproto
sprites
daytona
1import { vi, describe, it, expect, beforeEach } from "vitest";
2import consola from "consola";
3import { Sandbox } from "@pocketenv/sdk";
4import { putAuthKey, getTailscaleAuthKey } from "./tailscale";
5
6vi.mock("../lib/sdk", () => ({ configureSdk: vi.fn() }));
7vi.mock("../theme", () => ({
8 c: {
9 primary: (s: string | number) => String(s),
10 },
11}));
12vi.mock("consola", () => ({
13 default: { log: vi.fn(), success: vi.fn(), error: vi.fn(), info: vi.fn() },
14}));
15vi.mock("@pocketenv/sdk", () => ({
16 Sandbox: { get: vi.fn(), configure: vi.fn() },
17}));
18vi.mock("@inquirer/prompts", () => ({
19 password: vi.fn().mockResolvedValue("tskey-auth-abc123"),
20}));
21
22describe("tailscale commands", () => {
23 const mockExit = vi
24 .spyOn(process, "exit")
25 .mockImplementation(() => undefined as never);
26
27 beforeEach(() => {
28 vi.clearAllMocks();
29 });
30
31 describe("putAuthKey", () => {
32 it("saves Tailscale auth key and logs success", async () => {
33 const mockSandbox = {
34 tailscale: { setAuthKey: vi.fn().mockResolvedValue(undefined) },
35 };
36 vi.mocked(Sandbox.get).mockResolvedValue(mockSandbox as any);
37
38 await putAuthKey("my-sandbox");
39
40 expect(mockSandbox.tailscale.setAuthKey).toHaveBeenCalledWith(
41 "tskey-auth-abc123",
42 );
43 expect(consola.success).toHaveBeenCalledWith(
44 expect.stringContaining("my-sandbox"),
45 );
46 });
47
48 it("logs error and exits when saving fails", async () => {
49 vi.mocked(Sandbox.get).mockRejectedValue(new Error("API error"));
50
51 await putAuthKey("my-sandbox");
52
53 expect(consola.error).toHaveBeenCalledWith(
54 expect.stringContaining("Failed to save Tailscale auth key"),
55 );
56 expect(mockExit).toHaveBeenCalledWith(1);
57 });
58 });
59
60 describe("getTailscaleAuthKey", () => {
61 it("retrieves and logs the Tailscale auth key", async () => {
62 const mockSandbox = {
63 tailscale: {
64 getAuthKey: vi
65 .fn()
66 .mockResolvedValue({ authKey: "tskey-auth-abc123" }),
67 },
68 };
69 vi.mocked(Sandbox.get).mockResolvedValue(mockSandbox as any);
70
71 await getTailscaleAuthKey("my-sandbox");
72
73 expect(consola.info).toHaveBeenCalledWith(
74 expect.stringContaining("tskey-auth-abc123"),
75 );
76 });
77
78 it("logs error and exits when key not found", async () => {
79 const mockSandbox = {
80 tailscale: {
81 getAuthKey: vi.fn().mockRejectedValue(new Error("Not found")),
82 },
83 };
84 vi.mocked(Sandbox.get).mockResolvedValue(mockSandbox as any);
85
86 await getTailscaleAuthKey("my-sandbox");
87
88 expect(consola.error).toHaveBeenCalledWith(
89 expect.stringContaining("No Tailscale Auth Key found"),
90 );
91 expect(mockExit).toHaveBeenCalledWith(1);
92 });
93 });
94});