Skip to content

QA Testing Plan: Subscriptions

This document covers QA test cases for the Subscriptions business app located at /business/apps/subscriptions. The app supports creating subscription plans with monthly/quarterly/yearly intervals, managing features, linking courses for access gating, Stripe price integration, and subscriber tracking.

RoutePurpose
/business/apps/subscriptionsDashboard with stats and all plans list
/business/apps/subscriptions/newCreate plan form (superforms + createPlanSchema)
/business/apps/subscriptions/[id]Plan detail with publish, delete, course management, and subscribers list
RouteActionMethodKey Fields
/business/apps/subscriptions/newdefaultPOSTtitle, description, price, interval, features, stripe_price_id
/business/apps/subscriptions/[id]publishPOST(none)
/business/apps/subscriptions/[id]deletePOST(none)
/business/apps/subscriptions/[id]add-coursePOSTcourse_id
/business/apps/subscriptions/[id]remove-coursePOSTcourse_id

Test IDDescriptionPreconditionsStepsExpected ResultPriority
SUB-001Dashboard loads with instructor statsUser is logged in with plans1. Navigate to /business/apps/subscriptionsStats cards display: Total Plans, Published, Subscribers, Revenue. Plan list shows all plans.P0
SUB-002Dashboard shows empty state for new userUser is logged in with no plans1. Navigate to /business/apps/subscriptionsStats section is hidden. Empty state “No plans yet” is displayed.P1
SUB-003Unauthenticated user sees null statsUser is not logged in1. Navigate to /business/apps/subscriptionsPage loads with stats: null and empty plans. No crash.P1
SUB-004”New Plan” button navigates correctlyUser is logged in1. Click “New Plan” buttonNavigates to /business/apps/subscriptions/new.P0
SUB-005Plan links navigate to detail pageUser has plans1. Click a plan in the listNavigates to /business/apps/subscriptions/{id}.P1
SUB-006Plan interval displays correct abbreviationPlans with different intervals exist1. View plan listMonthly shows “/mo”, quarterly shows “/qtr”, yearly shows “/yr”.P2
SUB-007Plan status badges render correctlyPlans with draft, published, inactive statuses exist1. View plan listdraft = secondary, published = default, inactive = destructive.P2
Test IDDescriptionPreconditionsStepsExpected ResultPriority
SUB-010Create plan with required fieldsUser is logged in1. Navigate to /business/apps/subscriptions/new 2. Fill title 3. SubmitPlan is created. User is redirected to /business/apps/subscriptions/{new_id}.P0
SUB-011Create plan with all fieldsUser is logged in1. Fill title, description, price, interval, features, stripe_price_id 2. SubmitPlan is created with all fields persisted.P0
SUB-012Validation: empty title rejectedUser is logged in1. Leave title blank 2. SubmitForm returns 400 with error “Title is required”.P0
SUB-013Validation: title exceeds 255 charactersUser is logged in1. Enter title with 256+ characters 2. SubmitForm returns 400 with max length error.P1
SUB-014Validation: negative price rejectedUser is logged in1. Enter price as -5 2. SubmitForm returns 400 with error “Price must be positive”.P1
SUB-015Interval: monthlyUser is logged in1. Select interval “monthly” 2. SubmitPlan is created with interval: "monthly".P1
SUB-016Interval: quarterlyUser is logged in1. Select interval “quarterly” 2. SubmitPlan is created with interval: "quarterly".P1
SUB-017Interval: yearlyUser is logged in1. Select interval “yearly” 2. SubmitPlan is created with interval: "yearly".P1
SUB-018Features array persists correctlyUser is logged in1. Provide a features array 2. SubmitPlan is created with features stored.P1
SUB-019Stripe price ID persists correctlyUser is logged in1. Provide stripe_price_id 2. SubmitPlan is created with Stripe price ID linked.P1
SUB-020Unauthenticated user redirected from create pageUser is not logged in1. Navigate to /business/apps/subscriptions/newUser is redirected to /login.P0
Test IDDescriptionPreconditionsStepsExpected ResultPriority
SUB-030Load plan detail pageUser owns the plan1. Navigate to /business/apps/subscriptions/{id}Plan data loads with linked courses, subscribers list, and instructor courses for selection.P0
SUB-031404 for non-existent planUser is logged in1. Navigate to /business/apps/subscriptions/{invalid_id}404 error “Plan not found” is returned.P0
SUB-032403 for plan owned by another instructorUser does not own the plan1. Navigate to /business/apps/subscriptions/{other_instructor_plan}403 Forbidden error is returned.P0
SUB-033Publish a draft planUser owns a draft plan1. Submit the publish actionReturns { published: true }. Plan status updates to “published”.P0
SUB-034Delete a planUser owns a plan1. Submit the delete actionPlan is deleted. User is redirected to /business/apps/subscriptions.P0
SUB-035Subscribers list displays on detail pageUser owns a plan with subscribers1. Load the plan detail pageSubscribers list is populated with subscriber data.P1
Test IDDescriptionPreconditionsStepsExpected ResultPriority
SUB-040Add course to planUser owns the plan and has courses1. Submit add-course with course_idCourse is linked to the plan. Returns { courseAdded: true }.P0
SUB-041Add course fails without course_idUser is logged in1. Submit add-course without course_idReturns 400 “Missing course ID”.P1
SUB-042Add course handles server errorUser is logged in, service throws1. Trigger server errorReturns 500 “Failed to add course”.P1
SUB-043Remove course from planUser owns the plan with linked courses1. Submit remove-course with course_idCourse is unlinked from the plan. Returns { courseRemoved: true }.P0
SUB-044Remove course fails without course_idUser is logged in1. Submit remove-course without course_idReturns 400 “Missing course ID”.P1
SUB-045Remove course handles server errorUser is logged in, service throws1. Trigger server errorReturns 500 “Failed to remove course”.P1
SUB-046Instructor courses loaded for selectionUser owns the plan and has instructor courses1. Load plan detail pageinstructorCourses array is populated, enabling course selection dropdown.P1
Test IDDescriptionPreconditionsStepsExpected ResultPriority
SUB-050Plan with stripe_price_id links to StripePlan has stripe_price_id set1. Create or view plan with Stripe price IDStripe price ID is stored and available for checkout integration.P0
SUB-051Plan without stripe_price_id still functionsPlan has no stripe_price_id1. Create plan without Stripe price IDPlan is created successfully. Price ID field is null/undefined.P1