Complete Mobile App QA Test Guide

A release-ready test plan covering every current Clean Estimate Pro mobile page, workflow, role, builder, permission, offline path, and device integration.

Advancedownermanageradminsales repcrew leadtechnicianqaUpdated 2026-08-10

Complete Mobile App QA Test Guide

Use this guide for release candidates, regression passes, store builds, and production smoke tests of the Clean Estimate Pro mobile app. It covers the shared six-tab Fusion workspace, role dashboards, global search, CRM, leads, customers, messages, company-line calling, jobs, payments, settings, proposal detail, and the native Residential, Commercial, Fleet, Holiday Lights, Generic Quote, and Asphalt Maintenance estimate builders.

The route inventory below groups related permission-driven pages into test surfaces. A run is complete only when every applicable surface has a recorded result and every critical connected workflow has been completed without resetting the test data between steps.

Test only approved QA accounts and QA records. Never edit a real customer, call or message a real contact, collect a real payment, or clear another tester's data.

What "complete" means

Record one of these results for every test case:

ResultMeaning
PASSThe observed result matches the expected result and evidence is attached when required.
FAILThe result is wrong, incomplete, unsafe, misleading, or inconsistent with another surface.
BLOCKEDThe test cannot run because credentials, seed data, a provider, a device capability, or an environment dependency is unavailable.
NOT APPLICABLEThe approved build manifest explicitly excludes the feature or platform. Do not use this for a failure.

Do not mark a page PASS because it opened once. Exercise its controls, loading state, empty state, error state, role restrictions, back navigation, refresh behavior, and any external handoff.

Non-negotiable safety rules

  • Prefix every created record with QA-MOBILE-{runId}.
  • Use only an approved QA inbox and approved test phone number.
  • Use Stripe test mode and published Stripe test cards only.
  • Capture evidence before retrying or changing a failed state.
  • Stop the run immediately for cross-organization data, authentication bypass, real-customer communication, real-money risk, or destructive production-data behavior.
  • Do not clear the local cache while pending changes are greater than zero unless the test specifically validates data-loss warnings using disposable data.
  • Do not test company-line calling until the destination, inbound caller, and

representative callback number have all been confirmed as QA-owned.

  • Do not repair the product during the test pass. Finish evidence collection and triage first.

Test run record

Copy this table into the run report before testing.

FieldValue
Run ID
Tester
Date and timezone
Git SHA / release tag
App version
Build number
Expo runtime / OTA update ID
Build channelStore / internal / development / Expo Go
Backend base URL
Organization ID and name
Device model
OS and version
Screen size
Network types testedWi-Fi / cellular / offline
Roles tested
Stripe modeMust be test
Approved QA email
Approved QA phone

Preflight

  1. Install the exact candidate artifact. Do not substitute a local development build for a store or internal release candidate.
  2. Capture the app version, build number, release channel, runtime version, and backend base URL.
  3. Confirm the backend is the environment named in the release ticket. A production run should use https://app.cleanestimate.pro.
  4. Confirm the device clock, date, timezone, locale, and network state.
  5. Confirm the QA organization name and ID before opening any customer data.
  6. Confirm Stripe is in test mode before opening any checkout.
  7. Confirm the approved test email and phone can receive messages.
  8. Reset camera, microphone, photo-library, location, and notification permissions for the permission pass.
  9. Run the automated mobile checks listed in the release ticket before manual testing.
  10. Capture a clean launch video from app icon to the first usable screen.

Expected preflight result: the splash screen clears, no red error screen appears, the app does not hang on a blank screen, and no secret, access token, password, or full payment data appears in device logs.

For the P0 estimate-entry smoke pass, open the residential builder from both a scheduled lead's I'm at the door action and the lead profile's New estimate action. Repeat estimate-type entry for commercial, fleet, and holiday lights. Each builder must show its first usable native step without an app restart, blank screen, or preloadedRoutes.filter JavaScript error.

For canvass contact capture, select a lead-producing disposition and type 5555555555 into Phone. The visible value must become 555-555-5555, and the formatted number must remain attached to the saved QA lead.

Required device matrix

Matrix rowPriorityWhat it proves
Current Android phone, standard viewportP0Primary native release path
Small Android phone or smallest supported emulatorP0Keyboard, sticky footer, tab bar, and long-form usability
Current physical Android phoneP0 for notifications/camera/callsReal permissions, FCM call delivery, camera, audio, and background/killed lifecycle
Current iPhoneP0 when iOS is in the releaseiOS keyboard, safe areas, permissions, links, and lifecycle
Large phone or tabletP1Responsive layout and excessive line length
Large text / display scalingP1Accessibility and reachable actions
Dark system themeP1System-dialog and external-handoff readability, even when the app uses a light theme
Slow or unstable connectionP1Loading, retry, duplicate-submit prevention, and recovery

Run all P0 connected journeys on each release platform. A single-platform visual pass is not platform parity.

Usable-space regression pass

On the smallest supported Android and iPhone viewports, test every builder, page-sheet modal, bottom sheet, and pinned action bar used by the selected persona.

  1. Confirm no card, field, label, or action extends beyond the left or right

screen edge and the page does not scroll horizontally.

  1. Confirm two- and three-field rows stack when their labels and controls

cannot fit at a usable width.

  1. Confirm the header and close control remain below the status bar, notch, or

Dynamic Island.

  1. Confirm pinned Back, Next, Save, Close Kit, approval, and

submit actions remain above Android navigation controls and the iPhone home indicator.

  1. Open the keyboard in the last input on a long form. Verify the active field

and final action can still be reached without switching focus unexpectedly.

  1. Repeat a tall bottom sheet with large text enabled. Verify its content

scrolls within the safe screen height and can still be dismissed.

  1. Rotate any supported tablet or large phone once and confirm cards remain

bounded to the available width.

Any clipped or unreachable action is a release-blocking failure for its workflow.

Required personas

PersonaRequired coverage
OwnerFull sales workspace, organization edits, pricing/tax review, proposal close, job payment
ManagerFull sales workspace, organization edits, proposal close, job payment
Sales representativeAssigned sales data, CRM, all builders, proposal close, outbound and inbound company calling
Crew leadCrew-scoped Work and Jobs, payment collection, restricted quote behavior
TechnicianCrew-scoped Work and Jobs, no payment collection, restricted quote behavior
CustomerSecure proposal view, acceptance, signature, hosted checkout

Use separate accounts for each role. Changing a role mid-session does not replace a real role-boundary test.

Seed data

Prepare these records before the run. Every item must belong to the QA organization.

SeedMinimum state
Full customerName, company, email, phone, complete address
Sparse customerName only
Lead ANew, no appointment
Lead BAppointment today
Lead CPast appointment requiring follow-up
Lead DConverted or lost
Message threadsRead, unread, needs reply, email-only contact, phone-only contact
EstimatesDraft, sent, viewed, accepted, declined, expired, partially paid, paid
JobsScheduled, in progress, completed, cancelled
Invoice jobPositive balance due
Paid jobZero balance
No-invoice jobJob without an invoice
Crew assignmentsOne assigned crew account and one crew account without assignment
Multi-truck jobOne live job assigned to at least four trucks with distinct crews
PricingActive residential pricing version with known minimums and tax
Red LineOne account with access and one without access

Also create unique builder records during the run so autosave, delivery, sync, and cross-screen linkage are proven.

Codex QA residential catalog fixture

The approved Codex mobile fixture uses organization d673a4e6-f2d5-4ab6-8430-866b9b08a5ab (Codex QA Power Washing 20260308). If its active pricing version exists but Residential reports that verified pricing is unavailable, check that both the legacy catalog and the organization's default price book contain residential services.

From the cleanestimatepro repository, an authorized QA maintainer can run:

npx --yes tsx --env-file=.env.local scripts/qa/bootstrap-codex-residential-catalog.ts --org-id d673a4e6-f2d5-4ab6-8430-866b9b08a5ab

The script is deliberately limited to that exact organization ID, Codex QA slug/name, and an active owner@test.local owner membership. It copies missing services and add-ons through the standard organization bootstrap helpers, synchronizes them through the production residential price-book bridge, and validates the canonical mobile bundle. It refuses every other organization.

Expected current output is pricing version 1 with 9 services, 7 add-ons, and a canonical bundle revision. Then sign in as owner@test.local, tap Try pricing again, and confirm the builder shows Active pricing v1 before running RES-AI-01. Never adapt this fixture command to a customer organization.

Guarded signed mutation fixture

The signed job-lifecycle and customer-mutation suites use a separate guarded fixture generator. It refuses every organization except Codex QA Power Washing 20260308, requires the exact QA owner, accepts only mzr5165@gmail.com and the approved 7177031103 or 7178251710 test number, and defaults to no writes unless an explicit mode is supplied.

Run the preflight first with a fresh 8–24 character token and the exact release identity shown in More > About:

node --env-file=.env.local scripts/qa/seed-signed-mutation-fixtures.mjs `
  --fixture-token <unique-token> --qa-email mzr5165@gmail.com `
  --qa-phone 7177031103 --expected-app-version <version> `
  --expected-build-number <build> --expected-update-id <eight-character-id> `
  --device-serial <serial> --dry-run

Use --confirm-write in place of --dry-run only after the preflight matches the installed signed release. The script prints the exact job-lifecycle, customer-mutation, cleanup-preflight, and cleanup commands for the allocated record numbers and UUIDs. Do not hand-edit those identifiers. Emulator runs also require the explicit --allow-emulator acknowledgement.

The lifecycle contact has an example.invalid email and no phone. The customer-mutation record uses the approved recipient because that suite sends one real QA email and records one $0.01 manual check payment. It never sends an SMS or collects a card payment. Cleanup verifies every relationship, amount, truck, proof object, and identifier before deleting mutable records. The one accepted synthetic estimate remains isolated because production correctly prevents deletion of accepted contracts; cleanup never invokes the organization-wide estimate deletion RPC.

For populated visual evidence on the shared tabs, use the separate core-visual fixture. It inserts only direct synthetic QA rows: one purple lead appointment using the supported site_visit appointment type, one blue scheduled truck job, six compact Inbox conversations, a conversation containing SMS bubbles plus an aligned internal event, and six scored call-history cards. All contact numbers are reserved 717-555-01xx numbers, all emails use example.invalid, and every provider, provider-message, and recording identifier is null. The script never calls a messaging, calling, or webhook endpoint.

node --env-file=.env.local scripts/qa/seed-signed-core-visual-fixtures.mjs `
  --fixture-token <unique-token> --dry-run

After confirming the exact QA organization, actor, truck, record counts, and fresh contact keys, rerun with --confirm-write. Preserve the emitted manifest path and use the exact cleanup command printed by the script. Cleanup fails closed if any identifier, relationship, reserved contact, provider field, or linked record differs from the manifest.

Run the signed core-surface suite with the same unique core-visual token. The runner derives the exact QA-COREVIS-<TOKEN>-01 Inbox contact, searches for that conversation, verifies its Call and Text actions, then opens that exact thread. Evidence is valid only when both synthetic SMS bubbles, the aligned internal-note event, and its estimate-view follow-up text are visible. Do not accept a screenshot of whichever Inbox card happened to sort first.

For Schedule evidence, leave the untimed follow-up summary collapsed. The Day capture must show the compact follow-up count plus the token-scoped purple appointment and the seeded blue House Wash job. After selecting Week, wait for the seeded $425 job revenue and House Wash card before taking the weekly screenshot; a temporary loading label or zero-dollar summary is not evidence of the completed weekly view.

Role and permission expectations

CapabilityOwnerManagerSales repCrew leadTechnician
Six stable Fusion tabsYesYesYesYesYes
CRM lead/customer secondary routesYesYesYesNoNo
Native estimate launchersYesYesYesNoNo
Crew-scoped assigned jobsOrganization viewOrganization viewSales route viewYesYes
Home organization viewYesYesAssigned onlyAssigned onlyAssigned only
Schedule organization view and revenueYesYesNoNoNo
Own My Pay workspaceNoNoNoConfigured commission pay onlyConfigured commission pay only
Manager pipeline commissionActive Red Line onlyActive Red Line onlyNoNoNo
Collect job card/cash/check paymentYesYesNoYesNo
Edit organization settingsYesYesNoNoNo
Edit own profileYesYesYesYesYes
View pricing and tax referenceYesYesNoNoNo
Red Line detailMembership-controlledMembership-controlledMembership-controlledMembership-controlledMembership-controlled
Make/answer company callsYesYesPermission-controlledNoNo

Every role uses Home, Schedule, Create, Inbox, Phone, and More. Role-specific behavior applies inside those tabs, the pages exposed from More, organization settings, payment collection, API scoping, and Red Line access. A stable tab does not bypass backend permissions.

Complete page inventory

Use this as the route-coverage ledger.

ID rangeSurfaceCount
AUTH-01 to AUTH-03Sign in, forgot password, and session lifecycle3
TAB-01 to TAB-06Home, Schedule, Create, Inbox, Phone, More6
CAM-01 to CAM-02Native canvass campaign editor and Canvass workspace from More2
PHONE-01Call intelligence detail1
FIELD-01 to FIELD-02Crew Jobs and assigned Schedule route2
FIND-01Global Search1
CRM-00 to CRM-03Clients & Leads list, lead detail, customer detail, and account detail4
BRIEF-01Pre-knock brief1
EST-01 to EST-02Estimate list and estimate-type picker2
RES-01 to RES-06Residential builder6
COM-01 to COM-09Commercial builder9
FLT-01 to FLT-08Fleet builder8
HOL-01 to HOL-09Holiday Lights builder9
EST-GEN-01 and WEB-02Native Generic Quote and Asphalt Maintenance handoff2
CLOSE-01 to CLOSE-02Proposal detail and customer close flow2
MGR-01 to MGR-02Approval detail and estimate reassignment2
JOB-01 to JOB-02Jobs list and job detail2
INV-01 to INV-02Invoices list and invoice detail2
MSG-01Message thread1
SET-01 to SET-07Profile, Organization, Pricing, Tax, Notifications, Offline, About7
NAV-01Not-found route1
TotalCore release-coverage inventory72

If the installed build shows an extra tab or screen, add it to the ledger and test it. If a listed surface is missing, record FAIL unless the approved build manifest explains the difference.

AUTH: authentication and session suite

AUTH-01 Sign in

  1. Launch from a signed-out cold start.
  2. Submit with both fields empty.
  3. Submit with only email, then only password.
  4. Enter an invalid email/password combination.
  5. Enter valid credentials and tap Sign In once.
  6. Repeat using the keyboard submit action.
  7. Tap Sign In rapidly while the request is active.
  8. Background and foreground during sign-in.

Expected:

  • Missing fields show Missing information.
  • Invalid credentials show Sign In Failed without revealing account existence or secrets.
  • The active request shows Signing In... and Checking your account....
  • One user action creates one authentication request.
  • A successful login opens the correct organization and role workspace.
  • The keyboard never hides the submit action permanently.

AUTH-02 Forgot password

  1. Open Forgot your password?.
  2. Submit an empty email.
  3. Submit the approved QA email.
  4. Verify Check your inbox, Back to sign in, and Send another link.
  5. Open the reset email and complete the secure web flow.
  6. Return to the app and sign in with the new password.

Expected: the reset is sent once, the app does not expose whether an unapproved address exists, and back navigation returns to Sign in.

AUTH-03 Session lifecycle

  • Cold-start while signed in.
  • Background for 30 seconds, 2 minutes, and 15 minutes.
  • Resume after network changes.
  • Lock and unlock the device.
  • Force-stop and relaunch.
  • Allow a saved access token to expire when the test environment supports it.
  • Sign out, cancel once, then confirm sign-out.
  • Immediately sign in as a different role without force-stopping or relaunching

the app, then repeat the account switch several times.

  • Verify signed-out users cannot reopen cached private screens through deep links or the app switcher.

Expected: valid sessions survive normal lifecycle changes; refresh is deduplicated; explicit sign-out removes the push token and returns to Sign in; and an immediate account switch waits for logout cleanup before authenticating the next user. The new role opens its own workspace without a Supabase schema error, stale permissions, or requiring a force-stop.

TAB-01 Home

Test every Home section:

  • Greeting, user name, organization, and sync state.
  • Today, Week, Month, Quarter, and Year period control.
  • Owner/manager appointments, jobs, revenue, pipeline, close rates, lead-type

close rates, sales performance, crew performance, and hot follow-ups.

  • Sales agenda first, followed by hot follow-ups, call/email/text tasks,

personal pipeline, and performance.

  • Crew and technician assigned jobs first, with performance pay only when

the organization enables crew performance pay and that membership uses the commission pay model.

  • For crew and technician roles, switch through all five periods and confirm

the blue summary, section heading, job set, and empty-state copy use the selected period. Cancelled jobs must be absent; completed and invoiced jobs scheduled inside the period must remain visible.

  • Confirm the field route metric reports assigned stops or the address-ready

fraction. It must not display calculated or estimated mileage when the API does not provide real route distance.

  • Delay the assigned-jobs request, then fail it without cached data. Loading

must not claim there are zero jobs; failure must show Assigned work unavailable, and Retry must request the data again.

  • New-lead, repeated-estimate-view, and viewed-within-24-hours hot signals.
  • Create a lead several days before its appointment and verify it appears in

the period containing appointment_date, not the period containing created_at. Repeat across an organization-local midnight and a DST boundary.

  • Convert a lead to an estimate without changing its appointment date and start

time. Home must show one linked appointment; changing the time or using an unlinked estimate must preserve both appointments.

  • Create two timed agenda records that overlap on the same day. Confirm a

schedule-conflict row appears under Needs attention and opens the conflicting record. Remove the overlap and confirm the row clears.

  • Load an Inbox conversation with needs_response enabled and confirm the Home

bell shows an unread dot and opens Inbox. Clear the response state and confirm the dot disappears after refresh.

  • Search workspace row.
  • Local draft cards and resume behavior.
  • Pull to refresh.
  • Live-dashboard catch-up card.
  • Offline or queued sync chip.
  • In a preview or test environment, return a successful Home activity response

with {}, then repeat with only user and only organization. The screen must keep the signed-in account and selected workspace visible, render valid rows that are present, and use empty states for omitted collections.

  • Return an HTML sign-in/protection page with HTTP 200, then return malformed

JSON with a JSON content type. The mobile transport must reject both as a retryable connection failure, keep the response body out of diagnostics, and use the bounded Home data fallback instead of mapping either response.

Expected: changing the period updates every compatible card, each row opens the matching live record, empty sections show the correct state, and no role sees organization-wide or private pay data outside its permission scope. A partial successful activity response must never open a red error screen or crash while reading the account or workspace name. A non-JSON or malformed 2xx response is not a successful API payload, even if the hosting layer reports HTTP 200. Appointment cohorts must follow the scheduled appointment date in the organization's timezone and deduplicate only a truly matching linked lead/estimate appointment.

Run the owner and manager cases against the same QA records, including records assigned to another representative and another crew. Both roles must see those organization records on Home. Then test a crew lead and technician with each combination of organization performance pay on/off and membership pay model commission/hourly. My Pay must appear only for the on + commission combination, and its direct route must fail closed for every other combination. On the manager pipeline, disable Red Line in the active pricing configuration and verify the commission metric and note disappear; restore it and verify the authorized server-calculated total returns.

CAM-02 Canvass workspace from More

Run as owner, manager, and sales representative:

  1. Open the overview with and without an active territory assignment.
  2. As an owner or manager, open Campaigns from both the header and active-

campaign panel. Create one QA draft and one active QA campaign, edit every field, select start and end dates, and exercise every allowed lifecycle action. Confirm a representative cannot open the manager workspace.

  1. Return to the team map, select the newly created active campaign, and draw

its first territory. Enter a unique QA name, select only QA-authorized reps, add at least three points, test Undo and Clear, and save. Confirm the campaign is selectable before it has any existing territory and the saved territory immediately shows the correct assigned reps.

  1. Create an unassigned QA territory through an approved fixture or API and

confirm the manager map still lists it with zero assigned reps. Simulate an initial assignment failure and confirm no orphan boundary remains.

  1. Select a populated manager territory. Confirm its house markers and total,

knocked, not-hit, and do-not-knock counts load. Open a knocked house from both its marker and activity row, verify prior attempt history, record a QA-safe disposition, refresh, and confirm the marker, counts, and current status persist. Confirm the manager can save this disposition without manually starting a canvassing shift. Confirm the manager map starts in satellite view and its visible Map / Satellite control switches both directions.

  1. In an approved QA territory, tap an empty deliverable address point, add

the missing house, and confirm its compact disposition control opens. Verify an outside-boundary or duplicate point is rejected.

  1. Select Edit boundary, clear the QA polygon, and trace a non-rectangular

replacement with one finger drag. Save it and confirm the revised polygon persists while assigned reps, houses, counts, and knock history remain.

  1. Start, resume, interrupt, and end a shift.
  2. Open the field map and switch between map and list.
  3. Search addresses and apply every available filter.
  4. Tap an assigned target. Swipe the compact outcomes and tap each

no-contact result once. Confirm it saves without a second confirmation and advances to the next eligible target.

  1. Select Conversation / details, record each contact disposition, and

complete required contact, notes, follow-up, and appointment fields. Open Services discussed, select and deselect multiple service chips, save, and confirm the exact selections prefill the estimate handoff. Confirm the action dock remains above the device navigation area.

  1. For Interested and Appointment Set, confirm Door Knocking and

the signed-in rep are applied automatically. Test both Save + lead and Save + quote, confirming the latter opens the native residential builder with the saved client, lead, address, and visit attribution. Repeat both handoffs from the manager team map: Save + lead must open the native lead and Save + quote must open the native residential builder rather than stopping at a saved-status alert.

  1. Confirm the rep map opens in satellite view and the layers control switches

between satellite and standard maps without changing the selected territory or visible door status.

  1. Select Quote Sent and Sold. Confirm both require a permanently

labeled customer name field, create or match the Door Knocking lead, and that Save + lead opens the saved native lead page. Confirm phone and email remain visibly labeled before, during, and after entry.

  1. Lose connectivity mid-shift, queue a disposition, reconnect, and verify

one successful sync.

  1. Background and resume while location tracking is active.

Expected: tenant and assignment rules fail closed, GPS state is explicit, offline work is not duplicated, and another representative's private territory data never appears. Campaign edits stay inside the app, lifecycle errors explain active-shift or incomplete-territory blockers, and campaign dates save exactly as selected.

TAB-02 Schedule and route

Test day and week view with no items, one item, and multiple items:

  • Purple leads, blue jobs, yellow follow-ups, and orange high-priority

follow-ups.

  • Truck, technician/salesperson, record-type, day/week, and date filters.
  • Owner and manager all-work and daily-revenue view versus assigned-by-default

sales and field views.

  • Route order, appointment windows, travel links, and completed-state styling.
  • Lead, estimate, job, task, and event cards.
  • Call, message, directions, and open-record actions.
  • Pull to refresh, stale-data recovery, and offline display.
  • Date changes around midnight and the device time-zone boundary.

Expected: cards open the correct record, date-only appointments stay on their saved calendar day, truck/crew assignments resolve correctly, and Schedule never exposes work outside the signed-in role's scope.

Seed one item assigned to another sales rep and one job assigned to another crew. Confirm both are present for owner and manager roles, and absent for a sales rep, crew lead, or technician who is not assigned to them.

MORE-PIPE-01 Pipeline from More

Test every stage, filter, search mode, deal card, detail sheet, and empty state. Move only QA records between stages, reopen the record from its destination stage, and confirm the desktop pipeline reflects the same state.

Seed deals with at least three exact job types, two salespeople plus an unassigned deal, customer tags with overlap, and activity ages in the 0–7, 8–30, and 31+ day ranges. Include enough deal cards to require vertical scrolling. Verify:

  1. At the top of Pipeline, the controls, filters, metrics, stage rail, and deal

cards appear in their expected order.

  1. Scrolling down moves the controls, filters, metrics, and stage rail away

with the deal cards instead of leaving a permanently fixed Pipeline block. The normal app header and bottom navigation remain visible and usable.

  1. Scrolling back to the top restores access to the Pipeline controls without

changing the selected stage or filter state, and the stage rail still scrolls horizontally.

  1. The filter sheet opens with every compact dropdown collapsed and each row

shows the correct selected-value summary.

  1. Tapping a dropdown expands only that filter's choices. Opening another

dropdown collapses the first so no more than one choice list is visible.

  1. Select values, collapse and reopen their dropdown, then switch between

dropdowns. Every selection and summary persists until it is cleared.

  1. Multiple selections inside Job type, Salesperson, and Customer tags match

any selected choice.

  1. Job type, salesperson, age, tags, period, service line, and quick filters

combine with one another.

  1. Customer tags match any selected tag and use the same shared CRM labels.
  2. Sales representatives do not receive the salesperson section and still see

only their authorized records.

  1. Counts, value, follow-up metric, cards, and the no-results state all reflect

the visible filtered deals.

  1. Clear all removes job type, salesperson, age, and tag selections

without changing the period, service-line, quick filter, organization, or role scope.

Expected: one gesture produces one transition, counts refresh without duplicating deals, long service addresses may use two compact lines so city and state stay visible, and role/org scoping remains intact.

SECONDARY-01 CRM work surfaces

Owner, manager, and sales representative

Test these lanes:

  • Jobs & route
  • Estimates & proposals
  • New estimate
  • Search by name, phone, source, and address
  • All, Leads, Customers, and Follow-up filters
  • New lead, New customer, and New estimate chips
  • Pull to refresh
  • Partial-load warning
  • Empty results
  • Lead and customer rows
  • Recently active, Last contacted, and Name A-Z sorts

Expected: merged CRM rows are deduplicated, the selected sort is honored, filters combine with search, lead rows show an explicit Lead # plus the full address before appointment timing, and opening a row lands on the correct record.

Crew lead and technician

Expected:

  • Work shows Assigned jobs, Photos and issues, and the crew empty-state explanation.
  • The CRM lead/customer list does not load or appear.
  • The plus button opens Jobs.
  • No customer, lead, or estimate-creation modal is exposed from Work.

If the page promises photos, issues, notes, or completion but the released Job detail does not provide those controls, record a product-consistency defect against the release requirement.

SECONDARY-02 Estimate and record launchers

Sales-capable roles

Open every action:

  • Residential quote
  • Commercial
  • Fleet wash
  • Holiday Lights
  • All estimate types
  • New lead
  • New customer
  • Add job photo
  • Report issue
  • Search before creating

Expected: quote actions open the correct builder. New customer routes to the created customer. New lead routes to the created lead. Add job photo and Report issue open Jobs.

Crew lead and technician

Expected: estimate types are hidden; only field actions and Open jobs are shown.

Launcher promise check

The current launcher copy describes job photos, issues, notes, payments, and completion. The current Job detail route provides job/schedule/invoice review and supported payment collection, but no native status, photo, issue, note, signoff, or completion controls. Compare the installed build with the release requirement and file FAIL when copy promises an unavailable action.

TAB-04 Inbox

  1. Open the filter sheet and verify the approved Reply status,

Assignment, Channel, Engagement, Last outbound, and Priority groups. Combine choices from several groups and confirm the filter-button badge counts every active constraint.

  1. Change the draft and confirm the list does not change before **Apply

filters. Verify Reset clears every group. Enable Save as a view**, enter a name, apply it, and confirm the name remains in the current Inbox screen state without appearing as an organization-wide synced view.

  1. Verify Assigned to me uses the signed-in user's stored assignment;

channel and engagement filters exclude records missing that metadata; Viewed multiple times requires a recorded estimate view count above one; and Human/Automation excludes an unknown last-outbound kind.

  1. Confirm calls, voicemail, texts, emails, and estimate views for the same

matched client appear in one bordered customer card with the latest event, timestamp, and total activity count. At the default text size, confirm about six customer rows fit on a standard phone-height viewport and every row shows a useful one-line message or activity preview. Confirm approvals stay in separate System cards.

  1. Open read, unread, needs-reply, phone-only, and email-only threads.
  2. Tap a linked customer name and confirm the correct CRM profile opens. Test

a phone-only contact without a client link and confirm it still opens the conversation safely.

  1. Test loading, empty, error, and Try again states.
  2. Confirm needs-reply, unread, call, and reply actions stay attached to the

correct card and cannot be mistaken for the row above or below.

  1. Open the call sheet from Inbox at normal and large text sizes. Confirm it

opens without starting a call, scrolls when needed, and keeps both calling actions above Android system navigation. Confirm the blue Call in Clean Estimate surface and its white label are both clearly visible.

  1. Verify role and organization scoping.
  2. Open a conversation that only needs a response and confirm its header says

Needs reply, not Hot lead. Then verify Hot lead appears for a lead created within 24 hours, an estimate viewed within 24 hours, and repeated estimate/proposal views.

  1. Confirm the opened thread keeps the six-tab bottom bar with Inbox

selected. Test every tab destination, then return to the same conversation.

  1. Confirm the Today divider is visible and that every system activity row

uses the same horizontal alignment. Customer and team messages must retain their correct left/right alignment.

  1. Open the external reply selector and test Text and Email with valid

contact details. Select Internal note, verify the target says Team only, save a note, and confirm it appears in the timeline without sending an external message.

  1. Confirm paperclip and camera controls are visible. Selecting either must

show the unavailable explanation and must not claim or attempt a media upload from the conversation.

  1. Create two QA clients with the same reserved phone number or test email but

different names and client IDs. Give each client a distinct timeline event. Open the first card and confirm its header, profile link, bubbles, internal events, and composer remain on the first client without showing the second client's activity. Repeat from the second card.

  1. Save an Internal note for each shared-contact client and confirm the new

row appears only in the selected client's timeline. When external delivery is in scope, send only to the approved QA destination and confirm Inbox accepts the send only after the server validates the open client and contact together. A mismatched request must be rejected and must not appear as a successful send in the selected thread.

Expected: only allowed conversations appear. Filters update without stale rows from another query, each customer appears once, profile and conversation taps open the intended record, one row's actions never open another customer, and shared contact details never merge client identities, timelines, or new sends.

TAB-05 Phone

Run as owner, manager, and sales representative:

  1. Confirm the header shows the correct company number and in-app or secure

callback registration state.

  1. Confirm Quick dial stays compact, then enter an approved QA number and

place one company-line call.

  1. Test empty, invalid, formatted, pasted, and international phone input.
  2. Confirm calls today, missed, voicemail, and talk-time metrics match the

visible call history.

  1. Test All, Inbound, Outbound, Missed, and Voicemail

filters.

  1. Confirm each activity card clearly separates customer, number, timestamp,

direction, status, duration, representative, and voicemail preview.

  1. Tap an approved QA call card and confirm it opens Call intelligence

without also starting a call or opening Messages.

  1. Select Call back and Text on an approved QA contact and confirm those

actions do not also open call detail.

  1. Pull to refresh, background/return, switch workspaces, lose connectivity,

and retry an API error.

  1. Verify sales representatives see only their calls while authorized owners

and managers can see team activity.

  1. Sign in as crew lead and technician with default permissions. Confirm the

stable Phone tab shows Phone access is turned off, does not request the call-history or call-detail endpoints, and does not request an Android voice token in the background.

  1. Grant View Phone Activity without Place Phone Calls. Confirm permitted

activity and call detail load, while Quick dial and every callback action are absent and neither callback nor token APIs are requested.

  1. Grant both phone permissions. Confirm the full dialer and callbacks appear

without changing tab order. Remove each permission again while signed in, reload, and confirm the app fails closed using the saved override.

  1. With workspace recording enabled, complete one approved outbound in-app

call and one approved inbound call. Confirm the recording disclosure plays, the recording callback arrives, and transcript/coaching/tasks populate after background processing. Repeat with recording disabled and confirm no disclosure, recording, transcript, or invented coaching is created.

  1. Confirm the active filter and primary phone actions use blue, the four

daily totals share one divided card, and answered, missed, and voicemail activity use uniform white bordered rows.

  1. Verify a score badge appears only for a real call score. Missed calls and

voicemail must say Call Back; other callable activity must say Call.

Expected: Quick dial uses the company line, callbacks and text handoffs keep the selected contact, card taps open the selected call, filters and totals remain organization-scoped, and no unauthorized call activity, detail, token, or outbound-call request occurs.

PHONE-01 Call intelligence detail

Use only calls involving an approved QA contact. Prepare at least one connected call with a transcript and completed AI review, one voicemail transcript, and one call with neither review nor transcript.

  1. Open a reviewed call from TAB-05 Phone.
  2. Confirm customer/number, direction, result, date, duration, and

representative match the selected activity card and durable web call record.

  1. Verify the overall score, sentiment, outcome, summary, every scorecard

category, strength, coaching opportunity, and manager score/note.

  1. Verify each recommended next step. Compare the follow-up draft with the web

call detail, and confirm viewing it does not send a customer message.

  1. Verify every Created from this call task has the correct text, due time,

open state, and assignee.

  1. Verify Related open tasks contains pending work for the same client or

lead, deduplicates a task linked through both, and excludes completed work.

  1. Verify every transcript line is separate and labels the representative and

customer correctly. Test a long transcript, long names, and large display text without merged or clipped lines.

  1. Open a voicemail and confirm the heading says Voicemail transcript and

no sales score is invented.

  1. Open the empty-state call and confirm No coaching review yet and

Transcript unavailable are clear and do not block call facts, callback, text, or back navigation.

  1. Test loading, 404/no-access, offline, server error, Try again,

background/return, pull-to-refresh on the activity page, and device back.

  1. As an owner or authorized manager, open an allowed team call. As a sales

representative, attempt the same direct detail URL for another rep and confirm it fails closed. Confirm the rep sees only related tasks assigned to that rep.

  1. Inspect the mobile response and device logs. Confirm there is no provider

recording URL, Twilio credential, callback number, raw metadata object, token, or unrelated customer data.

Expected: the selected call opens one readable, permission-scoped source of truth for transcript, coaching, next steps, and associated work. Empty states are honest, actions keep the selected contact, and direct URLs cannot bypass role or organization isolation.

MSG-01 Message thread

Test:

  • Customer name and best available contact fallback.
  • Customer-name profile links from both the Inbox card and opened thread

header; each must open the matched CRM client and never another contact.

  • US phone formatting as XXX-XXX-XXXX in the thread header, composer target,

call sheet, Inbox fallback names, Phone activity, and call detail.

  • Inbound and outbound timeline alignment.
  • SMS and communication-event labels.
  • Chronological order.
  • Linked estimate cards.
  • Call quick action when a phone exists.
  • Call-sheet actions remain comfortably above three-button and gesture Android

system navigation and are fully tappable at maximum display/font scaling.

  • No-phone state.
  • Live-thread error with fallback context.
  • Empty history.
  • Search shortcut and back navigation.
  • First-load layout at cold-cache and warm-cache speeds. The filter strip must

stay compact while the timeline loads; it must not stretch, jump, or require a second refresh to reach the finished layout.

  • Long histories open directly on the newest item without visibly scrolling

from the oldest item after the screen paints.

Expected: internal event history and SMS are readable, linked estimates open, and no other customer's data appears.

TAB-03 Create

  1. Confirm the blue center Create tab is visible in the same position for

owner, manager, sales, crew lead, and technician accounts.

  1. With effective Client/Lead create permissions enabled, create a disposable

QA client and lead; confirm each opens the saved profile once. Remove the required permission overrides and confirm both launchers disable without a write request.

  1. Open Estimate and confirm the type cards have visible surfaces, padding,

accent rails, readable copy, and no left-edge clipping.

  1. Select Job, open an accepted QA estimate, and schedule it as work.
  2. Select Invoice, open an eligible QA job, and create its invoice.
  3. Select Task / Event. Exercise Call, Email, Meeting, Deadline, and Todo;

low, medium, and high priority; self and teammate assignment; customer association; due date/time; notes; validation; and retry after a connection failure.

  1. Confirm the saved task appears once on the assigned teammate's agenda.
  2. Confirm every launcher follows the effective capability returned by the

backend, not just the membership role. In particular, grant a technician only the task-create permission tuple and confirm Task / Event enables while Client, Lead, Estimate, Job, and Invoice remain disabled.

  1. Simulate a failed access check. Confirm every launcher fails closed with an

Access unavailable state and Quick Add does not advertise an action.

Expected: every allowed create action starts the correct durable workflow without duplicate records, cross-workspace data, or hidden form controls.

Company-line and device calling

Run from the Phone tab, customer, lead, proposal, and message thread.

Record the signed artifact, native build number, app version, runtime, and backend before this suite. Direct in-app audio requires the signed Android 1.1.2 (or newer) build; it is not valid to test this path in Expo Go or an older binary with a newer OTA bundle.

Native Android outbound

  1. Sign in as an active owner, manager, or user whose effective permissions

include Make calls.

  1. Open Call and confirm the displayed target is an approved QA number.
  2. Allow microphone access and select Call in Clean Estimate once.
  3. Verify the customer QA phone rings once without first calling the rep's

personal phone.

  1. Confirm caller ID is the workspace Twilio number.
  2. Confirm the overlay moves through connecting/ringing/connected, two-way

audio works, mute/unmute changes audio, and End disconnects both sides.

  1. Background and reopen the app during the connected call. Verify audio

continues and the active call is restored.

  1. Confirm the call appears once in the correct customer/lead/estimate history

with the correct direction and duration.

  1. Repeat with Use Device Dialer Instead and verify the distinction is

explicit. Do not complete the call unless the personal-line test is in scope.

  1. Deny microphone, revoke permission after a successful call, remove the

phone number, expire the session, disable voice, and simulate a provider error. Verify a clear recovery path and no duplicate call.

Expected: one tap creates one Twilio attempt to one approved QA number, the customer sees the company caller ID, audio stays inside Clean Estimate, and the selected record receives one call activity.

Secure callback fallback and web

  1. Use mobile web, normal web, or an Android build whose native registration is

deliberately unavailable.

  1. Start Call From Company Line.
  2. Verify the representative profile phone rings first. If no profile phone is

saved, verify the workspace forwarding number rings.

  1. Answer and confirm the approved QA customer rings second from the company

number.

  1. Decline or ignore the first leg and verify the customer is never called.

Expected: browser surfaces and unavailable native registration use the secure callback, while the signed registered Android build uses direct in-app audio.

Native Android inbound

Run the foreground, background, locked-screen, and terminated-app cases on a physical Android phone with Google Play services. An emulator is useful for UI and registration checks but is not the sole proof of production FCM delivery.

  1. Install 1.1.2 or newer, sign in once with an authorized office account, and

allow notifications.

  1. Call the workspace Twilio number from an approved QA phone.
  2. Verify all currently registered authorized Android office devices ring,

display the QA caller number, and show Answer and Decline. If the workspace has more than ten call-capable memberships, verify the ten most recently registered authorized devices are selected ahead of inactive or never-registered memberships.

  1. Answer on one device. Confirm the other devices stop ringing and two-way

audio works.

  1. Test mute/unmute, background/return, and End.
  2. Confirm the inbound call appears once in the correct customer history. An

unknown approved QA number must remain safely unlinked rather than attaching to another customer.

  1. Repeat while the app is backgrounded, the screen is locked, and the app has

been swiped away from Recents. Verify the Android call notification opens the incoming controls.

  1. Decline on all devices, then repeat with no answer. After the 18-second app

ring window, confirm the saved office forwarding number rings.

  1. Ignore the forwarding leg and confirm the caller reaches the configured

Clean Estimate voicemail.

  1. Test an offline authorized device, notification denied, an archived member,

and a role without Make calls. None may take the company line down or expose another organization's call.

  1. Leave an authorized device signed in for more than one hour and repeat the

inbound test to prove registration refresh.

  1. Separately use Android Settings to explicitly Force stop the app. Android

suppresses push delivery to a force-stopped package until the user opens it again, so verify forwarding and voicemail still receive the call. Reopen Clean Estimate and confirm subsequent app calls arrive again.

Expected: authorized app users get the first opportunity to answer; first answer wins; no answer falls back to office forwarding and voicemail; role, organization, and QA-contact boundaries remain enforced.

  1. Open Search from Home, Schedule, Create, sales and technician

Inbox, Phone, and More. Confirm each shortcut reaches the same Global Search screen.

  1. Test zero and one character.
  2. Test person name, company name, email, phone, address line 1, address line

2/unit, city, state, ZIP, estimate number, and job number. Confirm company results show the contact identity and complete address when available.

  1. As owner/manager/sales, test All, CRM, Leads, Estimates, and Jobs. Confirm

there is no Messages filter until conversation search is implemented.

  1. Open a client, lead, estimate, and job result.
  2. Test no matches, slow loading, special characters, and a very long query.
  3. Test role and organization scoping. Crew lead and technician defaults must

show only the Jobs filter and only assigned user/crew/truck jobs.

  1. Remove all searchable permissions and confirm a permission-unavailable

state. Fail the access request separately and confirm an error state rather than No matches.

  1. In More, confirm Search records opens Global Search while **Filter tools

and settings** still narrows only the local destination catalog.

Expected: searching starts at two characters, filters reflect the effective backend permission matrix, result type routes correctly, and unauthorized or unimplemented record types never appear.

CRM record creation and detail

Shared date and time controls

Exercise every editable date/time surface in New Lead, Edit/Schedule Lead, Canvass disposition follow-up and appointment, proposal Schedule next action, Job Reschedule, and Invoice Edit:

  1. Tap the date field and verify a calendar opens at the selected month.
  2. Move to the previous and next month, select a day, reopen the calendar, and

confirm the same day is selected.

  1. Confirm today and unavailable past days are visually distinct where the

workflow disallows past scheduling.

  1. Tap a time field, select morning, noon, and evening values in 15-minute

increments, and verify the field displays a readable AM/PM value.

  1. Save and reopen the record. Confirm the selected date and time persist

without timezone or one-day shifts.

  1. Verify Clear appears only on optional values, required dates cannot be

cleared, Android Back closes the picker before leaving the record, and all controls remain above system navigation on the smallest supported phone.

Expected: no mobile workflow asks the user to type YYYY-MM-DD, HH:MM, or an ISO timestamp manually. The same calendar and time behavior is available on Android, iOS, and the mobile-web rendering of the app.

CRM-00 Clients & Leads list

Open More > Clients & Leads. Verify:

  • Combined All, Customers, and Leads filters
  • Search by person, company, email, phone, lead number, and address
  • Customer and lead row labels, contact fallback, status, source, and value
  • New lead, new customer, and new estimate actions
  • Pull to refresh, loading, empty, no-results, error, and retry states
  • Opening each row type and returning without losing the query/filter
  • Organization and assigned-record boundaries for every staff role

On the separate Leads page, seed at least 151 records so a known matching lead falls outside the first 150 records by latest activity. Verify:

  • Searching for that older person's name or lead number still returns the

record, together with any newer legitimate matches.

  • An older sold or tagged lead remains searchable; do not reimport it,

duplicate it, or change updated_at to make the test pass.

  • Job type, salesperson (including Unassigned), last-activity age, and

shared customer-tag filters work individually and in combination with search and the existing lead status controls.

  • The filter sheet starts with every compact dropdown collapsed and its

selected-value summary visible. Opening one dropdown shows only its choices and collapses any other open dropdown. Selections persist after collapsing, reopening, and switching between dropdowns.

  • Multiple job types, salespeople, and tags match any selected choice; filter

sections combine; the active count is correct; Clear all removes those advanced selections while the current search and lead-status filter remain.

  • A sales representative remains self-scoped and does not receive the

salesperson filter.

Expected: every record is created once, appears in the correct filter, opens the correct detail route, and never leaks another organization's data.

New customer modal

Test:

  • First name, last name, company name
  • Email and phone
  • Address autocomplete and manual street/city/state/ZIP
  • Person-name only
  • Company-name only
  • No name
  • Invalid email
  • Optional blank contact fields
  • Save once and rapid double-tap
  • Close clean form
  • Keep editing and Discard on a dirty form
  • Edit an existing customer

Expected: a person or company name is required, invalid email is blocked, address selection fills components, and one save creates one record.

New lead modal

Test:

  • Search existing customers by name and select one
  • Verify selected customer contact and property fields prefill
  • Clear/change the selected customer
  • Create a new customer and lead together when no match exists
  • Required customer name
  • Email and phone
  • Fast service-address autocomplete, compact formatting, repeated-query cache,

component fill, and manual address

  • Managed lead-source dropdown and inline Add new source
  • Assigned and unassigned ownership
  • Scheduled and unscheduled creation
  • Calendar-selected appointment date, 15-minute start/end time choices, and

appointment notes

  • Multiline notes
  • Invalid email
  • No name
  • Dirty-form Keep editing and Discard
  • Save and duplicate-submit prevention

Expected: every lead is linked to exactly one authorized workspace customer, the created lead opens its detail page, and it remains searchable without creating a duplicate customer.

CRM-01 Lead detail

Verify:

  • Lead number, status, source, service address
  • Appointment date/time or Not scheduled
  • Green CONFIRMED indicator on the Clients lead row and lead detail after

link or SMS confirmation

  • Reschedule a confirmed lead and verify the old indicator disappears
  • Edit lead, Schedule/Reschedule, and Assign
  • Save an unscheduled lead, then schedule and assign it after creation
  • Schedule a QA lead whose existing source is no longer active; confirm the

source remains readable and the unchanged historical value does not block the update

  • Change source, property, appointment notes, and lead notes
  • Open the linked customer profile
  • Deposit amount
  • Call and message availability
  • New estimate with lead/customer prefill
  • Deposit/payment card when applicable
  • Conversation preview
  • Linked estimate history
  • Lead notes
  • Search and back navigation
  • Loading and unavailable states

CRM-02 Customer detail

Verify:

  • Customer identity and address
  • Contact fallback
  • Lifetime value
  • Last activity
  • Call, message, and schedule quick actions
  • Edit customer
  • New estimate with full customer prefill
  • Payment-due card
  • Message preview and full history
  • Estimate history
  • Lead, job, and invoice history
  • Timeline
  • Live-history reconnect fallback

Expected: edits update the same record, new estimates retain customer linkage, and all totals match the web dashboard.

Open an estimate from customer, lead, job, and invoice history. In each case, verify the estimate Back action returns to the originating record and the estimate Customer action opens the linked CRM profile.

CRM-03 Business account detail

Open a customer linked to a business account, then open the account. Verify company identity, billing/contact data, W-9 state, payment terms, all linked contacts, call/email actions, new-estimate prefill, loading/error states, and back navigation. Confirm a contact from another organization cannot be opened by changing the route ID.

BRIEF-01 Pre-knock brief

Open the brief from a scheduled lead. Verify appointment/customer context, address, notes, prior communication, linked estimate/payment context, directions, company-line call, message, new-estimate, full-lead, loading, unavailable, and back paths. I'm at the door must open the native residential builder directly with the lead, customer, and address attached. Sparse lead data must show honest empty states without crashing.

EST-01 Estimates list

Test:

  • Centered Estimates header, open-count subtitle, Back, and Add
  • Search by estimate, customer, and full service address
  • All, Draft, Sent, Viewed, Approved, Declined, and Expired
  • Recently viewed, Recently updated, Highest total, and Client name sorting
  • Compact status band with estimate number, type, and total
  • Customer and complete street/city/state/ZIP in the card body
  • Latest activity, assigned representative, and contextual action in the footer
  • Local and remote rows
  • Local-draft resume
  • Remote proposal detail
  • Realtime status update after customer view, signature, and payment
  • Empty result
  • Add and Search shortcuts

Expected: local drafts say On device, accepted estimates appear as Approved, recently viewed records sort by the persisted view timestamp with unviewed records following them, and one record does not appear twice. Create a new residential draft and confirm the estimate number shown on Review is identical in the Save as Draft confirmation and the Estimates list.

EST-02 Estimate-type picker

Open every module:

  • Residential
  • Holiday Lights
  • Fleet Wash
  • Commercial
  • Generic Quote
  • Asphalt Maintenance

Expected: customer/lead prefill survives through every applicable native builder. Generic Quote and Asphalt Maintenance both stay inside the app.

Shared native-builder behavior

Run these checks in every native builder:

  • Step title, current-step indicator, and all step labels.
  • Back and Next.
  • Android back gesture/button.
  • Sticky footer with keyboard open.
  • Subtotal, annual total where applicable, and margin.
  • Autosave indicator.
  • Background and foreground mid-step.
  • Force-stop and draft resume.
  • Orientation if supported.
  • Small-screen scrolling.
  • Rapid Next taps.
  • Invalid direct step URL.
  • Stack two valid direct residential step links without clearing app state,

then confirm only the visible route controls the active step and the app does not show Something went wrong or a maximum-update-depth error.

  • Network loss and reconnect.

Expected: no step loses prior data, no footer covers the final field, totals recalculate once, and resuming opens the saved review step with the correct module data.

Shared signed-runner device gate

The signed core-surfaces, CRM/operations, billing/delivery, and estimate-builder runners all require an explicit -DeviceSerial. Before checking app identity, each runner verifies that ADB can reach the selected device, Android has completed boot, and the target is physical hardware. An emulator identified by its serial or Android's QEMU property is rejected unless -AllowEmulator is supplied explicitly.

All four runner families use the same per-device exclusive lock under mobile/.maestro-results/.signed-device-locks/. The serial is sanitized into the lock filename, so two different signed suites cannot drive the same phone at the same time, while independent devices can run in parallel. If another signed suite owns that device, stop and wait for it to finish; do not remove an active lock or run a second tool against the phone.

-AllowEmulator is only a navigation, selector, and release-identity preflight. It never replaces the signed physical-device pass or certifies hardware, permissions, provider handoffs, connectivity transitions, or background behavior.

Signed core-surfaces runner

Use the release-agnostic core-surfaces runner to smoke-test the installed Home, Schedule, Inbox, Phone, and Create workspaces without creating records, sending messages, or placing calls. The expected release identity is supplied for each run instead of being pinned in the script. From the mobile project directory, connect a physical Android device and run:

.\scripts\run-signed-core-surfaces.ps1 `
  -ExpectedAppVersion 1.1.4 `
  -ExpectedBuildNumber 63 `
  -ExpectedUpdateId 019fc83e `
  -DeviceSerial <physical-device-serial>

Replace the example identity with the exact installed release. Before opening the five surfaces, the runner verifies all of the following:

  • Android versionName exactly matches -ExpectedAppVersion.
  • Android versionCode exactly matches -ExpectedBuildNumber, and the package

is not debuggable.

  • More > About shows the exact native version and build, eight-character

Expo OTA update ID, channel, and runtime supplied to the runner.

  • About reports Expo update as the source. An embedded launch or mismatched

OTA fails the gate.

-ExpectedChannel defaults to production, and -ExpectedRuntimeVersion defaults to the app version; pass them explicitly when a release uses different values. The read-only flows then verify:

  • Home period controls, Agenda, and Hot Follow-Ups;
  • Schedule Day and Week views, month picker, and filters;
  • Inbox list actions and opening one conversation without replying;
  • Phone quick-dial and recent-activity presentation without placing a call;
  • Create availability and prerequisite copy without creating a record.

The runner saves the About identity screenshot plus per-flow screenshots, JUnit XML, and command logs beneath mobile/.maestro-results/signed-core-surfaces/<release>/<timestamp>/. A flow fails if its assertions fail or it produces no screenshot evidence.

Physical hardware is the default gate. An emulator-* serial is rejected unless -AllowEmulator is supplied explicitly:

.\scripts\run-signed-core-surfaces.ps1 `
  -ExpectedAppVersion 1.1.4 `
  -ExpectedBuildNumber 63 `
  -ExpectedUpdateId 019fc83e `
  -DeviceSerial emulator-5554 `
  -AllowEmulator

Use that override only for an early UI and release-identity preflight. An emulator pass does not replace signed physical-device certification and does not prove hardware-dependent behavior such as calling, notifications, camera, audio, background execution, or real-device permissions.

Signed CRM and operations runner

Use the separate CRM/operations runner to verify populated customer, sales, and job workspaces without editing a record or triggering a customer-facing action. Supply the identity of the release installed on the device:

.\scripts\run-signed-crm-operations.ps1 `
  -ExpectedAppVersion 1.1.4 `
  -ExpectedBuildNumber 63 `
  -ExpectedUpdateId 019fc83e `
  -DeviceSerial <physical-device-serial>

The values are inputs, not a release pinned in the script. Before running the record flows, the gate verifies the exact Android version and build, rejects a debuggable package, and checks More > About for the exact eight-character Expo OTA update ID, channel, runtime, and Expo update source. The channel defaults to production, and the runtime defaults to the app version; use -ExpectedChannel and -ExpectedRuntimeVersion when the installed release differs.

The isolated read-only flows cover:

  • the populated Clients list and an individual client detail;
  • the Leads list, an individual lead detail, and Pipeline;
  • the Jobs list and an individual job detail;
  • the existing QA-MULTI-TRUCK job, including pinned SALES NOTES, all four

truck assignments, crew resources, and independent truck progress.

These flows navigate, search, open, scroll, assert, and capture evidence only. They do not call or text customers, change pipeline or job state, start or complete truck work, create invoices, collect payments, or edit sales notes. Each flow receives its own JUnit XML, command log, and screenshots under mobile/.maestro-results/signed-crm-operations/<release>/<timestamp>/; the About identity screenshot is stored with the same run. The runner stops on the first failure and also fails a flow that produces no screenshot evidence.

A physical Android serial is required by default. -AllowEmulator may be added explicitly with an emulator-* serial for an early navigation, selector, and release-identity preflight. That override does not replace the signed physical device pass and does not certify real-device permissions, calling, messaging, GPS, camera, background behavior, or other hardware-dependent behavior.

Signed billing and delivery runner

Use the separate billing/delivery runner to inspect invoice, payment, delivery, and connectivity surfaces without sending an invoice or message, placing a call, opening the payment provider, or recording a payment. Supply the exact identity of the signed Android release installed on the device:

.\scripts\run-signed-billing-delivery.ps1 `
  -ExpectedAppVersion 1.1.4 `
  -ExpectedBuildNumber 63 `
  -ExpectedUpdateId 019fc83e `
  -DeviceSerial <physical-device-serial>

Replace the example values for every release. Before any billing flow runs, the gate checks the exact Android versionName and versionCode, rejects a debuggable package, and verifies More > About shows the supplied native version/build, exact eight-character Expo update ID, channel, runtime, and Expo update source. -ExpectedChannel defaults to production, while -ExpectedRuntimeVersion defaults to the app version. An embedded launch or any identity mismatch fails the gate.

The runner executes these read-only flows in order and stops on the first failure:

  1. Inspect the Invoices list, Unsent filter, invoice detail metadata,

payment entry point, and collapsed supporting sections.

  1. Open payment choices and verify Card, ACH, Check, and the expanded Other

methods, then inspect configured tip choices including zero tip.

  1. Follow Card through the native hosted-checkout handoff, stopping before

Open secure card checkout opens the provider URL.

  1. Inspect the provider-backed QA conversation history without sending,

calling, replying, or editing.

  1. Enable airplane mode, cold-start the retained session, and inspect saved

offline data, sync queues, and sync controls.

  1. Disable airplane mode immediately afterward and verify the retained session

returns to Online sync ready without signing in again.

The flows navigate and assert only. They do not send invoices, email, or SMS; place calls; submit or record payments; open hosted checkout; alter invoice or conversation data; or deliberately enqueue new offline work. Use an approved QA account with a collectible QA invoice and the seeded provider-inspection conversation.

The About screenshot, per-flow screenshots, JUnit XML, and command logs are stored under mobile/.maestro-results/signed-billing-delivery/<release>/<timestamp>/. A flow also fails when it produces no screenshot evidence.

Physical Android hardware is required by default. Pass -AllowEmulator explicitly with an emulator serial only for early navigation, selector, offline-transition, and release-identity preflight. Emulator evidence does not replace the signed physical-device pass or certify real-device permissions, provider handoff, connectivity, background behavior, or other hardware-dependent behavior.

Signed disposable job-lifecycle runner

Use the controlled lifecycle runner only with a newly seeded, one-time QA fixture. This is an intentionally mutating gate: it starts and completes two truck runs and creates one draft invoice. It must never target an existing customer, reusable demo record, or ordinary QA-MULTI-TRUCK read-only fixture.

Before running, prepare one accepted estimate and its linked job with all of these properties:

  • the estimate and job show the same unique customer name in the form

QA-LIFECYCLE-<run-id>;

  • both record IDs are known UUIDs and belong to the approved QA organization;
  • the customer has no email address or phone number, so lifecycle automation

cannot contact a person;

  • the job has no invoice, exactly two distinct QA--prefixed executable truck

runs assigned to the signed-in QA user, and both runs begin scheduled;

  • each run already has one synthetic before photo and one synthetic after photo;
  • the job contains exactly one QA--prefixed service line item, in addition to

the standard generated checklist steps; and

  • the signed-in account may view estimates/jobs, execute both truck runs, and

create invoices.

The fixture is consumed by one successful run and must not be reused. From the mobile project directory, run:

.\scripts\run-signed-job-lifecycle.ps1 `
  -ExpectedAppVersion 1.1.4 `
  -ExpectedBuildNumber 63 `
  -ExpectedUpdateId 019fc83e `
  -DeviceSerial <physical-device-serial> `
  -FixtureMarker QA-LIFECYCLE-20260803-A1 `
  -AcceptedEstimateId <accepted-estimate-uuid> `
  -JobId <job-uuid> `
  -TruckOneName "QA Truck A1" `
  -TruckTwoName "QA Truck A2" `
  -ServiceLabel "QA Lifecycle Service" `
  -ConfirmDisposableFixture

The runner validates the exact non-debuggable native version/build and the eight-character Expo update ID, channel, runtime, and Expo update source. It is physical-device first, uses the shared per-device signed-runner lock, and refuses malformed UUIDs, non-QA labels, a missing confirmation switch, or a screen that does not expose the exact disposable marker.

The ordered flows:

  1. Open the accepted estimate and verify the disposable identity, accepted

state, and Copy to Job entry without converting, editing, or sending it.

  1. Open the linked job; start and complete Truck 1 while Truck 2 remains

scheduled, then start and complete Truck 2. Each completion requires the seeded proof photos and every checklist item, and the gate verifies aggregate progress moves from 0/2 to 1/2 to 2/2.

  1. Reopen the completed disposable job, verify No invoice linked yet, and

create one draft invoice for review.

The flows never tap Call, Text, Message, Send/Resend, Collect, Pay, hosted checkout, or payment-recording actions. They do not delete proof or alter the accepted estimate. The final completed job and draft invoice are the deterministic consumed-fixture state; archive or delete the entire synthetic QA fixture through the approved QA cleanup process after evidence review.

Identity, per-flow screenshots, JUnit XML, and command logs are stored under mobile/.maestro-results/signed-job-lifecycle/<release>/<timestamp>/. Stop and record BLOCKED when the exact disposable fixture is unavailable; never substitute another record.

Signed estimate-builder runner

Use the release-identity runner for the approved Residential, Commercial, Fleet, Holiday Lights, Generic Quote, and Asphalt Maintenance builder gates on an installed signed Android release. From the mobile project directory, run:

.\scripts\run-signed-estimate-builders.ps1 `
  -ExpectedAppVersion 1.1.4 `
  -ExpectedBuildNumber 63 `
  -ExpectedUpdateId 019fc4e7 `
  -DeviceSerial <physical-device-serial>

Replace the example values with the exact version, build number, and eight-character Expo update ID shown on More > About. The device serial is mandatory. Use -ExpectedRuntimeVersion or -ExpectedChannel when the release differs from their defaults. The runner requires adb and Maestro, rejects a debuggable package or mismatched release identity, acquires the shared per-device signed-runner lock, and executes the six approved builder flows. The About identity check matches the rendered INSTALLED RELEASE heading exactly, along with the release ID, channel, runtime, and update source. Successful adb pull and Maestro progress written to stderr are captured as runner logs and do not fail the gate unless the native command exits nonzero. Builder deep-link separators are escaped for the Android device shell so seeded customer fields separated by & remain in the URI instead of becoming jobs. Readiness and identity checks use Maestro's live accessibility hierarchy, so a continuously animating save indicator cannot leave a stale UIAutomator dump. The Commercial, Fleet, Generic Quote, and Asphalt gates open only when both explicit read-only preview parameters are present. Their approved customers, scope or fleet inventory, site notes, scheduling, add-ons, and totals are hydrated in memory. Auto-save and manual draft-save paths are disabled, forward editing is blocked, and the populated workspaces expose no delivery action. Normal builder links without those exact parameters continue to use live state and ordinary persistence. These gates therefore prove populated-screen fidelity without creating a proposal, sync item, or customer-facing delivery that must be cleaned up later. Commercial evidence includes separate top and lower captures; the lower capture must visibly reach the $14,600 total instead of repeating the top image. The Asphalt preview renders the approved Greenway Offices satellite overview with saved pavement and crack overlays, 48,500 square feet, 620 linear feet of cracks, 74 parking spaces, three work zones, four priced service rows, two-night phasing, and the $13,295 total. Its compact measurement overview is read-only and cannot auto-save or manually save the fixture. Screenshots, JUnit results, and logs are written beneath mobile/.maestro-results/signed-estimate-builders/<release>/<timestamp>/. Physical Android hardware is the default. Use -AllowEmulator only for the limited preflight described in Shared signed-runner device gate above.

Residential builder

RES-01 Address

Test GPS, location denied, autocomplete, manual street/city/state/ZIP, confirmation, and property lookup in both the five-step and Fusion builders. Verify the authenticated lookup fills square footage, stories, lot size, and year built when available; derives roof square footage and gutter length; updates property-priced service quantities; and leaves manual entry usable when no result is available. Start another estimate from a lead with known property square footage and verify the value is present before lookup returns.

RES-02 Property

Test square footage; siding values Vinyl, Wood, Brick, Stucco, Aluminum, Hardie, and Stone; story values 1, 1.5, 2, 2.5, and 3; lot size; year built; auto-filled values; and manual override.

Expected: changing square footage or stories updates pricing defaults without erasing deliberate edits unexpectedly.

Missing verified pricing recovery

Use an account/device state with no valid active residential pricing bundle. Complete the Step 2 property fields and verify:

  • The property form remains editable and can auto-save.
  • Next stays unavailable because services and totals cannot be verified.
  • The screen explains that pricing, rather than a property field, is blocking

progress.

  • Try pricing again issues a real bundle refresh and does not invent rates.
  • Keep draft & exit returns to Proposals; reopen the draft after restoring

pricing and confirm every property value remains.

  • A direct Step 3 route shows the same pricing recovery state and does not

render service controls or a zero-dollar quote.

RES-AI-01 Single-item photo measurement

Use an online owner or sales account with AI, estimate-view, and estimate-create access, available AI credits, and a verified active price book.

  1. Start a Residential estimate and enter a complete customer/service address.
  2. Select exactly one service, such as Driveway, Patio/Deck, Roof, Fence, or

Gutters, and open Measure with map or photo > Photo assist.

  1. Take a clear photo of only that service area. Include a visible scale

reference when practical, and verify the photo remains attached to that service after leaving and reopening Measure.

  1. Tap Analyze this service photo. Verify the response shows a starting

quantity, low/high range, confidence, measurement basis, visible observations, and honest flags. A photo without scale must show the missing scale limitation and must not claim high confidence.

  1. Before using the suggestion, confirm the estimate quantity and price have

not changed.

  1. Tap Use as starting point. Confirm the field becomes editable but

Apply to estimate remains blocked by Confirm measurement first.

  1. Correct the quantity using an on-site measurement when needed. Confirm the

edit revokes any earlier confirmation.

  1. Tap Confirm verified measurement, then Apply to estimate. Verify only

the selected service quantity changes and its total recalculates from the existing price book.

  1. Reopen Photo assist, use another suggestion, then replace the service photo.

Verify the old AI suggestion and any unconfirmed AI-derived quantity clear.

  1. Repeat while offline, with AI disabled, with exhausted credits, and with a

provider failure. Each state must explain the limitation, preserve manual measurement, and never fabricate or silently apply a quantity.

  1. Repeat with a photo of the wrong surface or multiple service areas. Verify

the response refuses a usable range or clearly flags the mismatch, and no estimate value changes.

Expected: AI proposes a reviewable measurement for one photographed item only. It never writes pricing, never commits a quantity without representative confirmation, and never reuses a suggestion after the photo or service changes.

RES-03 Services

Test every service and add-on:

  • House Wash
  • Driveway
  • Patio/Deck
  • Sidewalk
  • Fence
  • Gutter Cleaning
  • Algae/Mold Treatment
  • Concrete Sealing
  • Window Exterior Rinse
  • Gutter Guard Install

Test quantity, unit, rate/subtotal behavior, select/deselect, zero values, and multiple-service totals.

In the Fusion builder, verify services appear in a vertical list, each row has an accessible + or - control, and no horizontal swipe is needed to find a service.

RES-04 Upsells

Test:

  • Bundle prompt with one, two, three, four, and five selected services
  • Add suggested service
  • Maintenance plan on/off
  • One, two, and three visits per year
  • One-, two-, and three-year agreements
  • Included-service toggles
  • Seasonal defaults
  • Annual discount and multi-year discount
  • Holiday Lights sidecar on/off
  • C9 roofline feet
  • Mini strands
  • Wreaths
  • Minimum and bundle discount

Expected: optional totals appear once in Pricing and Review and survive back navigation.

RES-05 Pricing

Test:

  • Editable rate and subtotal for every selected service
  • Suggested price, floor, and Red Line status when allowed
  • Attempt below floor
  • Add-ons
  • Maintenance and Holiday Lights optional rows
  • Add custom line item
  • Invalid custom line item
  • Remove custom line item
  • Subtotal, tax, total, and margin
  • Red Line access disabled
  • Red Line feature disabled

Expected: the floor is enforced, tax matches the active pricing configuration and state override, and private Red Line/commission information respects membership access.

RES-06 Review and send

Verify customer, property, source, services, add-ons, upsells, custom items, subtotal, tax, total, and margin. Test:

  • Save as Draft without contact information
  • Queue Delivery without customer name
  • Queue Delivery without email or phone
  • Email only
  • Phone only
  • Both email and phone
  • Below-floor send attempt
  • Rapid double-tap
  • Offline queue and later sync

Expected: draft saves once; delivery requires name plus email or phone; queued delivery creates one proposal and one delivery per selected channel.

Commercial builder

COM-01 Client

Search and select an existing client. Clear it. Enter company/client name, email, and phone manually. Verify a client name is required before continuing.

COM-02 Properties

Test one and multiple properties. For each property test name, GPS/manual address, city, state, ZIP, total square feet, floors, roof type, siding type, parking type, paved surface square feet, and notes.

Also test Add Property, property tabs, delete confirmation, and the rule that the last property cannot be deleted.

Expected: every property needs address, city, state, ZIP, and positive square footage.

COM-03 Services

For each property test:

  • Building Wash
  • Gutter Clean
  • Pressure Wash Floor
  • Window Cleaning
  • Roof Treatment
  • Parking Lot Cleaning
  • Custom service
  • Daily Rate
  • Sq Ft Rate
  • Flat Price
  • Rate, days/quantity, subtotal, remove service

Expected: at least one service exists on every property.

COM-04 Pricing

Expand every property, edit every rate, edit days for daily-rate work, and verify property totals and portfolio subtotal. Zero or negative pricing must block continuation.

COM-05 Site conditions

For every property test water access, drainage, safety hazards, additional notes, photo capture, photo-library permission, photo removal, property tabs, and Copy to All Properties confirmation.

Water options are On-site Spigot, Fire Hydrant Permit, Water Truck Required, and Unknown.

COM-06 Scheduling

Test Weekly, Biweekly, Monthly, and Quarterly. Verify annual visits, total property visits, and Seasonal Adjustment.

Expected: frequency is required.

COM-07 Scope

Test portfolio discount boundaries, Net 30, Net 15, Due on Receipt, Custom, custom payment terms, payment notes, and special conditions/scope notes.

COM-08 Price review

Expand every property and verify services, property totals, portfolio subtotal, discount, displayed tax, per-visit total, frequency, and annual total. Compare every amount with an independent calculation and the web app.

COM-09 Review and send

Verify client, properties, services, schedule, terms, discount, seasonal adjustment, per-visit total, and annual total. Test draft, missing client, missing property, missing contact, email-only send, phone-only send, both channels, offline queue, and duplicate-submit prevention.

Fleet builder

FLT-01 Client

Search existing clients by name/email/phone; select and change client; enter name, email, phone, GPS/manual service address, city, state, and ZIP.

FLT-02 Fleet inventory

Test zero, one, and multiple quantities for Semi Truck, Box Truck, Pickup, Van, Bus, and Trailer. Verify total vehicles and estimated labor hours.

FLT-03 Site conditions

Test Onsite Hydrant, Offsite Water Truck, drainage method, access restrictions, camera/photo-library capture, permission denial, multiple photos, and removal.

FLT-04 Scheduling

Test Weekly, Biweekly, Monthly, Quarterly, and One-time. Toggle every preferred weekday and Seasonal Adjustment. Verify annual visits.

FLT-05 Pricing

Set hourly rates for every active vehicle type. Test zero, decimal, invalid, and large values. Test bulk discount at 0, a normal value, 100, and above 100.

Expected: line totals equal quantity multiplied by hours per unit multiplied by rate; discount applies once.

FLT-06 Add-ons

Test Interior Wash, Undercarriage, Windows, Tire Shine, and Engine Bay. Edit price, select/deselect, add multiple custom items, validate blank description/price behavior, edit, and remove.

FLT-07 Price review

Verify editable vehicle amounts, add-ons, custom items, raw subtotal, bulk discount, per-visit total, frequency, annual visits, and annual total.

FLT-08 Review and send

Verify client, address, fleet, site conditions, schedule, seasonal adjustment, pricing, discount, per-visit total, and annual total. Test draft, missing contact, email-only send, phone-only send, both channels, offline queue, and duplicate-submit prevention.

The current Fleet route does not block every incomplete earlier step. Deliberately continue with no vehicles, no water source, no frequency, and zero pricing. Record FAIL if the released workflow can send a meaningless proposal contrary to the release requirement.

Holiday Lights builder

HOL-01 Property

Test GPS/manual address, city, state, ZIP, property photo capture, photo permission denial, photo replacement, and back-navigation persistence.

HOL-02 Zones

Add, rename, retype, and delete multiple zones. Exercise Roofline, Tree, Bush/Shrub, Pathway, Fence, Window, and Custom. Verify property-photo reference and delete confirmation.

HOL-03 Materials

For every zone test LED String Lights, Icicle Lights, Net Lights, Rope Lights, Mini Lights, and C9 Bulbs. Edit linear feet, material cost per foot, estimated/manual labor hours, and labor rate.

Expected: zone material, labor, total, aggregate materials, aggregate labor, and zone subtotal recalculate once.

HOL-04 Add-ons

Test Timer/Controller, 25-foot extension cord, 50-foot extension cord, GFCI Adapter, and Extra Clip Pack. Exercise selection, quantity increment/decrement, editable price where available, custom item validation, custom item removal, and total.

HOL-05 Pricing

Expand every zone. Edit feet, material rate, labor hours, labor rate, and target margin. Verify Materials, Labor, Add-Ons, and Grand Total.

HOL-06 Review and send

Verify customer, property, zones, light types, feet, add-ons, materials, labor, total, and margin. Test draft, missing customer name, missing contact, email-only delivery, phone-only delivery, both channels, offline queue, and duplicate-submit prevention.

HOL-07 Signed visual preview

The signed Android estimate-builder gate opens Holiday Lights with previewMode=readonly&previewFixture=approved. This is a guarded, in-memory-only QA fixture, not a customer record: confirm the Stone Ridge HOA composition shows Roofline Lights (420 linear ft), 6 Pre-lit Wreaths, Garland, the Nov 10–14 / Jan 5–9 schedule, and the $5,160 total. Capture the required top and lower screenshots, then verify the preview does not expose Save Draft, design editing, or delivery controls. Do not use this route for ordinary estimate-entry testing; test the editable HOL-01 through HOL-06 journey separately with approved QA data.

The current Holiday Lights route does not block every empty earlier step. Try reaching Review with no address, no zones, and zero pricing. Record FAIL if a meaningless proposal can be delivered contrary to the release requirement.

HOL-08 Reopened estimate approval and evidence

  1. Save a Holiday Lights estimate using the three-year agreement, an

installation week, a takedown preference, customer and crew notes, at least one property mockup, and a Winter Wonderland render.

  1. Reopen the estimate detail screen. Confirm the total remains the selected

three-year seasonal price and is not described as a one-time price.

  1. Expand Install & takedown preferences, Attachments, and Notes.

Confirm the schedule preferences, both note types, every mockup with its lighting overlay, and the Winter Wonderland render are present.

  1. Select Approve & Sign. Confirm the approval card says **3-year holiday

lights agreement**, identifies the amount as per season, and shows the standard one-season comparison price.

  1. Continue to signature and confirm the same agreement wording remains. Save

the signature and verify approval succeeds without a Suds Club selection or a residential-only warning.

  1. Repeat with the one-season agreement and confirm it is labeled as a

one-season Holiday Lights estimate.

Expected: agreement term, pricing, preferences, notes, and visual evidence survive reopening. Suds Club is not shown or required for Holiday Lights, and the supported estimate can complete approval and signature normally.

HOL-09 Imported estimate reconstruction

Use isolated QA records, not a production customer record.

  1. Prepare an exact EST-779-style orphan fixture: a draft with estimate_type

and wizard_key set to residential, offer_type set to variant, and source_proposal_table set to estimate_offer_groups. Give the source column and the mirrored offer-child metadata one shared parent ID, but omit that parent, its offer group/member records, the proposal row, and the native builder snapshot. Add two Holiday Lights lines, C9 Roof/Gutter Line at $1,476 and Pole/Pillar Lights at $400; subtotal $1,876; 6% tax of $112.56; and total $1,988.56. Record its estimate ID, estimate number, current revision, and the organization's estimate count.

  1. As the assigned representative or an authorized manager, open the fixture

and select Edit estimate. Confirm the app asks Open as Holiday Lights? and explains that it will use this estimate's own customer, scope, and pricing.

  1. Select Cancel. Refresh the estimate and database read, then confirm no

proposal/snapshot was created, the estimate revision and values did not change, and the estimate count stayed the same.

  1. Select Edit estimate again, accept Open as Holiday Lights?, and

verify the builder contains this estimate's customer/property, both editable scope lines, and the exact $1,876 subtotal, $112.56 tax, and $1,988.56 total. Confirm it did not pull a similarly named, addressed, or priced estimate.

  1. Before the first save, change Pole/Pillar Lights from $400 to $500. Save

and confirm the same estimate ID and number now hold subtotal $1,976, 6% tax of $118.56, and total $2,094.56. Confirm the save created the native snapshot atomically, did not rerun an import, and did not increase the estimate count.

  1. Reopen Edit estimate, confirm the saved native builder state and changed

price restore, make a second edit, and save again. Reopen once more and verify the second save persisted on the same estimate ID with no duplicate.

  1. Prepare a compatible imported Holiday Lights fixture with positive scope of

$1,876, a Price-lock adjustment line of -$528.83, taxable amount $1,347.17, 6% tax of $80.83, and total $1,428. Open it, make no changes, and save. Confirm every imported amount remains exact and the negative adjustment is still editable after reopening.

  1. Repeat the adoption attempt as an unassigned representative who lacks edit

access, then with a normally non-editable status. Confirm neither attempt creates a proposal/snapshot or changes the estimate.

  1. Open an editable fixture in two sessions. Save one session, then try to save

the stale session. Confirm the stale save shows a refresh/conflict message, does not overwrite the newer revision, and does not create another record.

Expected: compatible manual imports require explicit confirmation and rebuild an editable Holiday Lights draft from the same estimate only. Cancel performs no write. The first and later saves remain on one estimate ID, preserve exact imported pricing and tax when unchanged, recalculate them after deliberate scope or price edits, and retain the normal permission, status, and stale- revision safeguards.

EST-GEN-01 Native Generic Quote

  1. Open Create > Estimate > Generic Quote and confirm it stays in the app.
  2. Enter customer contact information and a full service address.
  3. Add a live price-book service, product, and equipment item when each type is

available. Confirm the verified residential fallback does not relabel an item as a product or equipment item.

  1. Add and remove custom service, product, and equipment items.
  2. Exercise description, unit, quantity, unit price, taxable status, tax total,

customer message, and total calculations.

  1. Add enough items to scroll the line-item workspace to the bottom. Select

Review & send and verify the next screen resets to the top with Review Quote visible; it must not retain the prior scroll offset.

  1. Save a QA draft, leave the builder, and resume it from mobile.
  2. Force-stop and relaunch before resuming, then verify the draft remains

attached to the same organization and customer context.

Expected: the builder remains native, totals are stable, invalid or empty line items cannot create a meaningless quote, and the draft never appears in a different workspace. Entering review resets only the visual scroll position; the normal draft save and send behavior remains unchanged.

ASP-01 Native Asphalt Maintenance

  1. Open Create > Estimate > Asphalt Maintenance and confirm it stays in the

app.

  1. Enter the customer name and full service address. Confirm Measure remains

blocked until both are complete.

  1. On Measure, verify the satellite property image or the honest unavailable

state. Confirm the screen does not fabricate pavement polygons, crack paths, measurements, photos, or totals.

  1. Enter pavement square feet, crack linear feet, parking spaces, and zone

count. Toggle the supported services and change unit prices.

  1. Confirm service quantities follow the relevant measurements, disabled or

zero-quantity services do not create phantom charges, and the total updates consistently.

  1. Enter optional phasing, continue to Review, save the draft, close the app,

and resume the same draft from Estimates.

  1. Save offline, reconnect, sync, and verify one organization-scoped shared

estimate with the same customer, address, measurements, services, and total.

  1. Send the synchronized estimate using approved QA contact data, open its

customer view, and verify the customer-close flow reaches the matching Asphalt scope and total without exposing internal notes.

  1. Open a legacy Asphalt estimate that does not contain the native Asphalt

builder snapshot. Confirm it still opens the existing office/web editor instead of being misread as a new native draft.

Expected: the new Asphalt flow remains native, validation blocks empty property or meaningless pricing, entered measurements are labeled for field verification, autosave retains one draft identity, and synchronization never places the record in another workspace.

CLOSE-01 Proposal detail

Verify every area:

  • Compact customer, total, module, estimate number, proposal status, and

payment status summary

  • One primary Next step action that matches the current proposal state
  • Call, text, follow-up draft, and resend actions
  • Collapsed More options section with edit, schedule, duplicate, customer

profile, and customer approval actions

  • Progress tracker with drafted, sent, viewed, accepted, and paid stages
  • Delivery summary with email, SMS, PDF, and customer-view state
  • Paid amount, balance, deposit link, balance link, and latest payment link
  • Customer contact details and rep-private notes
  • Offline and queued-sync signals

Native estimate editing

Run this once for each synced native module: Residential, Commercial, Fleet, and Holiday Lights.

  1. Open a QA estimate from the Estimates list.
  2. Verify the detail has one Estimate header and back action, with no

second navigator Estimate Details header stacked above it.

  1. Select Edit estimate.
  2. Confirm Clean Estimate stays in the native app and opens the matching

builder at its first editable step with the saved customer and property data. Confirm the header identifies this as an edit workflow.

  1. Confirm the compact bottom bar visibly shows the per-visit amount and a

high-contrast Next action on Step 1. It must not leave a large blank footer or require an invisible tap target. On later steps, confirm Back and Next remain visible together.

  1. Navigate forward through every step, change one harmless QA field, return

to Review, and confirm the original estimate number is still displayed.

  1. Reopen estimate detail and confirm the same estimate number and record ID

contain the change. Confirm no duplicate estimate was created.

  1. On a second test session, change the same estimate before saving the first

session and confirm the stale session receives a conflict message rather than silently overwriting the newer revision.

  1. Sign out and back in, reopen the estimate, and repeat Edit to confirm the

canonical snapshot restores after the device's synced cache is cleared.

Expected: no admin URL or browser appears; Edit never starts a blank builder; the correct native module opens at its first step; step navigation retains the same draft ID; every forward action is visibly rendered; the footer remains a single compact row; and save updates exactly one canonical proposal/estimate pair.

Residential send after editing

  1. Open a residential QA estimate linked only to approved test contact

destinations.

  1. Select Edit estimate, advance to Review, and confirm there is no

Delivery confirmation checkbox on customer entry or Review.

  1. Confirm the saved email and SMS endpoints appear as selected delivery

channels after the draft loads.

  1. Scroll to the Review actions and confirm Send Estimate, **Present on

device, and Save as Draft** each display a visible button surface and not only text or an invisible tap target.

  1. Use Edit estimate details and confirm it returns to Step 1 without

losing the estimate number or entered changes.

  1. Return to Review and send to one approved test destination.
  2. Confirm the success or queued state names the original estimate number,

then reopen the same record and verify its delivery history and Sent status.

Expected: Send Estimate is enabled when required estimate fields and at least one valid delivery channel are present. Sending updates the existing estimate and its linked proposal to Sent, records the delivery attempt, and does not create a duplicate. The retired delivery-confirmation field must not be required by either the mobile form or delivery service. A rejected delivery must show its specific review message and must never display Sent. The immediate success state is Sent because carrier delivery is confirmed later by the messaging provider.

Customer presentation

  1. Open Hand to Customer.
  2. Confirm the secure customer page hides rep-private notes, Red Line, commission, internal controls, and unrestricted admin navigation.
  3. Review scope and pricing.
  4. Accept and sign as the QA customer.
  5. Return to mobile and refresh/reopen.
  6. Confirm signed name, time, status, and readiness update.

Proposal payment

  1. Create the suggested deposit link.
  2. Complete one successful Stripe test payment.
  3. Test a decline and a 3DS-required card.
  4. Reopen Latest link.
  5. Create a balance link after partial payment.
  6. Pay the remainder.
  7. Confirm amount paid, balance due, payment status, Home, Estimates, and web dashboard all match.

Expected: links are hosted and secure, a button cannot create duplicate checkout sessions through rapid taps, payment status is never marked paid after a decline, and no real card is used.

CLOSE-02 Customer close flow

Open the native close route from an eligible proposal. Complete every visible scope, acceptance, signature, payment, success, cancel, back, refresh, expired session, and already-completed state. Verify rep-private information never appears on the customer-facing portion and completing the flow updates the same proposal rather than creating a duplicate.

MGR-01 Approval detail

As owner/manager, open a pending Red Line approval. Verify request context, estimate/customer linkage, current and floor pricing, rep explanation, approve/reject controls, required notes when applicable, double-submit prevention, completed state, and list refresh. Sales and crew roles must not open the route directly.

MGR-02 Estimate reassignment

As owner/manager, open reassignment, search eligible active members, select and save a new assignee, then verify Pipeline, proposal detail, and web agree. Test no selection, current assignee, archived member, network failure, double-submit, and unauthorized direct-route access.

FIELD-01 / JOB-01 Jobs list from More

Test:

  • Owner/manager organization view
  • Sales representative route view
  • Crew lead and technician assigned-crew scope
  • Crew account with no assignment
  • Scheduled, active, completed, cancelled, and unknown status
  • Scheduled, Active, and Done metrics
  • Customer, service type, address, job number, schedule, status, and total
  • Green CONFIRMED indicator on the next-run card, remaining job rows, and

Dispatch inbox for confirmed jobs

  • Pull to refresh
  • Loading, error, and empty states
  • List performance near the 100-row limit

Expected: crew roles never see another crew's jobs.

For the multi-truck seed, sign in as each truck crew and start only that truck's run. Verify the other runs remain scheduled, proof and checklist state do not cross trucks, duplicate/retried start or complete requests do not create extra history, and the overall job completes only after the fourth truck finishes. Confirm the sales-notes card is visible before Start Job.

FIELD-02 Crew Schedule route

Run as crew lead and technician with zero, one, and multiple assigned jobs. Verify current location, assigned-job markers, selected-job details, directions, map/list handoff, denied-location behavior, and background/resume.

Expected: the map contains only authorized assigned work, continues to explain why location is unavailable when permission is denied, and never treats the emulator as proof of physical-device GPS accuracy.

JOB-02 Job detail

Verify:

  • Job number and status
  • Client and service type
  • Date, start time, address, Open in Maps, and total
  • Prominent green CONFIRMED indicator for a confirmed appointment
  • Customer, estimate, and invoice navigation
  • Reschedule active work with the calendar/time selectors and verify the new

date/time persists and the old confirmation indicator disappears

  • Refuse rescheduling completed, invoiced, or cancelled work
  • Invoice number, invoice status, taxable amount, paid, and balance
  • No-invoice explanation
  • Crew alerts
  • Crew notes
  • Missing address and missing job states

Job payment permissions

Expected:

  • Owner, manager, and crew lead can see collection controls when an invoice has a positive balance.
  • Sales representative and technician cannot see collection controls.
  • A paid invoice shows no collection controls.
  • A job without an invoice shows Create Invoice for an eligible office

user. One tap creates one draft with the job's customer, line items, discount, tax, total, and estimate linkage, then opens the new invoice.

Card payment

Configure three tip choices under Settings > Payment Collection, including at least one percentage and one flat amount. Reopen mobile, test all three plus No tip, and verify percentage tips use the taxable amount rather than the balance or tax. Continue to hosted card checkout and confirm the invoice amount plus the separate tip. Change the admin configuration while the payment screen is open and verify the outdated selection is refused until the screen reloads.

Verify the compact standard row contains only Card, ACH, and Other. From both invoice detail and the invoice-list Collect action, open the collector and tap its visible back arrow. Both paths must land on that invoice; the button must not become a no-op.

ACH payment

Select the standard ACH option, record the approved test payment, and verify the ledger stores ACH rather than a generic Other method. ACH remains a standard choice and does not appear again inside the expanded Other list.

Cash payment

Expand Other, select Cash, enter an optional cash receipt note, record payment, verify success alert, cleared form, refreshed balance, and separate tip.

Check payment

Expand Other, select Check, and verify the check/reference fields become visible. Record a check and verify the reference and payment amount appear in history. Test with neither check nor reference number, then with check number, reference number, and both. Verify the required-field alert and final ledger.

Other payment

Confirm Other expands to Cash, Check, and the alternate methods enabled under Settings > Payment Collection, including default Zelle, financing, and bank transfer choices. Test one configured method, verify its name in payment history and the receipt, then disable it and confirm a stale mobile submission is refused.

Field-work scope check

Crew roles must verify start-work, checklist, before/after proof, execution notes, and completion controls only on assigned work. Office roles verify customer/estimate/invoice navigation, job rescheduling, and invoice creation. Unauthorized roles and unassigned crew must not mutate the record.

INV-01 Invoices list

Open More > Invoices. Test search, All/Draft/Open/Overdue/Paid filters, status counts, invoice/customer/job identifiers, issue/due dates, total, paid, balance, pull to refresh, loading, empty, no-results, error, and role/tenant scope. Open each supported status and return without losing the current filter.

Add an inconsistent import fixture whose stored status is sent, send timestamp is empty, due date is in the past, and balance is positive. Verify it appears under both Unsent and Overdue, displays Unsent with Send as its next action, and contributes its balance to overdue totals. It must not appear under Sent. Also verify a zero-total unpaid draft stays Unsent and sendable instead of becoming Paid. Around a timezone boundary, confirm the Overdue tab and the row badge both use the device's local calendar date.

INV-02 Invoice detail

Verify invoice number/status, customer, issue/due dates, subtotal, discount, tax, total, paid, balance, line quantities/rates/amounts, notes, and linked client/job/estimate navigation. Test missing optional links, paid and overdue states, header and Android Back, invalid ID, refresh, and organization boundary. Edit due date with the calendar and edit notes, verify persistence, and compare totals with the job, proposal, and web invoice.

TAB-06 More and settings

Verify the account card shows the correct name, role, and organization. Open every row and return using both the header back action and Android back. Confirm the pending-sync badge matches Offline & Storage.

Confirm Search records opens Global Search and Filter tools and settings finds permitted More destinations without sending a record-search request.

MORE-REC-01 Recurring Plans and Suds Club

Open More > Recurring Plans & Suds Club with an organization that has at least one active plan and four occurrences. Verify:

  • Plans, Visits, and Exceptions each issue a bearer-authenticated

/api/mobile/maintenance-plans request for the selected organization.

  • All, Active, and Needs attention change the returned records, not

only the selected chip color.

  • The selected segment and filter label stays readable when the screen opens

and after every selection change. Repeat this check in Analytics and Payments because all three modules use the same accessible chip control.

  • A monthly plan shows its monthly charge, customer, plan term, live status,

and completed count without displaying an annual customer total.

  • The Suds Club callout states four visits per year and frames membership as an

upgrade opportunity without inventing a customer price.

  • Visits show their real service, sequence, schedule or target month, amount,

status, and job linkage.

  • Paused/draft/declined plans and overdue/skipped/canceled visits appear under

Exceptions when applicable.

  • The screen identifies itself as live read-only and exposes no schedule,

pause, save, or other write control.

  • A bearer token for another organization cannot read the plan, customer, or

occurrence.

Open approved destinations in Inventory, Dispatch, Expenses, Documents, Marketing, Administration, Account, and Exceptions. Expected: each screen loads live organization-scoped rows or an honest empty/error state, identifies itself as read-only, and exposes no simulated save action or /api/admin/* request. Change a segment and filter and confirm the shared mobile endpoint receives the selected screen, segment, and filter.

Open both Payments & Transactions and Payment Collection from the Finance section. Both rows must reach the live transaction workspace. The Payment Collection shortcut must not grant billing access, record money, or expose a provider write by itself.

For offline cold-start coverage, verify that a workspace snapshot older than 24 hours is deleted, an explicit membership authorization rejection never falls back to it, and a late membership or organization response cannot restore the snapshot after sign-out or an account change.

Open Team, Time & Pay as an owner or manager. Verify the visible Workforce navigation opens Team Timecards, Availability & Time Off, and Training & Certifications, and a timecard row opens Review Timesheet. Repeat as a crew lead or technician: Time Clock, availability, and training remain available, while My Pay appears only for configured commission pay. A sales representative must not inherit My Pay merely because the organization enables performance pay.

SET-01 Profile

Test avatar/photo-library permission, crop, upload, initials fallback, display name, read-only email, phone, role badge, disabled clean-state save, successful save, upload error, and persistence after relaunch.

Expected: the profile-photo summary and account fields use compact white Fusion panels on the standard mobile canvas, with no legacy gray full-screen surface.

SET-02 Organization

Owner and manager:

  • Upload a real PNG, JPEG, and WebP logo and verify Logo Updated appears
  • Reject a renamed or disguised non-image file before any upload
  • Verify the saved logo uses a new versioned URL, survives relaunch, and the

superseded same-workspace object remains available for historical content

  • Reject a correctly scoped logo URL when its storage object does not exist
  • Force profile refresh to fail after a successful upload and verify the app

says the logo is live but organization data could not refresh

  • Company name, phone, email, website
  • Street, city, state, ZIP
  • Every preset brand color
  • Valid and invalid custom hex
  • Multiline terms and conditions
  • Save and relaunch

Signed Android evidence on Build 63: the native photo picker and cropper uploaded the QA workspace's existing 1080x1080 PNG, displayed Logo Updated, and persisted a new logos/{workspace-id}/{uuid}.png URL. The saved object returned 200 image/png, matched the selected file byte-for-byte, the previous public object remained readable, and Organization passed again after a force-stop/cold reopen. A signed second-tenant replacement attempt remains the final physical isolation check; the API and Storage-policy isolation suites are already green.

Sales representative, crew lead, and technician:

  • Verify Access Restricted.
  • Verify no editable organization form or write request is available.

SET-03 Pricing Defaults

Verify active version; House Wash base, per-square-foot, and minimum; Driveway, Sidewalk, Patio, Fence, and Gutters minimums; global minimum ticket; default tax fallback; estimate expiry; and Red Line settings.

Expected: this screen is read-only and matches the active web price book. The authority note, section labels, compact value rows, loading card, and error card all use the Fusion settings hierarchy.

SET-04 Tax Rates

Verify organization state, pricing fallback, effective rate, PA 6% override, and MD 0% override. Compare a residential estimate in each available test organization.

Expected: this screen is read-only and matches the builder calculation. Its authority note and compact value rows match Pricing Defaults.

SET-05 Notifications

Test:

  • Load, six-second timeout, defaults fallback, and Retry
  • Proposal Viewed
  • Stale Deal Reminder
  • New Deal Assigned (Phase 2)
  • Quiet Hours on/off
  • Start and end time pickers at 30-minute intervals
  • Overnight quiet hours
  • Save and persistence
  • Physical-device push delivery
  • Foreground, background, and tapped-notification routing
  • Permission Allow, Deny, and recovery in system settings
  • Open a shared quote through its legacy /p link and confirm the redirect to

/quote records only one view, communication event, alert, and push

  • Prefetch the shared quote with next-router-prefetch and

x-middleware-prefetch; neither request may count as a customer view

  • For fleet and commercial-building proposals, confirm the push opens the

verified linked mobile estimate. A proposal without that link must not send a broken push.

Do not claim push PASS from an emulator that cannot register for real push notifications.

SET-06 Offline & Storage

Verify:

  • Offline banner
  • Cached proposal count
  • Pending changes
  • Last synced
  • Sync Now enabled and disabled states
  • Auto-sync toggle
  • Clear All Cache cancel and confirm
  • Failed Items and Dismiss Failed Items

Expected: Sync Now is disabled with no connection or no pending items. Clear All Cache warns that unsynced changes will be lost. Test cache deletion only with disposable QA data.

Also verify whether Auto-sync persists and actually changes sync behavior. The current screen stores the toggle in screen state; if the release requirement expects a persistent engine setting, record FAIL when it resets or has no effect.

SET-07 About

Verify icon, CleanEstimate Pro name, version, build, current copyright year, Terms, Privacy, support email, and support phone. Confirm every link opens the expected external app and approved production URL.

Expected: release metadata and help/legal links appear in separate compact Fusion panels, with the update action aligned inside the release panel.

GLOBAL-01 Bug report

On a top-level tab, nested detail screen, estimate builder, and settings screen:

  1. Confirm the floating bug button is visible, remains above the tab bar and

system navigation, and does not cover the screen's main action.

  1. Open it and confirm the current screen screenshot is attached before the

form appears.

  1. Enter a description, steps, expected result, impact, and area. Replace the

screenshot from the photo library.

  1. Send online and verify the returned bug number exists in **Admin > Bug

Reports, with the device, build, OTA update, page history, errors, failed requests, and screenshot. Confirm the native session succeeds without a browser cookie and does not return Unauthorized**.

  1. Repeat offline. Reconnect as the same user and workspace, then verify the

queued report sends once.

  1. Confirm signed-out and customer approval screens do not show the staff bug

button.

  1. For an allowlisted owner workspace, verify an accepted mobile report creates

a GitHub issue with codex:approved, then receives codex:started. Confirm other roles and workspaces do not receive the approval label automatically.

  1. For a disposable approved bug, confirm the hosted workflow opens a PR,

runs lint, typecheck, builds, web tests, mobile tests, database checks, and the docs build before merging. Confirm the matching docs update reaches main, the issue closes with codex:completed, and Vercel receives a production deployment. When mobile files changed, confirm an iOS and Android Expo production OTA is published.

  1. Force a release-gate failure and confirm the repair does not merge and

receives codex:failed with a usable Actions link. Confirm repeated label events do not start duplicate production work.

Open an invalid deep link. Verify the not-found page renders, explains the missing page, and returns to the mobile workspace without a crash or loop.

Offline, sync, and conflict suite

Run once as sales and once as a crew role.

  1. Open the app online and complete a sync.
  2. Open the records needed for the test.
  3. Start a native estimate and change data on multiple steps.
  4. Enable airplane mode.
  5. Continue, save a draft, and confirm queued/offline state.
  6. Force-stop and relaunch offline.
  7. Resume the local draft and verify every field and amount.
  8. Reconnect on a slow network.
  9. Trigger Sync Now.
  10. Confirm pending count returns to zero.
  11. Confirm the sync warning clears when no pending or failed work remains.
  12. Verify one server record, one client linkage, and one delivery.

Conflict pass:

  • Edit the same QA record on web while mobile is offline.
  • Reconnect mobile.
  • Verify the documented conflict behavior or record the actual resolution.
  • Confirm notes, totals, and status are not silently lost.

Failure pass:

  • Interrupt a sync.
  • Expire the session before sync.
  • Cause a retryable server error in a safe test environment.
  • Verify retries are bounded and failed items become visible.
  • Tap Retry and verify one failed item is counted once even when it exists

in both the local queue and the active sync engine.

  • Close the warning and verify it hides without deleting queued work. Change

the queue state and confirm a new warning appears.

Permission and device-integration suite

CapabilityAllow pathDeny pathRecovery
LocationGPS fills addressManual address remains usableEnable in system settings and retry
CameraCapture property/site photoNo crash; explanation remains clearEnable and capture
Photo librarySelect avatar/logo/photoPermission Required alertEnable and select
NotificationsGeneral push and inbound call notification arriveApp remains usable; calls use fallbackEnable, relaunch, and verify registration
MicrophoneTwo-way company-call audio worksClear permission guidance; no call startsEnable and retry the approved QA call
Phone dialerApproved QA number opensDialer unavailable alertInstall/enable dialer and retry
EmailApproved QA address opensEmail unavailable alertConfigure client and retry
MapsCorrect encoded address opensAddress/Maps unavailable alertAdd address and retry
BrowserCustomer view/checkout/web wizard opensClear unavailable alertRestore browser/link handling

Form data must survive every denied-permission path.

Conditional Canvass coverage

For owner, manager, and sales-representative builds, Canvass is a core tab. Verify:

  1. Add it to the route ledger.
  2. Follow the complete Canvassing guide.
  3. Test role, organization, campaign, territory, and feature gating.
  4. Test map/list, location permission, address selection, homeowner/business outcome, lead creation, appointment creation, notes, offline behavior, and resume.
  5. Verify no tab shifts position after configuration resolves.

If the approved build is supposed to include Canvass and it is missing, record FAIL.

Connected end-to-end journeys

Page-level coverage does not replace connected workflows. Run these with the same QA records.

Journey 1: Residential driveway close

Lead creation -> Lead detail -> Residential builder -> Draft resume -> Queue delivery -> Estimates -> Proposal detail -> Customer view -> Signature -> Deposit -> Balance -> Home/CRM/web verification.

Journey 2: Existing customer repeat sale

Search -> Customer detail -> Edit customer -> New estimate with prefill -> Residential upsells -> Delivery -> Customer history -> Message thread -> Company-line call.

Journey 3: Commercial portfolio

Existing client -> Three properties -> Different services and site conditions -> Copy conditions -> Recurring schedule -> Portfolio discount -> Review -> Delivery -> Customer acceptance -> Mobile status verification.

Journey 4: Fleet contract

New customer -> Six vehicle types -> Site photos -> Frequency/days -> Rates/discount -> Add-ons/custom item -> Review -> Delivery -> Draft/resume -> annual-total verification.

Journey 5: Holiday Lights

Property photo -> Every zone type -> Multiple light types -> Materials/labor -> Add-ons -> Margin -> Delivery -> Deposit link -> accepted/paid state.

Journey 6: Generic and Asphalt quotes

Generic Quote -> native customer information -> price-book/custom line items -> review -> save -> resume in mobile. Then test Asphalt Maintenance -> native property -> measurements -> services and phasing -> review -> save -> offline resume -> sync -> search/list/detail -> customer close.

Journey 7: Job and payment

Accepted estimate/job fixture -> Jobs list -> Maps -> Invoice -> card with tip -> partial/paid refresh -> cash/check variants on separate fixtures -> permission boundary verification.

Journey 8: Offline recovery

Online cache -> native builder -> airplane mode -> save -> force-stop -> offline resume -> reconnect -> sync -> one server record -> cross-screen verification.

Journey 9: Role boundaries

Owner -> Manager -> Sales -> Crew lead -> Technician. For the same seeded records, verify the same six-tab order with role-specific content, crew assignment scope, job payment permissions, organization restriction, Red Line membership, and API data boundaries.

Cross-cutting usability and accessibility

Run on every page:

  • Screen reader announces page title, field label, button role, selected state, disabled state, and error.
  • Touch targets are at least the supported minimum and are not overlapped.
  • Logical focus order follows the visual order.
  • Keyboard types match email, phone, numeric, decimal, and password input.
  • Submit/Next remains reachable with the keyboard open.
  • Large text does not clip totals or hide actions.
  • Color is not the only status signal.
  • Red Line, success, warning, danger, and disabled states retain readable contrast.
  • Dates, times, currency, and phone numbers are understandable.
  • Loading has a visible indicator.
  • Empty states explain the next action.
  • Error states preserve existing data and offer recovery.
  • Back navigation is predictable and does not discard without warning.
  • Bottom tab and sticky actions respect safe areas.
  • Fusion residential estimates do not show a duplicate route header, and the

pinned Save and Close Kit actions remain above the iPhone home indicator and Android system navigation bar.

Performance and reliability

Measure and record:

MetricTarget or release expectation
Cold launch to usable sign-in/workspace
Warm launch
Sign-in completion
Home live-data load
Search response after debounce
Builder step transition
Draft save
Proposal queue action
Sync 10 pending items
Jobs list at 100 rows
Memory after completing all four builders

Flag repeated API requests, uncontrolled retries, duplicate records, blank transitions, growing memory, frozen inputs, or scrolling below 30 FPS on the primary test device.

Security and privacy checks

  • Tenant and role boundaries hold on lists, search, detail routes, deep links, refresh, and cached data.
  • Customer view never exposes rep-private notes, Red Line, commission, internal IDs, or unrestricted admin navigation.
  • Logs contain no password, bearer token, reset link, full card number, signature secret, or private customer payload.
  • Signed and payment URLs are HTTPS and scoped to the intended record.
  • Sign-out prevents cached-data disclosure.
  • Direct IDs from another organization return a safe unavailable/not-found result.
  • Payment actions require a valid session and supported role.
  • Manual payment records include the correct organization, invoice, collector, method, amount, and tip.
  • Clear Cache affects only local app data.

Defect severity

SeverityDefinition
P0Cross-tenant exposure, auth bypass, real-customer send/call, real-money risk, secret exposure, or production-data corruption
P1Core login, create, quote, send, sign, pay, sync, or role workflow is blocked
P2Important workflow is wrong or misleading but a safe workaround exists
P3Visual, copy, accessibility, or polish issue without workflow loss

Every defect must include:

  • Test case ID and short title
  • Severity
  • Build, backend, role, organization, device, and network
  • Exact preconditions and steps
  • Expected and actual result
  • Screenshot or video
  • Relevant device/network logs with secrets removed
  • Record IDs using QA data only
  • Reproduction rate
  • Result after relaunch and after reinstall when safe
  • Web comparison when the workflow crosses to web

Final report

The release report must contain:

SectionRequired content
Executive resultPASS / FAIL / BLOCKED and release recommendation
CoveragePassed, failed, blocked, not applicable, and total
Route ledgerResult for all 67 current surfaces plus the call overlay and build-specific extras
Persona coverageResult for all five staff roles and customer
Device coverageEvery required platform/device row
Connected journeysResult for all applicable journeys
DefectsP0-P3 totals and links
Data cleanupRecords, payments, messages, calls, photos, and remaining cleanup
Evidence indexScreenshots, videos, logs, and network notes
Residual riskUntested or blocked areas and why

Release sign-off checklist

  • [ ] Exact artifact, build, runtime, backend, and organization were recorded.
  • [ ] Every current route has PASS, FAIL, BLOCKED, or approved NOT APPLICABLE.
  • [ ] All five roles were tested with separate accounts.
  • [ ] All six native builders were completed, saved, resumed, and delivered.
  • [ ] The native Asphalt Maintenance builder was completed, saved, resumed,

synchronized, and checked against a legacy Asphalt record.

  • [ ] Customer view, signature, deposit, and balance were verified.
  • [ ] Job card, cash, and check paths were verified with correct permissions.
  • [ ] Offline save, force-stop, resume, reconnect, and sync were verified.
  • [ ] Native outbound, inbound, first-answer-wins, background/killed delivery,

one-hour registration refresh, office fallback, and voicemail were tested with approved QA phones.

  • [ ] Camera, library, location, notifications, microphone, dialer, email, maps, and browser were allowed, denied, and recovered where applicable.
  • [ ] Search, empty, loading, error, retry, and not-found states were tested.
  • [ ] Small screen, large text, keyboard, screen reader, and safe-area checks passed.
  • [ ] No cross-organization or role-boundary issue occurred.
  • [ ] No real customer or real payment method was touched.
  • [ ] QA data cleanup was completed or documented.
  • [ ] No open P0 or P1 defect remains.

The QA lead signs the release only after the route ledger, connected journeys, evidence, cleanup, and residual risks are all present.

Was this article helpful?

Still need help? Contact support