Bundles - QA Test Plan
Overview
Section titled “Overview”The Bundles app allows instructors to package multiple courses together and offer them at a discounted bundle price. It depends on the Courses app for course data. Routes are under /business/apps/bundles/.
Bundle Statuses
Section titled “Bundle Statuses”draft— Newly created, not yet publishedpublished— Visible and purchasable by studentsinactive— Taken down from the storefront
1. Dashboard / Landing Page
Section titled “1. Dashboard / Landing Page”| ID | Description | Preconditions | Steps | Expected Result | Priority |
|---|---|---|---|---|---|
| BN-001 | Dashboard loads with stats | User is logged in as instructor | Navigate to /business/apps/bundles | Page shows stat cards: Total Bundles, Published, Total Sales, Revenue (USD formatted) | P0 |
| BN-002 | Bundle list renders | Bundles exist | View dashboard | Each bundle row shows thumbnail (or placeholder icon), title, course count, sales count, date, price, and status badge | P0 |
| BN-003 | Status badges render correctly | Bundles with draft/published/inactive statuses | View list | Draft = secondary, Published = default, Inactive = destructive | P1 |
| BN-004 | Empty state when no bundles | No bundles exist | View dashboard | ”No bundles yet” message shown | P1 |
| BN-005 | New Bundle button links correctly | User is logged in | Click “New Bundle” button | Navigates to /business/apps/bundles/new | P0 |
| BN-006 | Bundle row links to detail | Bundles exist | Click on a bundle row | Navigates to /business/apps/bundles/{id} | P0 |
| BN-007 | Revenue displays correct currency format | Stats have revenue data | View Revenue stat card | Amount formatted as USD (e.g., “$1,250.00”) | P1 |
2. Create Bundle
Section titled “2. Create Bundle”| ID | Description | Preconditions | Steps | Expected Result | Priority |
|---|---|---|---|---|---|
| BN-010 | Create page loads with form | User is logged in | Navigate to /business/apps/bundles/new | Form shows Title, Description, Price, Compare Price, and Thumbnail URL fields | P0 |
| BN-011 | Create bundle with valid input | User is logged in | 1. Enter title “Complete Web Dev Bundle” 2. Enter description 3. Set price to 49.99 4. Click “Create Bundle” | Bundle is created; user redirected to /business/apps/bundles/{id}?new=1 | P0 |
| BN-012 | Title is required | User is logged in | Leave title empty, submit | Validation error on title field | P0 |
| BN-013 | Price is required and numeric | User is logged in | Leave price empty or enter non-numeric, submit | Validation error on price field | P0 |
| BN-014 | Compare price is optional | User is logged in | Fill title and price, leave compare price empty, submit | Bundle created successfully without compare price | P1 |
| BN-015 | Thumbnail URL is optional | User is logged in | Fill required fields, leave thumbnail empty, submit | Bundle created with placeholder icon in list | P1 |
| BN-016 | Cancel returns to dashboard | User is on create page | Click “Cancel” | Navigates to /business/apps/bundles | P2 |
| BN-017 | Submit shows loading state | User fills form | Click “Create Bundle” | Button shows “Creating…” with spinner; button disabled | P1 |
| BN-018 | Server error shows toast | Server returns 500 | Submit form (simulated error) | Error toast displays server error message | P1 |
3. Bundle Detail Page
Section titled “3. Bundle Detail Page”| ID | Description | Preconditions | Steps | Expected Result | Priority |
|---|---|---|---|---|---|
| BN-020 | Detail page loads for owner | Bundle exists, user is owner | Navigate to /business/apps/bundles/{id} | Page shows title, status badge, thumbnail, description, price, compare price (strikethrough), created date, stats, and included courses | P0 |
| BN-021 | New bundle toast on creation | Redirected with ?new=1 | Navigate with ?new=1 | Success toast “Bundle created!” appears; param is cleaned from URL | P1 |
| BN-022 | Price and compare price display | Bundle has both price and compare_price | View detail | Price shown in USD format; compare price shown with strikethrough | P0 |
| BN-023 | Sales stats display | Bundle has sales | View detail page | Total Sales count and Revenue stat cards render correctly | P1 |
| BN-024 | Edit button links correctly | Bundle detail loaded | Click “Edit” button | Navigates to /business/apps/bundles/{id}/edit | P0 |
4. Publish / Unpublish Lifecycle
Section titled “4. Publish / Unpublish Lifecycle”| ID | Description | Preconditions | Steps | Expected Result | Priority |
|---|---|---|---|---|---|
| BN-030 | Publish draft bundle | Bundle status is draft | Click “Publish” button | Status changes to published; success toast; page refreshes; button changes to “Unpublish” | P0 |
| BN-031 | Unpublish published bundle | Bundle status is published | Click “Unpublish” button | Status changes to draft/inactive; success toast; page refreshes; button changes to “Publish” | P0 |
| BN-032 | Publish shows loading spinner | User clicks Publish | Observe button | Spinner shown, button disabled during request | P2 |
| BN-033 | Publish failure shows toast | Server error | Click Publish (simulated failure) | Error toast “Failed to publish” | P1 |
5. Course Management (Courses App Dependency)
Section titled “5. Course Management (Courses App Dependency)”| ID | Description | Preconditions | Steps | Expected Result | Priority |
|---|---|---|---|---|---|
| BN-040 | Included courses section displays | Bundle has courses | View detail page | ”Included Courses” section shows courses with index number, thumbnail, title, type, and individual price | P0 |
| BN-041 | Add course via picker dialog | Instructor has courses not in bundle | 1. Click “Add Course” 2. Search or browse available courses 3. Click a course | Course is added to bundle; success toast; dialog closes; list refreshes | P0 |
| BN-042 | Course picker search filters results | Instructor has multiple courses | Open picker, type search term | Only courses matching the search term are shown | P1 |
| BN-043 | Already-included courses hidden from picker | Bundle has some courses | Open course picker | Courses already in the bundle are not listed in available courses | P0 |
| BN-044 | All courses in bundle message | All instructor courses are added | Open course picker with empty search | ”All your courses are already in this bundle” message shown | P1 |
| BN-045 | Remove course from bundle | Bundle has courses | Click trash icon on a course row | Course is removed; success toast; list refreshes | P0 |
| BN-046 | Add course shows loading state | User clicks a course in picker | Observe button/row | Spinner shown on the selected course row | P2 |
| BN-047 | Remove course shows loading state | User clicks remove | Observe trash button | Spinner replaces trash icon during request | P2 |
| BN-048 | Empty courses state | Bundle has no courses | View included courses section | ”No courses yet. Add courses to build your bundle.” dashed border message | P1 |
6. Edit Bundle
Section titled “6. Edit Bundle”| ID | Description | Preconditions | Steps | Expected Result | Priority |
|---|---|---|---|---|---|
| BN-050 | Edit page loads with current data | Bundle exists, user is owner | Navigate to /business/apps/bundles/{id}/edit | Form pre-filled with current title, description, price, compare price, and thumbnail URL | P0 |
| BN-051 | Update bundle details | User changes title and price | Edit fields and click “Save Changes” | Bundle is updated; success toast “Bundle updated!” | P0 |
| BN-052 | Update validation - title required | User clears title | Clear title field, submit | Validation error on title | P0 |
| BN-053 | Update compare price | User changes compare price | Set compare price to 99.99, save | Compare price updates and shows strikethrough on detail page | P1 |
| BN-054 | Cancel returns to detail page | User is on edit page | Click “Cancel” | Navigates back to /business/apps/bundles/{id} | P2 |
7. Delete Bundle
Section titled “7. Delete Bundle”| ID | Description | Preconditions | Steps | Expected Result | Priority |
|---|---|---|---|---|---|
| BN-060 | Delete bundle with confirmation | Bundle exists | 1. Click trash icon 2. Confirm in dialog | Bundle deleted; user redirected to /business/apps/bundles | P0 |
| BN-061 | Cancel delete dialog | Delete dialog shown | Click “Cancel” | Dialog closes; bundle remains | P2 |
| BN-062 | Delete shows loading state | User confirms delete | Observe dialog button | Spinner on delete button; button disabled | P2 |
| BN-063 | Delete failure shows toast | Server error | Confirm delete (simulated failure) | Error toast “Failed to delete bundle” | P1 |
8. Authorization & Error Handling
Section titled “8. Authorization & Error Handling”| ID | Description | Preconditions | Steps | Expected Result | Priority |
|---|---|---|---|---|---|
| BN-070 | Unauthenticated user redirected on create | User not logged in | Navigate to /business/apps/bundles/new | Redirected to /login | P0 |
| BN-071 | Non-owner gets 403 on detail | Logged in as different instructor | Navigate to another instructor’s bundle | 403 error thrown | P0 |
| BN-072 | Non-existent bundle returns 404 | Invalid bundle ID | Navigate to /business/apps/bundles/nonexistent | 404 “Bundle not found” error | P1 |
| BN-073 | Non-owner gets 403 on edit | Logged in as different instructor | Navigate to another instructor’s bundle edit page | 403 error thrown | P0 |