Skip to content

QBTime Manager — End-to-End Test Walkthrough

Who this is for: the person testing QBTime Manager before go-live (or after a big change). It is a click-by-click script that assumes nothing — every URL, button label, and field is spelled out. Follow it top to bottom and you will exercise every feature the app has, from the public sales page through a manager's daily tasks.

Where to run it: against staging (staging.qbtime.r2d2dev.com) with Stripe in TEST mode and a QuickBooks Time trial/sandbox account. Never run write tests against a customer's live QBT data.

How to mark progress: each step has a checkbox. Tick it when the "✓ Expect" line matches what you see. If it doesn't, stop and note the step number.


Step 0 — Prerequisites (do these once, before testing)

You need five accounts/tools ready. None are optional for a full test.

0a. A QuickBooks Time trial (or developer) account

This is the system QBTime Manager connects to. Without it you can't test users, schedules, reports, approvals, or time off against real data.

  1. In a browser, go to https://quickbooks.intuit.com/time-tracking/ (QuickBooks Time). Click Free Trial (or Try it free).
  2. Sign up with an email you control and start the free trial (currently ~30 days; a card is only required to continue after the trial). Pick a company name like "QBTime Test Co."
  3. When the QBT dashboard loads, add 2–3 test team members (People → Add) with real-looking names and emails you can ignore. You'll manage these from QBTime Manager later.
  4. Add a schedule for a couple of them today (Schedule → New event) so the attendance report has data to compute.
  5. Developer access (API Add-On): QBTime Manager talks to QBT through that account's API Add-On, which yields the OAuth client_id / client_secret. In the QBT account go to Feature Add-ons → API, install/enable it, then click "Add a new application" to create credentials — copy the client ID and client secret. (You'll paste these in the Connect wizard, Step 5.)
  6. Approvals Add-On (for the approvals test): in the QBT account, enable the Approvals add-on (Add-ons → Approvals). Without it, the app's approval chain still works but won't write back to QBT.

✓ Expect: a QBT trial account with 2–3 team members, at least one scheduled shift today, and (eventually) an API client ID + secret.

0b. A Stripe account in TEST mode

  1. Log in to https://dashboard.stripe.com. Top-left, make sure the Test mode toggle is ON (it says "Test mode" in orange).
  2. Confirm the tier Prices exist: Product catalog → Products. You should see the plan products from seed_plans.sql. If not, that's a deploy step (see Deploying the App → Billing); don't start billing tests until they're there.
  3. Create one test coupon + promotion code for the discount test later: Product catalog → Coupons → Create (e.g. 50% off, Duration = Repeating, 3 months), then add a Promotion code like TEST50.
  4. Have Stripe's test card handy: 4242 4242 4242 4242, any future expiry, any CVC, any ZIP.

✓ Expect: Stripe in Test mode, plan prices visible, one promo code TEST50.

0c. Access to the staging app + the setup secret

  1. The app is at https://staging.qbtime.r2d2dev.com.
  2. You need the staging SETUP_BOOTSTRAP_SECRET value (from the password manager / Cloudflare dashboard) to create the first admin in Step 3.
  3. You need a TOTP authenticator app on your phone (Google Authenticator, Authy, or Microsoft Authenticator) for MFA.

0d. An email inbox you can read

Report emails and password-reset links go to real addresses. Use an inbox you can open (e.g. a test Gmail) for the recipient in report + reset tests.

0e. A terminal (for the cron + internal-endpoint checks)

PowerShell on the machine that has the repo, with npx wrangler available and npx wrangler login already done.

✓ Expect: you can open the staging URL, you have the setup secret, an authenticator app, a readable inbox, and a working terminal.


Step 1 — The sales page

  • [ ] 1.1 Open https://get.qbtime.r2d2dev.com (the marketing/landing page). ✓ Expect: the QBTime Manager landing page loads, with Features, Pricing, FAQ links and Start now / Get started buttons.
  • [ ] 1.2 Scroll to Pricing. ✓ Expect: tier cards (Starter, Standard, …) each with a Choose button.
  • [ ] 1.3 Confirm the footer reads "Published by CowboyMSP · support@cowboymsp.com · cowboymsp.com" (branding/chargeback disclosure), and the browser tab shows the QBTime favicon.
  • [ ] 1.4 Click Choose Starter. ✓ Expect: the browser goes to https://qbtime.r2d2dev.com/signup?plan=starter (the app's signup page, with the plan pre-selected).

Step 2 — Self-serve signup + Stripe Checkout (TEST mode)

  • [ ] 2.1 On the signup page, ✓ Expect: heading "Start with QBTime Manager", fields for Company name, Admin email, Admin username, Password, Plan, and the disclosure line "operated by CowboyMSP … charges appear as COWBOYMSP* QBTIME".
  • [ ] 2.2 Fill: company "E2E Test Co", the admin email from 0d, a username, a password ≥ 12 chars. Leave Plan = Starter. Click Continue to payment. ✓ Expect: redirect to a Stripe Checkout page (checkout.stripe.com).
  • [ ] 2.3 On Checkout, ✓ Expect: a line for the monthly plan + a one-time onboarding fee line, and an "Add promotion code" link.
  • [ ] 2.4 Click Add promotion code, enter TEST50, apply. ✓ Expect: a discount line appears and the total drops.
  • [ ] 2.5 Pay with the test card 4242 4242 4242 4242 (any future expiry/CVC/ZIP). ✓ Expect: payment succeeds and you're returned to /app/billing?checkout=success in the app.
  • [ ] 2.6 In Stripe Dashboard → Payments, find the test payment. ✓ Expect: the statement-descriptor preview shows COWBOYMSP* QBTIME (the per-product override on the QBTime price; or your configured value), the discount applied, and an invoice with the onboarding fee.

Note: self-serve signup creates the customer + first admin and provisions billing. The QBT connection happens next, in the Connect wizard (Step 5).


Step 3 — First-run platform admin (one-time, the operator/you)

This is separate from customer signup — it creates the root Global Admin (the DevOps account that runs the whole platform). Do it once per environment.

  • [ ] 3.1 Open https://staging.qbtime.r2d2dev.com/setup. ✓ Expect: a first-run form with Setup secret, Username, Email, Password.
  • [ ] 3.2 Enter the staging SETUP_BOOTSTRAP_SECRET (from 0c) + a username, email, and strong password. Submit. ✓ Expect: "The root Global Admin was created. Sign in, then enroll MFA. Remember to unset the setup secret."
  • [ ] 3.3 Security check: in the Cloudflare dashboard, remove SETUP_BOOTSTRAP_SECRET for staging (so /setup can't be reused). Reload /setup. ✓ Expect: it no longer lets you create another admin.

Step 4 — Sign in + mandatory MFA

  • [ ] 4.1 Go to /login. Enter the admin username + password from Step 3. ✓ Expect: you're prompted to enroll MFA (it's mandatory).
  • [ ] 4.2 At /mfa/enroll, scan the QR with your authenticator app, enter the 6-digit code. ✓ Expect: you receive recovery codes — save one for 4.5.
  • [ ] 4.3 You're signed in. ✓ Expect: the platform console (/platform) if this is a DevOps account, or the app (/app) for a customer admin.
  • [ ] 4.3a In the app header, the moon/sun theme toggle flips light/dark and the choice persists on reload (replaces the old Light/Dark text).
  • [ ] 4.4 Sign out (top right). Sign in again. ✓ Expect: after password, it asks for the 6-digit code; enter it to get in.
  • [ ] 4.5 Sign out, sign in, and at the code step click "Use a recovery code"; enter the saved recovery code. ✓ Expect: it works (one-time use).
  • [ ] 4.6 Forgot password: sign out, on /login click Forgot password?, enter the admin email. ✓ Expect: the "if an account exists…" message, and a reset email arrives at the 0d inbox. Click the link, set a new password, sign in with it.
  • [ ] 4.7 Lockout: sign out and enter a wrong password ~5 times. ✓ Expect: a lockout message; it clears after the window (or via a password reset).

Step 5 — Connect a QuickBooks Time company

This links the app to your QBT trial (Step 0a). As a customer admin, go to the app; as DevOps, use the customer app via the Customer app link.

  • [ ] 5.1 Go to /app/companies. If a company already exists from signup, click Connect on it; otherwise click Add a company, enter a name + timezone (the timezone picker lets you type to search), and the QBT client ID/secret.
  • [ ] 5.2 The Connect wizard has three steps: Create the QuickBooks Time API add-on → Enter your API credentials → Authorize the connection. Follow them; use the client ID/secret from your QBT API add-on (Step 0a). ✓ Expect: each step has a "Need help? We'll set it up for you" link (files a support request — don't need it here).
  • [ ] 5.3 On Authorize, you're sent to Intuit to approve, then returned to the app. ✓ Expect: the company's status changes from pending to connected.
  • [ ] 5.4 Rotate secret: on the Companies page, click Rotate secret for the company, paste a new (or the same) secret. ✓ Expect: "secret rotated"; the company still works.

Step 6 — Users (daily task: manage your people)

  • [ ] 6.1 Go to /app/users. ✓ Expect: the team members from your QBT trial appear (read live from QBT). If you added >50, a Load more button pages them.
  • [ ] 6.2 Click Add user, fill username/email/name/mobile, save. ✓ Expect: the new user appears (written back to QBT — verify in the QBT account).
  • [ ] 6.3 Click Edit on someone, change their name, save. ✓ Expect: updated.
  • [ ] 6.4 Tick the checkboxes on 2 users (or Select all), click Archive selected. ✓ Expect: an Undo banner appears for ~10s. Click Undo. ✓ Expect: the users return to active.
  • [ ] 6.5 Click Export CSV. ✓ Expect: a users.csv downloads and opens.

Step 7 — Schedule (daily task: build & adjust shifts)

  • [ ] 7.1 Go to /app/schedule, Week view. ✓ Expect: a 7-day grid.
  • [ ] 7.2 Click the + on a day header (or Add shift), pick a calendar, a person, start/end times, save. ✓ Expect: a colored shift block on that day.
  • [ ] 7.3 Click the shift block → Edit, change the time, save. ✓ Expect: updated.
  • [ ] 7.4 Drag the shift block onto a different day and drop it. ✓ Expect: it moves to that day (same time-of-day); reload the page — it's still on the new day (persisted to QBT).
  • [ ] 7.5 Switch to List view. Tick a couple of shifts, Deactivate selected. ✓ Expect: an Undo option; deactivated shifts drop off.
  • [ ] 7.6 ✓ Expect: a day with no published shift shows a coverage-gap flag; a person double-booked shows a red conflict outline.

Step 8 — Reports (daily task: who showed up)

  • [ ] 8.1 Go to /app/reports. Pick Today (or Yesterday), click Preview. ✓ Expect: an on-screen report grouping people into Present, Late, Absent, In progress, On leave, Unscheduled — matching your QBT trial data.
  • [ ] 8.2 Click Download PDF on the preview. ✓ Expect: the browser print dialog opens with the report; "Save as PDF" produces a file.
  • [ ] 8.3 Click Run & send. ✓ Expect: the report emails to the configured recipients; check the 0d inbox — the From shows QBTime Manager (CowboyMSP).
  • [ ] 8.4 Under Scheduled reports, create one (type, cadence, time, days, recipients, delivery mode). ✓ Expect: it lists; you can Enable/Disable and Delete it.
  • [ ] 8.5 Saved views: under Saved views, name the current run (e.g. "Yesterday — E2E Test Co"), click Save view. ✓ Expect: it lists with Run and Delete; Run re-loads those params and previews.
  • [ ] 8.6 Additional report data (engine): with live timesheets present, the system computes Hours per employee, Overtime (over threshold), and Hours by jobcode. Note: these compute correctly but are not yet selectable as their own emailed report type (the dispatch/wiring is a future step) — verify the numbers look right once you can compare against QBT. Missing-punch detection is live and feeds the bell (see 9.x).

Step 9 — Notifications & proactive alerts

  • [ ] 9.1 After a report run (Step 8) that has a no-show or late person, open the bell (top right). ✓ Expect: a proactive alert like "N no-shows on " / "late arrivals" / "coverage gap".
  • [ ] 9.2 Go to /app/settings → Proactive alerts. Toggle No-shows off, save. Re-run a report. ✓ Expect: no no-show alert this time.
  • [ ] 9.3 Open the bell, click to mark read. ✓ Expect: the unread badge clears.

Step 10 — Multi-level approvals

(Needs the QBT Approvals Add-On enabled — Step 0a — for the QBT write-back.)

  • [ ] 10.1 Go to /app/approvals (under More ▾). Under Submit a period for approval, pick start/end dates. Leave it single-level. Click Submit. ✓ Expect: a pending request appears with a 1-step chain.
  • [ ] 10.2 Click Approve step 1. ✓ Expect: status → approved. Check the QBT account: the users' approved-through date now matches the period end.
  • [ ] 10.3 Submit another period, tick Two-level (manager → admin). ✓ Expect: a 2-step chain. Approve step 1 → still pending (advances to step 2). Approve step 2approved.
  • [ ] 10.4 Submit a third period, then Reject. ✓ Expect: status → rejected (whole request). Check /app/activity — every submit/approve/reject is logged.

Step 11 — Time Off (read-only)

  • [ ] 11.1 In your QBT trial, create a time-off request for a team member.
  • [ ] 11.2 In the app, go to /app/time-off (under More ▾). ✓ Expect: the leave entry appears (user, dates, status). It's read-only for now — an info banner says approve/deny is coming. If fields look wrong/blank, note it: the time-off field mapping is defensive and unverified against live QBT.

Step 12 — Billing edge cases (Stripe TEST mode)

  • [ ] 12.1 Over-limit company add: on Starter (1 company), add a 2nd company. ✓ Expect: it's created with no immediate charge, and a dashboard banner appears: "your plan moves to at $X/mo next cycle."
  • [ ] 12.2 In Stripe (test), confirm a one-time onboarding delta invoice item was queued for the next invoice (only the difference vs the tier you started on).
  • [ ] 12.3 Over the largest plan: try to add companies beyond the top tier's limit. ✓ Expect: a hard block — "exceeds the largest available plan, contact us."
  • [ ] 12.4 Past-due: in Stripe, mark the test invoice unpaid (or use a failing test card on a new sub). ✓ Expect: a past-due banner in-app; after the grace window the account locks; paying unlocks it.
  • [ ] 12.5 Manage billing: /app/billing → Manage billing in Stripe opens the Stripe customer portal.
  • [ ] 12.6 Coupon survives tier change (lifetime free): apply a 100%-off forever coupon to a test customer, then add a company to bump their tier. ✓ Expect: tier changes, monthly stays $0, and no onboarding-delta invoice item is created (the app skips it for discounted customers).
  • [ ] 12.7 Repeating discount + growth: a 50%-off-for-3-months customer who grows → the 50% off now applies to the new tier's price for the remaining months, then reverts to the full new-tier rate. ✓ Expect: discount persists on the higher tier (use a Stripe test clock to fast-forward past the 3 months).

Step 13 — Scheduled reports cron (terminal)

  • [ ] 13.1 In PowerShell: npx wrangler tail qbtime-cron-staging. Wait for the next :00/:15/:30/:45. ✓ Expect: a line "*/15 * * * *" @ ... - Ok.
  • [ ] 13.2 Direct test of the app endpoint (PowerShell):
    Invoke-WebRequest -Uri "https://staging.qbtime.r2d2dev.com/api/v1/internal/run-due-reports" `
      -Method POST -Headers @{ "X-Internal-Secret" = "<staging INTERNAL_TASK_SECRET>" } |
      Select-Object -ExpandProperty Content
    
    ✓ Expect: 200 + a {evaluated,due,sent,skipped,failed} summary. A wrong secret → 403.
  • [ ] 13.3 Set a scheduled report's time to the current 15-min window, wait for the cron. ✓ Expect: the email arrives; re-firing does not double-send.

Step 14 — Platform / DevOps console (DevOps account)

  • [ ] 14.1 Sign in as the DevOps admin → /platform. ✓ Expect: Customers, DevOps accounts, Fleet health in the nav, plus a Docs ▾ dropdown (User Docs / Ops Docs) and a light/dark toggle (moon/sun icon) in the header.
  • [ ] 14.1a Click Docs ▾ → both User Docs ↗ and Ops Docs ↗ open in a new tab. Click the moon/sun icon → the theme flips and persists on reload.
  • [ ] 14.2 Customers: create a customer; click View as to impersonate. ✓ Expect: an amber "Impersonating…" banner; Stop ends it. Both are logged.
  • [ ] 14.3 DevOps accounts (Global Admin only): create a DevOps account. ✓ Expect: you cannot disable the last Global Admin.
  • [ ] 14.4 Fleet health: open it. ✓ Expect: a row per company across all customers — connection, token state, last run, 7-day failures.
  • [ ] 14.5 Isolation: sign in as a customer account and try to open /platform. ✓ Expect: you're redirected to /app (blocked server-side).

Step 15 — Security spot-checks

  • [ ] 15.1 IDOR: as a customer admin of company A, try to load company B's data by editing the companyId in a URL/request. ✓ Expect: 403.
  • [ ] 15.2 Audit chain: as DevOps, hit GET /api/v1/platform/verify-audit. ✓ Expect: { ok: true }.
  • [ ] 15.3 Confirm a saved QBT client secret is never shown back (Companies page shows it masked), and no secrets appear in browser devtools network responses.

Go-live sign-off

When every box above is ticked on staging with test data, you're ready to:

  1. Switch Stripe to live mode (live keys in the production Cloudflare env only).
  2. Run Steps 1–15 again on production with a real (small) transaction you refund, or with a live promo code that makes the first charge trivial.
  3. Enable the QBT Approvals Add-On on the real customer's QBT account.
  4. Hand the customer the User Guide (docs.qbtime.r2d2dev.com).
Tester Date Environment Result (pass/fail + notes)
staging
production