the universal sandbox runtime for agents and humans. pocketenv.io
sandbox openclaw agent claude-code vercel-sandbox deno-sandbox cloudflare-sandbox atproto sprites daytona
7
fork

Configure Feed

Select the types of activity you want to include in your feed.

at 1241cd4e999bb3f48dca4cab7bcff14fe6f5d6ad 219 lines 6.4 kB view raw
1import { vi, describe, it, expect, beforeEach } from "vitest"; 2import consola from "consola"; 3import { Sandbox } from "@pocketenv/sdk"; 4import { 5 createService, 6 listServices, 7 restartService, 8 startService, 9 stopService, 10 deleteService, 11} from "./service"; 12 13vi.mock("../lib/sdk", () => ({ configureSdk: vi.fn() })); 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("service commands", () => { 40 const mockExit = vi 41 .spyOn(process, "exit") 42 .mockImplementation(() => undefined as never); 43 44 beforeEach(() => { 45 vi.clearAllMocks(); 46 vi.mocked(client.post).mockResolvedValue({ data: {} }); 47 }); 48 49 describe("createService", () => { 50 it("creates a service and logs success", async () => { 51 const mockSandbox = { 52 service: { add: vi.fn().mockResolvedValue(undefined) }, 53 }; 54 vi.mocked(Sandbox.get).mockResolvedValue(mockSandbox as any); 55 56 await createService("my-sandbox", "web", ["npm", "start"], { 57 ports: ["3000"], 58 description: "Web server", 59 }); 60 61 expect(mockSandbox.service.add).toHaveBeenCalledWith("web", "npm start", { 62 description: "Web server", 63 ports: [3000], 64 }); 65 expect(consola.success).toHaveBeenCalledWith( 66 expect.stringContaining("web"), 67 ); 68 }); 69 70 it("logs error and exits when creation fails", async () => { 71 vi.mocked(Sandbox.get).mockRejectedValue(new Error("Not found")); 72 73 await createService("my-sandbox", "web", ["npm", "start"], {}); 74 75 expect(consola.error).toHaveBeenCalledWith( 76 "Failed to create service", 77 expect.any(Error), 78 ); 79 expect(mockExit).toHaveBeenCalledWith(1); 80 }); 81 }); 82 83 describe("listServices", () => { 84 it("lists services and logs a table", async () => { 85 const mockSandbox = { 86 service: { 87 list: vi.fn().mockResolvedValue({ 88 services: [ 89 { 90 id: "svc-1", 91 name: "web", 92 command: "npm start", 93 status: "RUNNING", 94 createdAt: new Date().toISOString(), 95 }, 96 ], 97 }), 98 }, 99 }; 100 vi.mocked(Sandbox.get).mockResolvedValue(mockSandbox as any); 101 102 await listServices("my-sandbox"); 103 104 expect(mockSandbox.service.list).toHaveBeenCalledOnce(); 105 expect(consola.log).toHaveBeenCalledOnce(); 106 }); 107 108 it("logs error and exits when listing fails", async () => { 109 vi.mocked(Sandbox.get).mockRejectedValue(new Error("Not found")); 110 111 await listServices("my-sandbox"); 112 113 expect(consola.error).toHaveBeenCalledWith( 114 "Failed to list services", 115 expect.any(Error), 116 ); 117 expect(mockExit).toHaveBeenCalledWith(1); 118 }); 119 }); 120 121 describe("restartService", () => { 122 it("restarts a service via API", async () => { 123 await restartService("svc-1"); 124 125 expect(client.post).toHaveBeenCalledWith( 126 "/xrpc/io.pocketenv.service.restartService", 127 undefined, 128 expect.objectContaining({ params: { serviceId: "svc-1" } }), 129 ); 130 }); 131 132 it("logs error and exits when restart fails", async () => { 133 vi.mocked(client.post).mockRejectedValue(new Error("API error")); 134 135 await restartService("svc-1"); 136 137 expect(consola.error).toHaveBeenCalledWith( 138 expect.stringContaining("Failed to restart service"), 139 expect.any(Error), 140 ); 141 expect(mockExit).toHaveBeenCalledWith(1); 142 }); 143 }); 144 145 describe("startService", () => { 146 it("starts a service via API", async () => { 147 await startService("svc-1"); 148 149 expect(client.post).toHaveBeenCalledWith( 150 "/xrpc/io.pocketenv.service.startService", 151 undefined, 152 expect.objectContaining({ params: { serviceId: "svc-1" } }), 153 ); 154 }); 155 156 it("logs error and exits when start fails", async () => { 157 vi.mocked(client.post).mockRejectedValue(new Error("API error")); 158 159 await startService("svc-1"); 160 161 expect(consola.error).toHaveBeenCalledWith( 162 expect.stringContaining("Failed to start service"), 163 expect.any(Error), 164 ); 165 expect(mockExit).toHaveBeenCalledWith(1); 166 }); 167 }); 168 169 describe("stopService", () => { 170 it("stops a service via API", async () => { 171 await stopService("svc-1"); 172 173 expect(client.post).toHaveBeenCalledWith( 174 "/xrpc/io.pocketenv.service.stopService", 175 undefined, 176 expect.objectContaining({ params: { serviceId: "svc-1" } }), 177 ); 178 }); 179 180 it("logs error and exits when stop fails", async () => { 181 vi.mocked(client.post).mockRejectedValue(new Error("API error")); 182 183 await stopService("svc-1"); 184 185 expect(consola.error).toHaveBeenCalledWith( 186 expect.stringContaining("Failed to stop service"), 187 expect.any(Error), 188 ); 189 expect(mockExit).toHaveBeenCalledWith(1); 190 }); 191 }); 192 193 describe("deleteService", () => { 194 it("deletes a service via API and logs success", async () => { 195 await deleteService("svc-1"); 196 197 expect(client.post).toHaveBeenCalledWith( 198 "/xrpc/io.pocketenv.service.deleteService", 199 undefined, 200 expect.objectContaining({ params: { serviceId: "svc-1" } }), 201 ); 202 expect(consola.success).toHaveBeenCalledWith( 203 expect.stringContaining("svc-1"), 204 ); 205 }); 206 207 it("logs error and exits when deletion fails", async () => { 208 vi.mocked(client.post).mockRejectedValue(new Error("API error")); 209 210 await deleteService("svc-1"); 211 212 expect(consola.error).toHaveBeenCalledWith( 213 expect.stringContaining("Failed to delete service"), 214 expect.any(Error), 215 ); 216 expect(mockExit).toHaveBeenCalledWith(1); 217 }); 218 }); 219});