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