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 main 151 lines 4.5 kB view raw
1import { vi, describe, it, expect, beforeEach } from "vitest"; 2import consola from "consola"; 3import { Sandbox } from "@pocketenv/sdk"; 4import { putFile, listFiles, deleteFile } from "./file"; 5 6vi.mock("../lib/sdk", () => ({ configureSdk: vi.fn() })); 7vi.mock("../lib/getAccessToken", () => ({ 8 default: vi.fn().mockResolvedValue("test-access-token"), 9})); 10vi.mock("../lib/env", () => ({ 11 env: { POCKETENV_TOKEN: "", POCKETENV_API_URL: "https://api.pocketenv.io" }, 12})); 13vi.mock("../theme", () => ({ 14 c: { 15 primary: (s: string | number) => String(s), 16 secondary: (s: string | number) => String(s), 17 error: (s: string | number) => String(s), 18 }, 19})); 20vi.mock("../client", () => ({ 21 client: { post: vi.fn().mockResolvedValue({ data: {} }) }, 22})); 23vi.mock("consola", () => ({ 24 default: { log: vi.fn(), success: vi.fn(), error: vi.fn() }, 25})); 26vi.mock("@pocketenv/sdk", () => ({ 27 Sandbox: { get: vi.fn(), configure: vi.fn() }, 28})); 29vi.mock("fs/promises", () => ({ 30 default: { 31 access: vi.fn().mockResolvedValue(undefined), 32 readFile: vi.fn().mockResolvedValue("file content"), 33 }, 34})); 35vi.mock("@inquirer/prompts", () => ({ 36 editor: vi.fn().mockResolvedValue("editor content"), 37})); 38 39import { client } from "../client"; 40import fs from "fs/promises"; 41 42describe("file commands", () => { 43 beforeEach(() => { 44 vi.clearAllMocks(); 45 Object.defineProperty(process.stdin, "isTTY", { 46 value: true, 47 configurable: true, 48 }); 49 }); 50 51 describe("putFile", () => { 52 it("writes file content from local path", async () => { 53 const mockSandbox = { 54 file: { write: vi.fn().mockResolvedValue(undefined) }, 55 }; 56 vi.mocked(Sandbox.get).mockResolvedValue(mockSandbox as any); 57 58 await putFile("my-sandbox", "/remote/path.txt", "./local/file.txt"); 59 60 expect(fs.readFile).toHaveBeenCalledWith( 61 expect.stringContaining("local/file.txt"), 62 "utf-8", 63 ); 64 expect(mockSandbox.file.write).toHaveBeenCalledWith( 65 "/remote/path.txt", 66 "file content", 67 ); 68 expect(consola.success).toHaveBeenCalledWith( 69 expect.stringContaining("/remote/path.txt"), 70 ); 71 }); 72 73 it("logs error when local file does not exist", async () => { 74 const mockExit = vi 75 .spyOn(process, "exit") 76 .mockImplementation(() => undefined as never); 77 vi.mocked(fs.access).mockRejectedValue( 78 Object.assign(new Error("ENOENT"), { code: "ENOENT" }), 79 ); 80 81 await putFile("my-sandbox", "/remote/path.txt", "./missing.txt"); 82 83 expect(consola.error).toHaveBeenCalledWith( 84 expect.stringContaining("No such file"), 85 ); 86 expect(mockExit).toHaveBeenCalledWith(1); 87 }); 88 89 it("logs error when sandbox write fails", async () => { 90 const mockSandbox = { 91 file: { write: vi.fn().mockRejectedValue(new Error("Write failed")) }, 92 }; 93 vi.mocked(Sandbox.get).mockResolvedValue(mockSandbox as any); 94 95 await putFile("my-sandbox", "/remote/path.txt", "./local/file.txt"); 96 97 expect(consola.error).toHaveBeenCalledWith( 98 expect.stringContaining("Failed to create file"), 99 ); 100 }); 101 }); 102 103 describe("listFiles", () => { 104 it("lists files and logs a table", async () => { 105 const mockSandbox = { 106 file: { 107 list: vi.fn().mockResolvedValue({ 108 files: [ 109 { 110 id: "file-1", 111 path: "/etc/config.json", 112 createdAt: new Date().toISOString(), 113 }, 114 ], 115 }), 116 }, 117 }; 118 vi.mocked(Sandbox.get).mockResolvedValue(mockSandbox as any); 119 120 await listFiles("my-sandbox"); 121 122 expect(mockSandbox.file.list).toHaveBeenCalledOnce(); 123 expect(consola.log).toHaveBeenCalledOnce(); 124 }); 125 }); 126 127 describe("deleteFile", () => { 128 it("deletes a file via API", async () => { 129 await deleteFile("file-1"); 130 131 expect(client.post).toHaveBeenCalledWith( 132 "/xrpc/io.pocketenv.file.deleteFile", 133 undefined, 134 expect.objectContaining({ params: { id: "file-1" } }), 135 ); 136 expect(consola.success).toHaveBeenCalledWith( 137 expect.stringContaining("file-1"), 138 ); 139 }); 140 141 it("logs error when deletion fails", async () => { 142 vi.mocked(client.post).mockRejectedValue(new Error("API error")); 143 144 await deleteFile("file-1"); 145 146 expect(consola.error).toHaveBeenCalledWith( 147 expect.stringContaining("Failed to delete file"), 148 ); 149 }); 150 }); 151});