This is the interactive UAT companion for Teboho, who is running all Milestone 1 tests solo. Rather than coordinating a team, Teboho logs in and out of each pre-seeded system account in sequence, covering every user journey from one workstation.
Use the Test Scripts tab for step-by-step instructions per role. Use Feature Matrix to track completion. Log every issue in Bug Log.
All accounts below are pre-seeded. Teboho also creates one personal account on Day 1 to test the registration and email verification flow.
| Role | Login Email | Password | Notes |
|---|---|---|---|
| super_admin | superadmin@jtg.org.za | password123 | Pre-seeded. Audit log, user management, sign-off. |
| programme_admin | programmeadmin@jtg.org.za | password123 | Pre-seeded. All programme admin steps. |
| reviewer | reviewer@jtg.org.za | password123 | Pre-seeded. John Reviewer. |
| verif. officer | verifier@jtg.org.za | password123 | Pre-seeded. Sarah Verifier. |
| sponsor | sponsor@jtg.org.za | password123 | Pre-seeded. ABC Corporation. |
| learner (eligible) | thabo@example.com | password123 | Pre-seeded. Thabo Mokoena, UJ, Computer Science, 3rd Year. |
| learner (ineligible) | lerato@example.com | password123 | Pre-seeded. Lerato Dlamini, TUT, Electrical Engineering, 2nd Year. |
| your own account | Your real email | Your choice | Self-register on Day 1 to test registration + email verification. |
Before Day 1 role-specific testing begins, register a personal account. This tests features that cannot be tested with pre-seeded accounts: the registration form, email verification flow, and super admin role-assignment workflow.
superadmin@jtg.org.za/password123superadmin@jtg.org.zapassword123superadmin@jtg.org.za/password123superadmin@jtg.org.za/password123programmeadmin@jtg.org.zapassword123thabo@example.compassword123lerato@example.compassword123verifier@jtg.org.zapassword123reviewer@jtg.org.zapassword123sponsor@jtg.org.zapassword123| ✓ | Feature | Result / Notes |
|---|---|---|
| Self-registration form loads and accepts valid input | ||
| Registration rejected if email already in use | ||
| Verification email received within 2 minutes of registration | ||
| Verification link activates the account | ||
| Login with unverified account is blocked | ||
| Super admin sees self-registered accounts in Admin → Users | ||
| Role assignment takes effect after next login | ||
| Portal access control enforced — cannot access other roles' portals |
| ✓ | Feature | Result / Notes |
|---|---|---|
| Create programme with name, deadline, fund amount, eligibility restriction | ||
| Create universal programme with no eligibility filter | ||
| Form builder: text, file upload, and dropdown field types added | ||
| Conditional logic: field shows/hides based on dropdown value | ||
| Form publishes successfully — status changes to "Published" | ||
| Document checklist: required document types configured | ||
| Notification toggles: per-programme on/off saves correctly | ||
| Scoring rubric: 3+ criteria with weights summing to 100% | ||
| Auto-assignment rule fires when application moves to approved_for_review | ||
| Manual reviewer assignment works without triggering auto-rule | ||
| Contract template: merge fields save and preview correctly |
| ✓ | Feature | Result / Notes |
|---|---|---|
| Eligible learner sees restricted programme in listing | ||
| Ineligible learner does NOT see restricted programme (or is blocked on apply) | ||
| Both learners see universal programme | ||
| POPIA consent checkbox saves and enables applications | ||
| Application form with conditional logic works correctly | ||
| Save as draft preserves application state across navigation and logout | ||
| Submit application: status changes, ApplicationSubmitted email fires | ||
| Upload ID Document — appears in checklist as Pending | ||
| Upload Academic Transcript — appears in checklist as Pending | ||
| Upload Proof of Income — checklist shows 3/3 submitted | ||
| Application status tracker shows correct timeline of events | ||
| In-app notifications appear and can be marked as read |
| ✓ | Feature | Result / Notes |
|---|---|---|
| Verification dashboard lists applications with pending documents | ||
| Verify document — status updates to Verified, no errors | ||
| Reject document with reason — rejection reason saved | ||
| Rejection reason visible to learner in their portal | ||
| All three documents verified → application automatically moves to under_review | ||
| Verification queue updates after actions (verified items leave pending list) |
| ✓ | Feature | Result / Notes |
|---|---|---|
| Reviewer dashboard loads with assigned applications visible | ||
| COI declaration banner visible before any scoring is possible | ||
| "No conflict" declaration allows access to scoring screen | ||
| Rubric scoring inputs work; weighted total calculated correctly | ||
| Submit scores — scores locked, editing not possible after submission | ||
| Conflict declaration recuses reviewer from application | ||
| Recused application removed from active scoring queue | ||
| Admin panel shows recused status for conflicted reviewer | ||
| Committee recommendation saved and visible on application |
| ✓ | Feature | Result / Notes |
|---|---|---|
| Bulk status change: multiple applications update simultaneously | ||
| Each affected learner receives a StatusChanged notification | ||
| Shortlist ranking shows applications ordered by weighted score | ||
| Bulk shortlist action moves selected applications to "shortlisted" | ||
| Award offer created — AwardOffered email fires to learner | ||
| Offer letter PDF downloads with real merged data (no placeholders) | ||
| Accept Award 1: status updates, ContractReady email fires | ||
| Decline Award 2: status updates to "declined", cannot be reversed | ||
| Declining award triggers waitlist promotion automatically | ||
| Waitlisted learner receives WaitlistPromoted email | ||
| Waitlist admin panel shows promotion timestamp |
| ✓ | Feature | Result / Notes |
|---|---|---|
| Contract generated with correctly merged data (name, amount, programme) | ||
| Sign contract: timestamp and IP address recorded | ||
| Download signed contract PDF successfully | ||
| Signed contract shows "Signed" status with correct timestamp | ||
| Contract version history: generated → signed, both timestamped | ||
| Admin contract search finds signed contract by learner name |
| ✓ | Feature | Result / Notes |
|---|---|---|
| Data access request submitted with reference number | ||
| DSR status notification received when admin acknowledges | ||
| Data export JSON contains real profile and application data | ||
| Erasure request submitted with reference number | ||
| Erasure executed: account anonymised, login fails | ||
| Erasure report PDF written to storage | ||
| Retention policy configuration area present and saves changes | ||
| php artisan reminders:deadline --dry-run: lists correct applications, no emails sent | ||
| php artisan reminders:deadline sends emails on first run | ||
| Running reminder command twice sends no duplicate emails (idempotency) |
| ✓ | Feature | Result / Notes |
|---|---|---|
| Sponsor dashboard shows linked programme with application counts | ||
| Application detail visible without restricted private learner data | ||
| Awards section shows issued awards with correct statuses | ||
| Sponsor cannot access admin, learner, or reviewer portal pages |
| ✓ | Feature | Result / Notes |
|---|---|---|
| Audit log accessible to super admin | ||
| Log entries filterable by date | ||
| Bulk shortlist entry present with correct user and timestamp | ||
| Erasure entry present with correct user and timestamp | ||
| Reviewer assignment entry present with correct user and timestamp |
Log every issue found during testing. A bug that is not logged does not exist. Add rows using the button below. Triage all items on Day 4.
| # | Day | Role | Step ref | What happened | Expected behaviour | Severity | Status | Screenshot? |
|---|---|---|---|---|---|---|---|---|
| 1 | ||||||||
| 2 | ||||||||
| 3 | ||||||||
| 4 | ||||||||
| 5 | ||||||||
| 6 | ||||||||
| 7 | ||||||||
| 8 | ||||||||
| 9 | ||||||||
| 10 | ||||||||
| 11 | ||||||||
| 12 | ||||||||
| 13 | ||||||||
| 14 | ||||||||
| 15 | ||||||||
| 16 | ||||||||
| 17 | ||||||||
| 18 | ||||||||
| 19 | ||||||||
| 20 |
| ✓ | Prerequisite | How to verify |
|---|---|---|
| ☐ | All migrations run clean against a fresh database | php artisan migrate --fresh |
| ☐ | Scheduler cron active on UAT server | * * * * * php artisan schedule:run |
| ☐ | All 8 seeded accounts active and accessible | Log in with each credential set in the accounts table |
| ☐ | Email delivery configured to real inboxes | Register a test account; verify email lands in real inbox within 2 minutes |
| ☐ | Storage symlink created | php artisan storage:link |
| ☐ | File permissions on storage/app/public allow web writes | Upload a test PDF; confirm URL accessible in browser |
| ☐ | Database seeded with learner profiles, sponsor, and contract template | php artisan db:seed |
| ☐ | Queue driver decision confirmed | QUEUE_CONNECTION=sync or queue:work running |
| ☐ | UAT environment is NOT the production database | Confirm DB_DATABASE in .env points to UAT schema |
| Command | When to run |
|---|---|
php artisan migrate --fresh --seed | Before Day 1. Resets UAT database to clean seeded state. |
php artisan storage:link | Once, before Day 1. Required for document and offer letter file serving. |
php artisan queue:work | Run persistently if using database queue driver. Alternatively set QUEUE_CONNECTION=sync. |
php artisan reminders:deadline --dry-run | Day 4 preview — lists applications without sending emails. |
php artisan reminders:deadline | Day 4 — send actual reminders. Run twice to confirm no duplicate sends. |