Files
puter/src/puter-js/tests/api
spacedandDevin AI 7ac2f2e247 feat(ai-chat): let requests opt out of provider fallback (#4343)
* ai-chat: fallback: false fails on the first route instead of rerouting

A chat request whose first provider fails is retried on up to two other
providers that serve the same model, and the caller pays for whichever
one answers. Callers who want one specific route, or who want to handle
a vendor failure themselves, had no way to turn that off.

Passing fallback: false (puter.js option, /drivers/call arg, and the
OpenAI-compat and Anthropic-compat request bodies) makes the first
attempt's failure final: the route is still marked unhealthy, and the
error is classified the same way an exhausted chain would be.

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* ai-chat: cover fallback: false in the SDK suite

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* ai-chat: fallback: false rejects a pinned provider with no route for the model

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* docs: plainer wording for the fallback option

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-10-30 19:35:45 -07:00
..
…

puter.js API test environment

Client-agnostic test suites for puter.js, run against a self-contained in-memory Puter server — no external server, no stdout password scraping, no .env. The same suite files execute on three platforms through thin adapters:

Runner Platform How the SDK runs
runners/node.test.ts node.js Built SDK bundle loaded into a fresh vm context per test (like src/init.cjs)
runners/browser.test.ts headless Chromium (playwright) Fixture page served same-origin on the API host loads /puter.js/v2 from the server itself
runners/workerd.test.ts local workerd (Miniflare) Suite bundle deployed as a real Puter worker via puter.workers.create, dispatched through the local worker proxy

Running

Build the SDK bundle and worker preamble once (repeat after SDK changes):

npm run build:workerLib

Then, from the package root:

npm run test:puterjs            # all three platforms
npm run test:puterjs:node
npm run test:puterjs:browser    # needs `npx playwright install chromium` once
npm run test:puterjs:workerd

How it works

Each runner boots setupPuterTestEnv() (from src/backend/testUtil.ts) in beforeAll: a fully in-memory backend (sqlite / dynalite / redis-mock / fauxqs S3) listening on a real ephemeral port, with the production extensions loaded and two deterministic users seeded:

  • admin — member of the admin group,
  • testuser — a regular, non-privileged user (what suites run as).

The env manifest ({ origin, apiOrigin, users } with fixed passwords and pre-minted session tokens) is JSON-serializable and crosses into whatever runtime executes the tests. Root-only routes (e.g. POST /login) live on origin; the SDK talks to apiOrigin (the api. subdomain host).

Adding tests

Tests are added once and run on all three platforms — never write a per-platform test here.

  1. Existing area (apps, auth, fs, kv): add a test to the matching suites/<name>.suite.ts — one entry in the object, key is the test name, value gets the context t.
  2. New area (e.g. hosting): create suites/hosting.suite.ts and register it in suites/index.ts (explicit list, no globbing — esbuild bundles exactly this list for the browser/workerd runners).
import { suite } from '../harness/types.ts';

export default suite('example', {
    'does the thing': async (t) => {
        await t.puter.fs.write(`/${t.env.users.user.username}/x.txt`, 'hi');
        t.assert.ok(await t.puter.fs.stat(/* … */));
    },
});

Rules that keep a suite runnable everywhere:

  • Platform-agnostic only. No node/browser/workerd-specific imports — a suite may use the SDK instance (t.puter, authed as the regular user), global fetch, and t.assert (ok/equal/deepEqual/rejects).
  • Admin or cross-user assertions go through plain fetch with t.env.users.admin.token (see auth.suite.ts) — that works identically on every platform.
  • Unique resource names per test (file paths, kv keys): tests in a suite share one server and one user, so don't reuse names across tests.
  • The runners in runners/ enumerate suites automatically — adding a suite requires no runner changes.

Iterate fast with npm run test:puterjs:node (boots in ~3s); run npm run test:puterjs before pushing to cover browser and workerd too.