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.
- In a browser, go to https://quickbooks.intuit.com/time-tracking/ (QuickBooks Time). Click Free Trial (or Try it free).
- 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."
- 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.
- Add a schedule for a couple of them today (Schedule → New event) so the attendance report has data to compute.
- 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.) - 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¶
- Log in to https://dashboard.stripe.com. Top-left, make sure the Test mode toggle is ON (it says "Test mode" in orange).
- 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. - 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. - 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¶
- The app is at https://staging.qbtime.r2d2dev.com.
- You need the staging
SETUP_BOOTSTRAP_SECRETvalue (from the password manager / Cloudflare dashboard) to create the first admin in Step 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=successin 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_SECRETfor staging (so/setupcan'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.csvdownloads 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 2 → approved.
- [ ] 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):
✓ Expect: 200 + a
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{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
companyIdin 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:
- Switch Stripe to live mode (live keys in the production Cloudflare env only).
- 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.
- Enable the QBT Approvals Add-On on the real customer's QBT account.
- Hand the customer the User Guide (docs.qbtime.r2d2dev.com).
| Tester | Date | Environment | Result (pass/fail + notes) |
|---|---|---|---|
| staging | |||
| production |