Demo District / Test labDownload UAT catalog ↓

Beyond the happy path

Good tests need
interesting problems.

Real accounts. Conflicting edits. A response that never makes it back.
Start a fresh scenario, follow the workflow, and check what actually happens.

8 working websites28 repeatable presets85 acceptance workflows
Ready for a fresh run

Each start creates isolated PostgreSQL data for this browser. Normal accounts and records are preserved. Runs last 24 hours; all tabs in this browser share the active run.

People / HRIS

One request.
Three different responsibilities.

Employees request leave. Managers decide for their team. HR monitors balances and adjusts allowances with an audit trail.

Public sample password for all People accounts: Leave123!

People sample accounts
NameRole / teamEmail
Alex MorganemployeeProduct[email protected]
Sam RiveraemployeeProduct[email protected]
Nina PutriemployeeOperations[email protected]
Maya ChenmanagerProduct[email protected]
Leo SantosmanagerOperations[email protected]
Harper EllisHR adminPeople[email protected]
28 scenarios

HRIS

Employee → manager → HR

Six accounts across three roles and two teams. Three requests in different states.

  1. Sign in as Alex and submit Annual leave on a free working day.
  2. Sign out, sign in as Maya, open Approvals and approve the new request.
  3. Sign out, sign in as Harper, inspect Alex's balances and Activity.
Expected outcome

The employee sees only their own requests. The manager sees only their team. Pending days move to approved days once; available balance stays consistent. HR sees the approval and audit actor.

hris-journey

HRIS

Reject, explain, resubmit

Signed in as Maya, the Product manager. Alex has a pending one-day request.

  1. Open Alex's pending request, choose Reject and try an empty note.
  2. Enter a reason of at least 10 characters and save.
  3. Sign in as Alex; inspect the rejection, balance, and submit another request on those dates.
Expected outcome

Missing rejection reason is rejected. Rejection releases the reserved day. A new request can reuse the released dates; the original audit trail remains.

hris-reject

HRIS

Permission checks beyond hidden buttons

Signed in as Alex, an employee. Nina belongs to a different team.

  1. Visit /hris/approvals and /hris/balances directly.
  2. Attempt decide and adjust-balance through /hris/api as Alex.
  3. Sign in as Maya and attempt a decision on Nina's LV-SEED-003.
Expected outcome

Restricted pages show access denied. Employee mutations return 403; a manager accessing another team's record receives 404. No status, balance or audit entry changes.

hris-permissions

HRIS

Reserved days consume the allowance

Signed in as Alex with a one-day Annual allowance already reserved by the seeded request.

  1. Submit another one-day Annual request on non-overlapping dates.
  2. Cancel the seeded pending request, then submit again.
  3. Sign in as HR and try to reduce the allowance below committed days.
Expected outcome

The first submission is rejected for insufficient balance. Cancelling releases the day. HR cannot set allowance below approved plus pending days.

hris-balance

HRIS

Two managers' tabs race a decision

Signed in as Maya with Alex's pending request at version 1.

  1. Open the same request in two tabs.
  2. Approve in one; try rejecting the old version from the other tab or API.
  3. Inspect balances and Activity.
Expected outcome

Exactly one transition is accepted. Stale decisions return 409. Balance and audit history reflect one decision only.

hris-conflict

HRIS

HR filters, sorting and pagination

Signed in as HR with ten requests across two teams, including seven extra half-day requests.

  1. Go to page two, then filter to Operations and Pending.
  2. Search an impossible name, clear filters and sort by leave start date.
  3. Open a record, use Back, then refresh.
Expected outcome

Filters intersect and reset pagination. Empty results are explicit. Back and refresh preserve the URL filters and ordering. Page controls are valid at both ends.

hris-filters

HRIS

Leave request saved, response interrupted

Signed in as Alex. The next leave submission commits, then returns a simulated 503.

  1. Submit a valid request on a free working day.
  2. Retry the unchanged form after the error.
  3. Inspect requests, balances and Activity.
Expected outcome

Only one request, one reserved amount and one submission audit entry exist.

hris-retry

HRIS

Employee session expires mid-form

Signed in as Alex. The session expires immediately before submitting leave.

  1. Complete and submit a valid request.
  2. Sign in again and inspect requests and balances.
Expected outcome

The expired session receives 401, the sign-in form appears, and no request or balance change is saved.

hris-expiry

Authentication

Sign in, sign out, come back

A registered account with a saved notebook. Signed out.

  1. Sign in with the sample account below.
  2. Open Saved, sign out, then use Back and reload Account.
  3. Sign in again and open Saved.
Expected outcome

Favorites return after login. Account details disappear after logout, including in another tab when it regains focus.

login

Authentication

Guest bag meets an existing account

The account has 2 Sand notebooks; the guest has 1. Both saved the same notebook.

  1. Sign in with the sample account.
  2. Open Your bag and Saved.
  3. Sign out, sign in again and check both lists.
Expected outcome

One notebook line with quantity 3 and one favorite. Logging in again does not merge the guest bag twice.

guest-merge

Authentication

Wrong password and lockout

The sample account has four failed sign-in attempts.

  1. Submit a wrong password of at least 8 characters.
  2. Then submit the correct sample password.
Expected outcome

The fifth wrong attempt says email or password is incorrect. The next attempt is rate limited for 15 minutes. Starting this scenario again resets the counter.

login-lockout

Authentication

Session expires while editing

Signed in. The session expires immediately before the next profile save.

  1. Edit Full name, then Save details.
  2. Reload the page, sign in again and inspect the name.
Expected outcome

Save is rejected with a sign-in message. The original name remains; the expired session cannot change the account.

session-expired

Search & filters

Combined filters and browser history

Ten jobs, including multiple teams, job types and remote roles.

  1. Combine Team, Job type and Remote only.
  2. Search for an impossible term, then clear the filters.
  3. Set filters again, open a result, use Back and reload.
Expected outcome

Every result matches every active filter. Zero results is clear. Clear filters resets all controls. URL, reload and Back preserve the same filtered list.

filters

Boundaries

A truly empty workspace

Tasks and support tickets are empty.

  1. Inspect board counts, then open All tasks.
  2. Create a task and return to the board.
  3. Open Careloop and create its first request.
Expected outcome

Counts show zero without NaN. Empty states have working creation links. New records appear and persist after reload.

empty-workspace

Boundaries

At the record limit

200 tasks already exist, the workspace limit.

  1. Try to create another valid task.
  2. Delete one task, then try again.
Expected outcome

The extra task is rejected without changing the count. Deleting one creates room for exactly one new task.

full-workspace

Search & filters

Unicode, long text and literal markup

Tasks include accented text, Arabic, Japanese, emoji and literal HTML-like text.

  1. Search for café, then Japanese text 東京.
  2. Inspect and edit the task containing <img text.
  3. Reload and inspect the saved description.
Expected outcome

Search handles case and surrounding whitespace. User text remains literal text and never creates executable HTML. Long text stays within the layout.

unicode

Commerce

The last notebook

One notebook remains in inventory and one is in the bag.

  1. Complete checkout with valid sample details.
  2. Open the notebook product, then cancel the order.
  3. Cancel again through the API using the same order ID.
Expected outcome

Checkout consumes the last item. Cancellation restores exactly one item; repeating cancellation never increases stock twice.

last-item

Bookings

Overlapping and adjacent stays

Bamboo House is booked from three days from today through five days from today.

  1. Note the seeded booking dates.
  2. Try an overlapping Bamboo House stay.
  3. Try a stay starting on the seeded checkout date.
Expected outcome

Overlap is rejected. Back-to-back stays are allowed. Cancelling the original frees its dates.

booking-conflict

Bookings

One ticket, two contenders

Seven of eight Clay Club tickets are reserved in this test workspace.

  1. Open this event in two tabs of this browser.
  2. Reserve the last ticket in each tab.
  3. Cancel the successful reservation and try again.
Expected outcome

Only one additional ticket can be reserved. Stale tabs cannot oversell. Cancellation frees one place.

last-seat

Concurrency

Two tabs edit the same task

The normal seeded project board.

  1. Open the same task in two tabs.
  2. Save a changed title in the first tab.
  3. Save the older form in the second tab.
Expected outcome

The stale form receives a conflict message. Reloading shows the first tab's change; it is never silently overwritten.

stale-edit

Network recovery

Slow save and double click

The next task save takes 1.5 seconds before processing.

  1. Fill a valid task and rapidly submit twice.
  2. Inspect the disabled busy control and wait for completion.
Expected outcome

Exactly one task is created. Pending state prevents a second submission and clears when the response arrives.

slow-save

Network recovery

Server error before saving

The next task save returns 503 before changing the database.

  1. Fill and submit a task.
  2. Inspect the error and unchanged form values.
  3. Submit the same form again.
Expected outcome

The first save changes nothing. The retry creates one task, retains the entered values and clears the error.

retry-save

Network recovery

Save succeeds, response is lost

The next task save commits, then returns a simulated 503 instead of its result.

  1. Fill and submit a task.
  2. Retry the unchanged form after the error.
  3. Count matching tasks and reload.
Expected outcome

The retry reuses its request ID. One task exists, even though the first response reported an error.

lost-response

Network recovery

Order commits before a lost response

One notebook is in the bag. The next checkout commits, then returns a simulated 503.

  1. Enter sample customer details and place the order.
  2. Retry the unchanged checkout after the error.
  3. Inspect order history and inventory.
Expected outcome

The same order is returned. History contains one order and inventory decreases only once.

checkout-lost

Network recovery

Temporary HTTP rate limit

The next sign-in returns 429 with Retry-After: 1.

  1. Sign in with the sample account.
  2. Read the error, wait one second and retry.
Expected outcome

The first response changes no account state. A retry signs in normally and the error clears.

rate-limit

Network recovery

Initial page data fails

The next workspace bootstrap returns 503.

  1. Open the site and inspect its error state.
  2. Use Retry loading, without re-entering the URL.
Expected outcome

A visible error and keyboard-accessible retry are offered. Retrying displays the seeded board.

load-error

Detector controls

Known passing discount

A 100000 IDR basket with the correct discount implementation.

  1. Enter SAVE10 in coupon-input.
  2. Click apply-coupon.
  3. Assert order-total has exact text 90000.
Expected outcome

The business assertion passes: total is 90000.

coupon-pass

Detector controls · intentional defect

Known failing discount

A 100000 IDR basket with an intentional discount defect.

  1. Enter SAVE10 in coupon-input.
  2. Click apply-coupon.
  3. Assert order-total has exact text 90000.
Expected outcome

A correct test runner reports a FAILED assertion: expected 90000, actual 100000. The defect is intentional.

coupon-fail

A repeatable starting point.

Start the same preset again to get fresh data. Failures such as 503, 429, expiry and lost responses happen once at the documented action. Other operations use the real application and PostgreSQL.

Form & Field account presets use [email protected] / District123!. These are public synthetic credentials for isolated sample data.

Check the outcome, not just the click.

The catalog includes role permissions, state transitions, totals, ownership, retries, filters and accessibility checks. It is an acceptance plan, not a Veriflow workflow import or a claim that every possible edge case is covered.

Download all 85 workflows as JSON →

Browse all 85 acceptance workflows
HRIS-01 · hris-journey

Three-role approval journey

Employee submits, manager approves, HR checks the balance and audit trail.

Expected: Pending → Approved; one reserved amount becomes used once. Each role sees only allowed data.

HRIS-02 · hris-reject

Rejection requires context

Reject with a blank or short reason, then a valid explanation.

Expected: Invalid reasons do not mutate state. Valid rejection releases days and is visible to the employee.

HRIS-03 · hris-permissions

API role enforcement

As employee POST decide/adjust-balance, including a forged role field.

Expected: 403; roles come from the authenticated server session, never submitted fields.

HRIS-04 · hris-permissions

Manager team isolation

Maya attempts to approve Nina's request or reads Operations data.

Expected: No cross-team data is returned; the attempted decision returns 404.

HRIS-05 · hris-permissions

Employee ownership

Alex attempts to cancel Sam's request or forge employeeId on submission.

Expected: Cancellation is denied; a submission always belongs to the signed-in employee.

HRIS-06 · hris-balance

Balance reservation

Submit more days than available, counting Pending requests too.

Expected: 409; no request or audit row and no negative balance.

HRIS-07 · hris-balance

Cancellation restores days

Cancel Pending and Approved future requests, then repeat.

Expected: Days are released once. Repeating the same request ID is idempotent; a new invalid transition gets 409.

HRIS-08 · hris-journey

Overlap across leave types

Submit Sick leave overlapping Pending Annual leave.

Expected: Overlap is rejected across types and pending/approved states.

HRIS-09 · hris-journey

Working-day calculation

Submit Friday through Monday, then weekend-only dates.

Expected: Friday–Monday counts two days; weekend-only is rejected.

HRIS-10 · hris-journey

Half-day boundary

Submit one weekday as Half day, then a multi-day Half day.

Expected: Single weekday reserves 0.5; multi-day half leave is rejected.

HRIS-11 · hris-journey

Invalid dates

Submit reversed, past, impossible, over-30-day and over-one-year dates.

Expected: Validation errors with no mutation, even when HTML validation is bypassed.

HRIS-12 · hris-conflict

Concurrent decisions

Send approve and reject for version 1 concurrently.

Expected: One succeeds, one gets 409; exactly one decision audit entry.

HRIS-13 · hris-conflict

Terminal status transitions

Try approving Rejected, Cancelled or already Approved requests.

Expected: 409; terminal requests cannot return to Pending or change decision.

HRIS-14 · hris-balance

HR adjustment guard

Reduce allowance below pending plus approved, then set a valid amount with a reason.

Expected: Invalid adjustment is rejected; valid change is versioned and audited.

HRIS-15 · hris-balance

Stale HR balance edit

Submit two adjustments with the same employee version.

Expected: Second gets 409; the first adjustment is preserved.

HRIS-16 · hris-filters

Filter and pagination interaction

Filter while on page 2, clear and sort, use Back and reload.

Expected: Page resets on filter changes; count, rows and URL stay consistent.

HRIS-17 · hris-retry

Ambiguous submission retry

Retry an unchanged submission after its response is interrupted.

Expected: Same record ID; one reservation and one audit entry.

HRIS-18 · hris-expiry

Expired authorization

Submit after session expiry, then sign in again.

Expected: 401; no request is created and no balance is consumed.

HRIS-19 · hris-journey

Role switch and logout

Sign out as employee, sign in as manager then HR; replay old session tokens.

Expected: Session tokens rotate and old tokens cannot access private data.

HRIS-20 · hris-journey

Audit integrity

Inspect actor, target, old/new decision and timestamp after submit, decide, cancel and balance change.

Expected: Each successful operation records one immutable audit event; rejected operations record none.

AUTH-01 · login

Email normalization

Sign in with [email protected]; repeat with surrounding spaces through the API.

Expected: The same account is used, with no duplicate user.

AUTH-02 · login

Wrong password vs unknown user

Try a wrong password, then an unknown email.

Expected: Both return the same generic error and no account data.

AUTH-03 · login

Duplicate registration

Register the sample email again using different capitalization.

Expected: 409 conflict; existing account and password are unchanged.

AUTH-04 · login

Password confirmation

Register with mismatched passwords; correct the confirmation.

Expected: Mismatch blocks submission; correction allows creation.

AUTH-05 · login

Password bounds

Submit passwords of 7, 8, 128 and 129 characters via the API.

Expected: Only 8 through 128 characters are accepted; whitespace in passwords is significant.

AUTH-06 · login-lockout

Persistent lockout

Trigger lockout, reload and try the correct password.

Expected: Reload does not reset the 15-minute rate limit.

AUTH-07 · guest-merge

Guest favorites and cart merge

Sign in twice, with a logout between attempts.

Expected: Guest cart merges once and saved IDs remain unique.

AUTH-08 · session-expired

Expired session write

Save an edited profile after expiry.

Expected: 401; stored profile is unchanged.

AUTH-09 · login

Logout across tabs

Open Account in two tabs, sign out in one, focus the other.

Expected: The other tab refreshes its session and hides private profile data.

AUTH-10 · login

Session rotation

Inspect HttpOnly cookies before and after sign-in and sign-out; replay the old token via API.

Expected: Tokens rotate; the old token cannot read the account.

AUTH-11 · login

Account isolation

Use two browser contexts and try to cancel the other user's order ID.

Expected: 404 and no change to another user's order.

FILTER-01 · filters

Filter intersection

Combine a team, job type, remote flag and search text.

Expected: Results match all active constraints, not just the last one.

FILTER-02 · filters

Zero results and recovery

Search an impossible term, then clear all filters.

Expected: Zero state is explicit; all ten jobs return.

FILTER-03 · filters

Back and refresh

Filter, open a job, use Back, then reload.

Expected: Filter values and result count agree with the URL.

FILTER-04 · unicode

Case and whitespace

Search CAFÉ and then padded café; search 東京.

Expected: Case and outer whitespace do not change matching; Unicode works.

FILTER-05 · filters

Literal special characters

Search for .* [ ] % and an apostrophe.

Expected: Input is literal text, never a regex or query expression.

FILTER-06 · filters

Invalid URL filters

Load a list with an unknown enum, invalid boolean and nonnumeric guest count.

Expected: Invalid values fall back to valid defaults; controls and results agree.

FILTER-07 · filters

Sort after filtering

At Haven, choose Ubud and sort price low then high.

Expected: Only Ubud stays remain and prices are correctly ordered.

FILTER-08 · filters

Saved jobs plus filters

Save two jobs; combine filters on Saved jobs; remove one.

Expected: Only saved matching jobs appear; count updates after removal.

FILTER-09 · filters

Dietary intersection

At Table & Thyme combine Bowls, vegan and text search.

Expected: Only matching vegan bowls remain; clear resets the checkbox too.

FORM-01 · empty-workspace

Whitespace-only input

Create a task or ticket using only spaces in required text.

Expected: Server validation rejects it even if HTML validation is bypassed.

FORM-02 · unicode

Long values

Try a 120-character task title and then 121 through the API.

Expected: 120 is accepted; 121 is rejected without partial mutation.

FORM-03 · unicode

Markup remains text

Save literal <img src=x onerror=alert(1)> in a task description.

Expected: The exact text is displayed; no image or script executes.

FORM-04 · filters

Unsafe portfolio URL

Apply to a job using javascript: or data: as the portfolio URL.

Expected: The server accepts only http: or https: URLs.

FORM-05 · retry-save

Values survive failed save

Enter multiple fields, trigger 503, then inspect and retry.

Expected: Entered values remain; error clears on success.

FORM-06 · empty-workspace

Enter-key submit

Complete a form using Tab and submit with Enter.

Expected: Exactly one record is created with an accessible result.

CART-01 · last-item

Stock boundary

Request quantity zero, negative, fractional, string, 1 and above stock.

Expected: Only valid integer quantities within stock are accepted.

CART-02 · last-item

Aggregate stock across colors

Add the same product in different colors beyond combined availability.

Expected: Stock is enforced across variants; failed additions change nothing.

CART-03 · coupon-pass

Coupon normalization and repeat

Apply padded lowercase save10 twice.

Expected: 10% applies once and the total remains 90000.

CART-04 · coupon-pass

Invalid coupon after valid

Apply SAVE10, then an invalid code.

Expected: Error appears; the accepted coupon and total remain consistent.

CART-05 · last-item

Empty bag coupon

Remove the final line, then apply a coupon via API.

Expected: Coupon is cleared and the empty-bag request is rejected.

CART-06 · checkout-lost

Pickup vs delivery validation

Choose pickup with no address; switch to express delivery.

Expected: Pickup needs no address; delivery requires address and five-digit postal code.

CART-07 · checkout-lost

Server-owned prices

Submit a fake total or unit price with checkout.

Expected: The server calculates catalog prices and shipping itself.

CART-08 · checkout-lost

Duplicate checkout

Send the same checkout request ID twice, including concurrently.

Expected: One order and one stock deduction; retries return the same order.

CART-09 · last-item

Repeated cancellation

Cancel an order twice.

Expected: Stock is restored only once.

BOOK-01 · booking-conflict

Overlapping dates

Try partial overlap, identical dates and containing dates.

Expected: Every overlap with a confirmed booking is rejected.

BOOK-02 · booking-conflict

Adjacent dates

Start a new stay exactly on an existing checkout date.

Expected: Adjacent stays are accepted.

BOOK-03 · booking-conflict

Invalid date ranges

Try same-day, reversed, impossible date, 31 nights and over one year ahead.

Expected: Invalid ranges are rejected without a booking.

BOOK-04 · booking-conflict

Guest capacity

Try zero guests and one more than room capacity.

Expected: The server rejects both requests.

BOOK-05 · last-seat

Stale availability race

Reserve the final ticket from two tabs concurrently.

Expected: One succeeds, one fails; confirmed total never exceeds capacity.

BOOK-06 · last-seat

Cancel and reserve again

Cancel a confirmed reservation and repeat the cancellation.

Expected: Capacity is released once and can be reserved again.

STATE-01 · stale-edit

Lost update prevention

Save two different edits based on the same task version.

Expected: First succeeds; second receives 409 and does not overwrite it.

STATE-02 · empty-workspace

Refresh after create

Create a task, reload its details and the board.

Expected: The record is saved in PostgreSQL and counts agree.

STATE-03 · empty-workspace

Deleted record deep link

Delete a task, then revisit its old details URL.

Expected: A useful not-found state replaces the edit form.

STATE-04 · full-workspace

Record count boundary

Attempt task 201; delete one and retry.

Expected: The limit is enforced and recovering space works.

STATE-05 · filters

Duplicate active application

Apply to the same job twice, then withdraw and apply again.

Expected: Active duplicate is rejected; reapplication after withdrawal works.

STATE-06 · empty-workspace

Resolved ticket reply

Create and resolve a ticket, attempt reply via API, reopen and reply.

Expected: Closed reply is rejected; reopened reply persists.

STATE-07 · empty-workspace

Cancellation confirmation

Dismiss a delete/cancel confirmation, then accept it.

Expected: Dismissal changes nothing; acceptance performs the change once.

NET-01 · slow-save

Rapid duplicate clicks

Double-click a slow submit.

Expected: One mutation, visible busy state, then enabled controls.

NET-02 · retry-save

503 before commit

Submit then retry unchanged.

Expected: First request changes nothing; retry creates one record.

NET-03 · lost-response

503 after commit

Submit then retry unchanged.

Expected: Same request ID recovers the already-created record.

NET-04 · rate-limit

429 retry

Inspect Retry-After and retry after one second.

Expected: A useful error appears; a later attempt succeeds.

NET-05 · load-error

Initial load recovery

Trigger failed bootstrap, then use Retry loading.

Expected: No infinite loading screen; seeded data appears on retry.

API-01 · empty-workspace

Malformed request

POST malformed JSON, an array, unknown action and missing fields.

Expected: 400 responses with safe messages; no partial records.

API-02 · empty-workspace

Payload limit

POST more than 16 KiB to each business API and the lab API.

Expected: 413, with no state changes.

API-03 · empty-workspace

Cross-origin mutation

POST with an unrelated Origin or Sec-Fetch-Site: cross-site.

Expected: 403 before creating or mutating any state.

API-04 · lost-response

Reused request ID with new payload

Replay a successful request ID with changed task data.

Expected: 409; the first record is unchanged.

API-05 · empty-workspace

Workspace isolation

Read and edit record IDs from another browser context.

Expected: Other workspace data is absent and mutations return 404.

UX-01 · filters

Keyboard-only filters

Navigate controls with Tab and choose values with the keyboard.

Expected: Focus is visible and every filter is operable and labeled.

UX-02 · unicode

Mobile long content

Use a 375px viewport with long and Unicode task content.

Expected: No horizontal document overflow or clipped controls.

UX-03 · retry-save

Accessible error and recovery

Trigger a server error, inspect alert semantics, retry.

Expected: The error is announced and removed when the operation succeeds.

CONTROL-01 · coupon-fail

Known bad assertion

Assert exact total 90000 after SAVE10 in the broken scenario.

Expected: A functioning test runner reports failure with actual 100000.

CONTROL-02 · coupon-pass

Known good assertion

Run the same assertion in the fixed scenario.

Expected: The same test passes with actual 90000.

LAB-01 · login

Fresh-run repeatability

Start a preset, mutate it, then start the preset again.

Expected: A new isolated run has its original seed data.

LAB-02 · login

Normal data preservation

Create a normal record, run a preset, then leave the lab.

Expected: The normal browser's data and cookies are restored unchanged.