/ sdks / sandbox / javascript / tests / sandbox.connect.resume.test.mjs
sandbox.connect.resume.test.mjs
  1  import assert from "node:assert/strict";
  2  import test from "node:test";
  3  
  4  import {
  5    ConnectionConfig,
  6    DEFAULT_EGRESS_PORT,
  7    DEFAULT_EXECD_PORT,
  8    Sandbox,
  9  } from "../dist/index.js";
 10  
 11  function createAdapterFactory() {
 12    const calls = [];
 13    const sandboxes = {
 14      async getSandboxEndpoint(sandboxId, port, useServerProxy) {
 15        calls.push({ method: "getSandboxEndpoint", args: [sandboxId, port, useServerProxy] });
 16        return {
 17          endpoint: `sandbox.internal:${port}`,
 18          headers: { "x-port": String(port) },
 19        };
 20      },
 21      async resumeSandbox(sandboxId) {
 22        calls.push({ method: "resumeSandbox", args: [sandboxId] });
 23      },
 24      async getSandbox() {
 25        throw new Error("not implemented");
 26      },
 27      async listSandboxes() {
 28        throw new Error("not implemented");
 29      },
 30      async createSandbox() {
 31        throw new Error("not implemented");
 32      },
 33      async deleteSandbox() {},
 34      async pauseSandbox() {},
 35      async renewSandboxExpiration() {
 36        throw new Error("not implemented");
 37      },
 38    };
 39  
 40    const adapterFactory = {
 41      createLifecycleStack() {
 42        return { sandboxes };
 43      },
 44      createExecdStack(opts) {
 45        calls.push({ method: "createExecdStack", args: [opts] });
 46        return {
 47          commands: { kind: "commands" },
 48          files: { kind: "files" },
 49          health: { async ping() { return true; } },
 50          metrics: { kind: "metrics" },
 51        };
 52      },
 53      createEgressStack(opts) {
 54        calls.push({ method: "createEgressStack", args: [opts] });
 55        return {
 56          egress: {
 57            async getPolicy() {
 58              return { defaultAction: "deny", egress: [] };
 59            },
 60            async patchRules() {},
 61          },
 62        };
 63      },
 64    };
 65  
 66    return { adapterFactory, calls };
 67  }
 68  
 69  test("Sandbox.connect wires execd and egress stacks and getEndpointUrl uses protocol", async () => {
 70    const { adapterFactory, calls } = createAdapterFactory();
 71    const connectionConfig = new ConnectionConfig({ domain: "https://api.opensandbox.test" });
 72    connectionConfig.withTransportIfMissing = () => connectionConfig;
 73  
 74    const sandbox = await Sandbox.connect({
 75      sandboxId: "sbx-1",
 76      connectionConfig,
 77      adapterFactory,
 78      skipHealthCheck: true,
 79    });
 80  
 81    assert.equal(sandbox.id, "sbx-1");
 82    assert.equal(await sandbox.getEndpointUrl(8080), "https://sandbox.internal:8080");
 83    assert.deepEqual(
 84      calls
 85        .filter((entry) => entry.method === "getSandboxEndpoint")
 86        .map((entry) => entry.args.slice(0, 2)),
 87      [
 88        ["sbx-1", DEFAULT_EXECD_PORT],
 89        ["sbx-1", DEFAULT_EGRESS_PORT],
 90        ["sbx-1", 8080],
 91      ],
 92    );
 93    assert.equal(calls[2].method, "createExecdStack");
 94    assert.equal(calls[2].args[0].execdBaseUrl, `https://sandbox.internal:${DEFAULT_EXECD_PORT}`);
 95    assert.deepEqual(calls[2].args[0].endpointHeaders, { "x-port": String(DEFAULT_EXECD_PORT) });
 96  });
 97  
 98  test("Sandbox.resume refreshes endpoints through connect after resuming lifecycle", async () => {
 99    const { adapterFactory, calls } = createAdapterFactory();
100    const connectionConfig = new ConnectionConfig({ domain: "http://127.0.0.1:8080" });
101    connectionConfig.withTransportIfMissing = () => connectionConfig;
102  
103    const sandbox = await Sandbox.connect({
104      sandboxId: "sbx-2",
105      connectionConfig,
106      adapterFactory,
107      skipHealthCheck: true,
108    });
109  
110    calls.length = 0;
111    const resumed = await sandbox.resume({ skipHealthCheck: true });
112  
113    assert.equal(resumed.id, "sbx-2");
114    assert.equal(calls[0].method, "resumeSandbox");
115    assert.deepEqual(calls[0].args, ["sbx-2"]);
116    assert.deepEqual(
117      calls
118        .filter((entry) => entry.method === "getSandboxEndpoint")
119        .map((entry) => entry.args.slice(0, 2)),
120      [
121        ["sbx-2", DEFAULT_EXECD_PORT],
122        ["sbx-2", DEFAULT_EGRESS_PORT],
123      ],
124    );
125  });