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 { listEnvs, putEnv, deleteEnv } from "./env";
5
6vi.mock("../lib/sdk", () => ({ configureSdk: vi.fn() }));
7vi.mock("dayjs", () => {
8 const mockDayjs: any = vi.fn(() => ({
9 fromNow: vi.fn().mockReturnValue("2 days ago"),
10 }));
11 mockDayjs.extend = vi.fn();
12 return { default: mockDayjs };
13});
14vi.mock("../lib/getAccessToken", () => ({
15 default: vi.fn().mockResolvedValue("test-access-token"),
16}));
17vi.mock("../lib/env", () => ({
18 env: { POCKETENV_TOKEN: "", POCKETENV_API_URL: "https://api.pocketenv.io" },
19}));
20vi.mock("../theme", () => ({
21 c: {
22 primary: (s: string | number) => String(s),
23 secondary: (s: string | number) => String(s),
24 highlight: (s: string | number) => String(s),
25 },
26}));
27vi.mock("../client", () => ({
28 client: { post: vi.fn().mockResolvedValue({ data: {} }) },
29}));
30vi.mock("consola", () => ({
31 default: { log: vi.fn(), success: vi.fn(), error: vi.fn() },
32}));
33vi.mock("@pocketenv/sdk", () => ({
34 Sandbox: { get: vi.fn(), configure: vi.fn() },
35}));
36
37import { client } from "../client";
38
39describe("env commands", () => {
40 beforeEach(() => {
41 vi.clearAllMocks();
42 });
43
44 describe("listEnvs", () => {
45 it("lists env variables and logs a table", async () => {
46 const mockSandbox = {
47 env: {
48 list: vi.fn().mockResolvedValue({
49 variables: [
50 {
51 id: "var-1",
52 name: "MY_VAR",
53 value: "hello",
54 createdAt: new Date().toISOString(),
55 },
56 ],
57 }),
58 },
59 };
60 vi.mocked(Sandbox.get).mockResolvedValue(mockSandbox as any);
61
62 await listEnvs("my-sandbox");
63
64 expect(mockSandbox.env.list).toHaveBeenCalledWith({ limit: 100, offset: 0 });
65 expect(consola.log).toHaveBeenCalledOnce();
66 });
67
68 it("logs an empty table when no variables exist", async () => {
69 const mockSandbox = {
70 env: { list: vi.fn().mockResolvedValue({ variables: [] }) },
71 };
72 vi.mocked(Sandbox.get).mockResolvedValue(mockSandbox as any);
73
74 await listEnvs("my-sandbox");
75
76 expect(consola.log).toHaveBeenCalledOnce();
77 });
78 });
79
80 describe("putEnv", () => {
81 it("updates a variable and logs success", async () => {
82 const mockSandbox = {
83 env: { put: vi.fn().mockResolvedValue(undefined) },
84 };
85 vi.mocked(Sandbox.get).mockResolvedValue(mockSandbox as any);
86
87 await putEnv("my-sandbox", "MY_VAR", "my-value");
88
89 expect(mockSandbox.env.put).toHaveBeenCalledWith("MY_VAR", "my-value");
90 expect(consola.success).toHaveBeenCalledWith("Variable updated successfully");
91 });
92 });
93
94 describe("deleteEnv", () => {
95 it("deletes a variable and logs success", async () => {
96 await deleteEnv("var-1");
97
98 expect(client.post).toHaveBeenCalledWith(
99 "/xrpc/io.pocketenv.variable.deleteVariable",
100 undefined,
101 expect.objectContaining({ params: { id: "var-1" } }),
102 );
103 expect(consola.success).toHaveBeenCalledWith("Variable deleted successfully");
104 });
105
106 it("logs an error when deletion fails", async () => {
107 vi.mocked(client.post).mockRejectedValue(new Error("API error"));
108
109 await deleteEnv("var-1");
110
111 expect(consola.error).toHaveBeenCalledWith("Failed to delete variable");
112 });
113 });
114});