Comparisons / Test harnesses
Jest tests against supabase-js versus continuous posture checks
The short version
- Hand-rolled tests drive supabase-js as anon/authenticated users against a real project, asserting what each identity may read or write. RowShield evaluates the whole catalog continuously and probes the deployed bundle — coverage without authorship.
- Choose Jest/Vitest + supabase-js test patterns when — your team already writes client-level tests and keeps them current through refactors.
- Choose RowShield when — coverage gaps scare you more than failing asserts: every table nobody wrote a test for is currently unverified.
RowShield rules relevant here
Head to head: Jest/Vitest + supabase-js test patterns vs RowShield
| Capability | Jest/Vitest + supabase-js test patterns | RowShield | Edge |
|---|---|---|---|
| Coverage model | Per-path: only the flows someone encoded get checked, and any table without a spec sits outside the model. | Whole-catalog: every public table on every scan, whether or not a spec file ever mentioned it. | RowShield |
| Authoring cost | Each table-times-role-times-operation combination is code to write, review and maintain; combinations multiply fast. | Connect once; shipped rules apply universally across every table the catalog holds today or gains tomorrow. | RowShield |
| Write-path safety | Requires deliberate destructive-case tests against shared data — writes teams reasonably hesitate to run. | Catalog analysis catches missing WITH CHECK clauses by reading definitions alone, never inserting anything anywhere. | RowShield |
| Client-behaviour fidelity | Real SDK semantics: auth headers, retries, error shapes — faithful to what production clients actually do. | HTTP-level probing: faithful to wire behaviour rather than SDK quirks, which suits posture questions better than UX ones. | Jest/Vitest + supabase-js test patterns |
| Runtime feedback | At test-run time inside repositories — immediate when run, absent entirely in the weeks between runs. | Scheduled against the deployed project, with transition alerts firing after deploys and between them alike. | RowShield |
| Tooling familiarity | Lives in the JavaScript test stack developers already use daily — no new surface for engineers at all. | A new surface — dashboard, CLI, alerts — typically adopted by whoever owns posture rather than by every developer. | Jest/Vitest + supabase-js test patterns |
| Bundle leak detection | Out of scope unless someone engineers bundle scanning separately; most suites never consider it at all. | SERVICE_ROLE_KEY_EXPOSED scans deployed scripts automatically each cycle, catching keys that agents leave in client bundles. | RowShield |
Column claims about Jest/Vitest + supabase-js test patterns are sourced below. Where the edge is theirs, the page says so — and the sections that follow explain why Supabase teams still pick RowShield.
What the pattern does
Teams instantiate the Supabase client twice — once with the anon key, once with a test user's token — then assert expectations: anon cannot read invoices, the user can read their own rows. Against a staging project this catches gross policy mistakes early.
The usual shape is a small matrix harness: seed a couple of tenants, exercise reads and writes through both clients, and assert what each identity may see. Done consistently it documents intended access paths in executable form, which has real value during reviews and onboarding.
The pattern's honesty ends at its own coverage list. Tables added by agents, policies rewritten in dashboards, buckets flipped public — none appear until someone extends the suite.
Where the scopes differ
Client tests sample; catalog rules census. The census matters because attackers need exactly one forgotten table, not the failure of a tested flow.
There is also the fabrication risk: tests asserting forged JWTs against staging verify staging, while the probe exercises the deployed origin with the very key view-source exposes.
Failure modes divide cleanly along the same line. A tested signup flow keeps working while a sibling table ships with RLS disabled; the suite stays green because nothing it encodes changed, while the census notices a new public table immediately — coverage breadth is not a tuning knob but the difference between these instruments.
Why Supabase teams choose RowShield over hand-rolled tests
Completeness without authorship, findings with fixes, and history: resolved findings stay resolved visibly, regressions announce themselves. The nine shipped rules encode institutional knowledge — tautology normalisation, service-role suppression, empty-response nuance — that each team otherwise relearns.
Teams migrating describe a familiar arc: their policy-assertion specs were the least-maintained part of the suite, updated only after incidents, precisely when it was too late. Handing that slice to scheduled scans removed both the guilt and the gap; flow-level specs stayed, now backed by a monitor watching everything the specs never covered.
Where the test pattern is the right choice
App-level regression safety — signup flows, tenant switches, optimistic updates — genuinely benefits from supabase-js tests. They validate experience, not just policy; keep them for that, since no catalog rule can tell you whether the product feels broken to a signed-in user.
They also encode intent in reviewable form, which matters when access rules are contractual rather than incidental. The pivot is scope, not merit: once the question becomes "what can the anon key reach right now", authoring more specs stops scaling, because every answer expires the moment the next dashboard edit lands — which is scheduled verification's entire reason to exist.
Using both
Keep the suite for flows; add RowShield for totality. Many teams delete their policy-assertion specs after the first month of scans — the monitor covers them with better memory and zero maintenance. The remaining division of labour is clean: specs guard what users experience scan over scan, scans guard what attackers enumerate, and neither pretends to do the other's job.
Frequently asked
- Is RowShield affiliated with Jest, Vitest or Supabase?
- No. Veristria builds RowShield independently. Jest, Vitest and supabase-js are referenced descriptively because they define the testing patterns many Supabase teams use first, and they remain properties of their respective projects and communities. Nothing here implies endorsement, partnership or shared development, and all descriptions rely on publicly available documentation. All three remain excellent tools for their intended jobs.
- Is RowShield a good alternative to these tests?
- For verifying authorization posture comprehensively, yes — coverage comes from the catalog rather than from specs anyone wrote. For asserting application workflows end-to-end, client tests still earn their place alongside: they catch broken experiences and regressions in product behaviour that posture monitoring deliberately ignores, and the two together cover disjoint halves of the risk.
- Does RowShield execute writes like my tests do?
- Never. Catalog rules read metadata only; the probe issues GET, HEAD and OPTIONS requests exclusively, and write-refusal is enforced in code rather than convention. That design means scans are safe against production databases holding real customers, which is precisely the environment hand-written destructive tests tend to avoid and therefore never verify.
Check your project in about ten seconds
Paste a URL. No signup, no writes, nothing stored.
Run the free audit