> ## Documentation Index
> Fetch the complete documentation index at: https://docs.encoreos.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Edge and API Testing Guide

> This document is the single reference for testing Supabase Edge Functions and the Functions API from your IDE and local environment. It covers local stack work…

This document is the single reference for testing Supabase Edge Functions and the Functions API from your IDE and local environment. It covers local stack workflow, debugging with breakpoints, Deno unit tests, integration tests against local functions, and troubleshooting.

**See also:** [TESTING\_SETUP\_AND\_RUN.md](TESTING_SETUP_AND_RUN.md) (all test types), [EDGE\_FUNCTIONS.md](../integrations/EDGE_FUNCTIONS.md) (function reference and deployment). Verification results: EDGE\_AND\_API\_VERIFICATION\_RESULTS.md.

***

## Prerequisites

* **Supabase CLI** — Install globally or use `npx supabase` from the project root. See [Install the Supabase CLI](https://supabase.com/docs/guides/cli/getting-started#install-the-supabase-cli).
* **Docker** — Required for `supabase start` (local Postgres, Auth, etc.).
* **Deno** (optional) — For running Edge Function unit tests (`deno test`). Install from [deno.land](https://deno.land/) if you want to run `npm run test:functions` locally.

***

## Full local stack

1. **Start the local Supabase stack** (Postgres, Auth, Realtime, Storage, etc.):
   ```bash theme={null}
   npx supabase start
   ```
   Or: `npm run supabase:start` (if you use the npm script). Get the API URL and anon key with:
   ```bash theme={null}
   npx supabase status
   ```

2. **Serve Edge Functions with hot-reload:**
   ```bash theme={null}
   npm run supabase:functions:serve
   ```
   Or: `supabase functions serve`. Omitting a function name serves **all** functions. Hot-reload is on by default.

3. **Invoke locally:**
   * **From the app:** Point `VITE_SUPABASE_URL` at `http://localhost:54321` and use `supabase.functions.invoke('my-func', { body })`.
   * **From terminal (cURL):**
     ```bash theme={null}
     curl -i -X POST 'http://localhost:54321/functions/v1/my-func' \
       -H 'Authorization: Bearer <anon_key>' \
       -H 'Content-Type: application/json' \
       -d '{"key": "value"}'
     ```
     Use the anon key from `npx supabase status`.

***

## Local env for Edge/API

For local function and API testing, use a `.env.local` (or shell export) with:

* `VITE_SUPABASE_URL=http://localhost:54321`
* `VITE_SUPABASE_PUBLISHABLE_KEY=<anon key from npx supabase status>`

Get the anon key after running `supabase start`:

```bash theme={null}
npx supabase status
```

Use the **anon** key for client-style calls; use **service\_role** only for tests that need elevated access (e.g. integration tests using the service role client).

***

## Debugging with breakpoints

1. **Start functions in inspect mode:**
   ```bash theme={null}
   npm run supabase:functions:serve:inspect
   ```
   This runs `supabase functions serve --inspect-mode brk`. Execution pauses on the first line when a request hits a function.

2. **Attach Chrome DevTools:**
   * Open Chrome and go to `chrome://inspect`.
   * Click **Configure** and add target `127.0.0.1:8083`.
   * Under "Remote Target", click **Open dedicated DevTools for Node**.

3. **Trigger a function** (e.g. cURL or the app). Execution will pause so you can set breakpoints, step through code, and inspect variables.

***

## Deno unit tests

**Location:** Tests are co-located with functions, e.g.:

* `supabase/functions/<name>/index.test.ts`
* `supabase/functions/<name>/index_test.ts`

Examples: [generate-templated-pdf/index.test.ts](../../supabase/functions/generate-templated-pdf/index.test.ts), [hr-encrypt-bank-account/index\_test.ts](../../supabase/functions/hr-encrypt-bank-account/index_test.ts).

**Environment when testing against local:**

* **generate-templated-pdf** and similar: Set `VITE_SUPABASE_URL=http://localhost:54321` and `VITE_SUPABASE_PUBLISHABLE_KEY=<anon from npx supabase status>`.
* **hr-encrypt-bank-account**: Set `SUPABASE_URL=http://localhost:54321` (and optionally `TEST_AUTH_TOKEN` for authenticated tests).

**Run from repo root:**

```bash theme={null}
npm run test:functions
```

This runs all Deno tests under `supabase/functions`. Ensure the local stack and `supabase functions serve` are running if tests call the HTTP endpoint.

**IDE:** Use the Deno extension in VS Code/Cursor and the task **"Run Edge Function (Deno) tests"** to run the same command from the editor. If your workspace has no `.vscode/tasks.json`, copy or merge from [docs/development/vscode-tasks-edge-functions.json](../development/vscode-tasks-edge-functions.json) into `.vscode/tasks.json`.

***

## API Gateway parity (local vs production)

| Environment    | Base URL                                          |
| -------------- | ------------------------------------------------- |
| **Local**      | `http://localhost:54321/functions/v1/`            |
| **Production** | `https://<project-ref>.supabase.co/functions/v1/` |

For **prod-like local behavior**, run `supabase functions serve` **without** `--no-verify-jwt` and send a valid `Authorization: Bearer <token>` header (anon key or user JWT). The default `npm run supabase:functions:serve` uses `--no-verify-jwt` for easier local iteration; use inspect or a separate serve command when testing JWT verification.

***

## Logs

* **Local:** Function stdout/stderr appear in the terminal where you ran `supabase functions serve`.
* **Production:** Use the Supabase Dashboard (Edge Function logs) or the CLI. Use structured logging in code (e.g. `logger.info` with `correlationId`, no PHI) for easier filtering.

***

## Integration tests against local

To run Vitest integration tests that invoke Edge Functions against your local stack:

1. Set `VITE_SUPABASE_URL=http://localhost:54321` and `SUPABASE_SERVICE_ROLE_KEY` (and `VITE_SUPABASE_PUBLISHABLE_KEY` if tests use anon client). Get keys from `npx supabase status` after `supabase start`.
2. Run `npm run supabase:functions:serve` in a separate terminal.
3. Run integration tests, e.g.:
   ```bash theme={null}
   npm run test:integration
   ```
   Or a subset, e.g.:
   ```bash theme={null}
   npm run test:integration -- tests/integration/fa/fa-handle-bank-balance-updated.test.ts
   ```

The test setup uses [tests/setup.ts](../../tests/setup.ts) and tests such as [tests/integration/fa/plaid-create-link-token.test.ts](../../tests/integration/fa/plaid-create-link-token.test.ts) use `VITE_SUPABASE_URL` and `supabase.functions.invoke`. With the URL pointing at local and functions serve running, those tests hit your local functions.

***

## Fast prod checks

* **Dashboard:** Use the **Test** tab for each function in the Supabase Dashboard to try different headers, payloads, and JWTs.
* **cURL:**
  ```bash theme={null}
  curl -X POST 'https://<project-ref>.supabase.co/functions/v1/<func>' \
    -H 'Authorization: Bearer <ANON_KEY>' \
    -H 'Content-Type: application/json' \
    -d '{"key": "value"}'
  ```

***

## Troubleshooting checklist

| Issue                | What to check                                                                                                                                                                                 |
| -------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **401/403 locally**  | Missing or invalid `Authorization` header. Confirm anon key (or user JWT). If the function has `verify_jwt = true` in production, run serve without `--no-verify-jwt` and send a valid token. |
| **Import errors**    | Use `npm:` or `jsr:` specifiers in Edge Functions and pin versions. Do not use Node-style imports.                                                                                            |
| **File writes**      | Writes are allowed only under `/tmp`.                                                                                                                                                         |
| **Hanging requests** | Look for unawaited Promises. Offload background work with `EdgeRuntime.waitUntil(promise)` so the response is not delayed.                                                                    |

***

## See also

* [TESTING\_SETUP\_AND\_RUN.md](TESTING_SETUP_AND_RUN.md) — All test types and env vars
* [EDGE\_FUNCTIONS.md](../integrations/EDGE_FUNCTIONS.md) — Function reference, deployment, and JWT config
* [SUPABASE\_CLI\_LOCAL\_WORKFLOW.md](../development/supabase/SUPABASE_CLI_LOCAL_WORKFLOW.md) — Migrations and local DB workflow
