Skip to content

Phase 2: Operation Test Suites

Goal

Create three operation-measurement test suites so TendSocial can measure the Prisma database cost and performance impact of each API route, standard user flow, page load, click, and action.

Prisma pricing is based on database operations. Prisma states that it counts Prisma ORM queries, not every SQL statement generated behind the scenes. Source: Prisma pricing.

Metrics to capture

Each measured action should capture:

MetricMeaning
measurementIdUnique UUID for request/action correlation.
labelHuman-readable action label.
apiDurationMsBackend request duration.
browserDurationMsUser-visible browser action duration.
prismaOrmOpsCount of Prisma ORM operations.
sqlStatementsSQL statement count generated by Prisma.
sqlDurationMsTotal SQL duration from Prisma query events.
networkRequestsAPI calls triggered by a browser action.
rowsReadOptional if available.
rowsWrittenOptional if available.
warningsN+1, duplicate fetches, slow query, missing-index suspicion.

Instrumentation foundation

Prisma query logging

Prisma Client supports event-based logging with $on('query'), including query, params, and duration. Source: Prisma Client logging.

Example:

ts
import { PrismaClient } from "@prisma/client";

export const prisma = new PrismaClient({
  log: [
    { emit: "event", level: "query" },
    { emit: "stdout", level: "error" },
    { emit: "stdout", level: "warn" },
  ],
});

prisma.$on("query", (event) => {
  console.log({
    query: event.query,
    params: event.params,
    durationMs: event.duration,
  });
});

Request correlation

Every API request and Playwright action should include:

http
x-tendsocial-measurement-id: <uuid>
x-tendsocial-measurement-label: dashboard.load

Backend responses should include headers where possible:

http
x-db-orm-ops: 8
x-db-sql-statements: 11
x-db-sql-duration-ms: 42
x-api-duration-ms: 123

And optionally a JSON debug payload in benchmark mode:

json
{
  "measurementId": "...",
  "label": "dashboard.load",
  "apiDurationMs": 123,
  "prismaOrmOps": 8,
  "sqlStatements": 11,
  "sqlDurationMs": 42
}

Suite A: Backend API operation tests

Goal

Call each API route directly from the backend test runner and measure the Prisma impact of every route without browser noise.

Command

bash
pnpm test:dbops:api

Coverage checklist

API areaRequired actions
Auth/sessioncurrent user, session check, workspace membership
Workspacelist, load, switch, update
Brand profileload, update, brand voice/tone
Contentlist, detail, create, update, archive/delete
Bloglist, load body, save draft
Calendarmonth load, week load, schedule item
Campaignslist, detail, attach content
Social accountslist, connect placeholder, sync metadata
AI workflow metadatacreate draft, save generation result, update status
Publishing queueenqueue, list, update status
Notificationslist, mark read
Settingsload/update account and workspace settings

Output

text
reports/dbops/api-summary.json
reports/dbops/api-summary.csv
reports/dbops/api-summary.md

API result row

json
{
  "endpoint": "/api/content",
  "method": "GET",
  "actionLabel": "content.list",
  "status": 200,
  "apiDurationMs": 118,
  "prismaOrmOps": 7,
  "sqlStatements": 9,
  "sqlDurationMs": 39,
  "warnings": []
}

Suite B: Playwright standard task run

Goal

Measure representative user workflows through a real browser.

Playwright supports reusable authenticated browser state, which avoids logging in during every test. It recommends storing auth state under playwright/.auth and keeping it out of source control because it can contain sensitive cookies/headers. Source: Playwright authentication.

Command

bash
pnpm test:dbops:e2e-standard

Standard flows

FlowSteps
App shellOpen app, load dashboard, load workspace
Content creationCreate social post, save draft, view list
Blog draftCreate blog post, edit body, save
Calendar schedulingOpen calendar, schedule content, change date
Brand settingsLoad brand profile, update voice/tone settings
Social accountsLoad connections, open account detail
AI draft generationTrigger mocked AI generation, save result
Publishing queueEnqueue mocked post, view queue/status

Playwright network tracking

Playwright can monitor request and response events and wait for network responses after user actions. Source: Playwright network.

Use:

ts
page.on("request", request => {
  // capture request.method(), request.url(), headers
});

page.on("response", async response => {
  // capture response.status(), response.url(), DB measurement headers
});

Output

text
reports/dbops/e2e-standard.json
reports/dbops/e2e-standard.csv
reports/dbops/e2e-standard.md

Suite C: Exhaustive Playwright action/page-load crawl

Goal

Measure every page load, click, modal open, tab switch, filter, search, sort, pagination, save, and destructive action in the app.

This is a DB profiler, not a QA suite.

Command

bash
pnpm test:dbops:e2e-exhaustive

Action registry

Create:

text
tests/dbops/action-registry.ts

Example:

ts
export const actions = [
  {
    id: "dashboard.load",
    route: "/dashboard",
    steps: [
      { type: "goto", url: "/dashboard" }
    ],
  },
  {
    id: "content.open-create-modal",
    route: "/content",
    steps: [
      { type: "goto", url: "/content" },
      { type: "click", role: "button", name: "Create" }
    ],
  },
  {
    id: "content.filter.status-draft",
    route: "/content",
    steps: [
      { type: "goto", url: "/content" },
      { type: "click", role: "button", name: "Status" },
      { type: "click", role: "option", name: "Draft" }
    ],
  }
];

Measurement wrapper

For every action:

ts
const measurementId = crypto.randomUUID();

await page.setExtraHTTPHeaders({
  "x-tendsocial-measurement-id": measurementId,
  "x-tendsocial-measurement-label": action.id,
});

Collect all API responses and sum DB measurement headers.

Output

text
reports/dbops/e2e-exhaustive.json
reports/dbops/e2e-exhaustive.csv
reports/dbops/e2e-exhaustive.md
reports/dbops/e2e-exhaustive-hotspots.md

Hotspot ranking:

text
highest Prisma ORM operations
highest SQL statement count
highest SQL duration
highest browser duration
highest repeated API calls
highest background/polling noise

Traces

Enable Playwright trace on failure or retry. Trace viewer is useful for debugging which browser actions and network requests created a DB hotspot. Source: Playwright trace viewer.

Suggested config:

ts
use: {
  trace: "on-first-retry",
}

For dedicated investigation:

bash
npx playwright test --trace on

Initial thresholds

Action classTarget Prisma ops
Simple read1-3
Workspace/dashboard shell<10
Calendar/content list<15
Heavy editor save<10
AI generation save<10
Background batch jobBounded and paginated

Acceptance criteria

ItemTarget
API suite createdYes
Standard Playwright suite createdYes
Exhaustive Playwright suite createdYes
Reports emitted as JSON, CSV, and MarkdownYes
Measurement IDs correlate browser/API/Prisma activityYes
Top 20 DB hotspots identifiedYes
CI can run API suiteYes
Exhaustive suite can run manually/on demandYes

Sources

TendSocial Documentation