Skip to content

QA Testing Plan: Products

This document covers QA test cases for the Products business app located at /business/apps/products. The app supports creating and managing digital and physical products with media uploads, pricing, specifications, and publish/draft lifecycle.

RoutePurpose
/business/apps/productsDashboard with stats and recent products list
/business/apps/products/newCreate product form (superforms + createProductSchema)
/business/apps/products/[id]Product detail with actions: publish, delete, add/remove media, add/remove files, add/remove specs
RouteActionMethodKey Fields
/business/apps/products/newdefaultPOSTtitle, description, short_description, thumbnail_url, price, compare_price, type
/business/apps/products/[id]publishPOST(none)
/business/apps/products/[id]deletePOST(none)
/business/apps/products/[id]add-mediaPOSTurl, type (image/video), product_id
/business/apps/products/[id]remove-mediaPOSTmedia_id
/business/apps/products/[id]add-filePOSTtitle, file_path, product_id
/business/apps/products/[id]remove-filePOSTfile_id
/business/apps/products/[id]add-specPOSTkey, value, product_id
/business/apps/products/[id]remove-specPOSTspec_id

Test IDDescriptionPreconditionsStepsExpected ResultPriority
PROD-001Dashboard loads with stats for authenticated userUser is logged in and has products1. Navigate to /business/apps/productsStats cards display: Total Products, Published, Total Sales, Revenue. Recent products list shows up to 5 items.P0
PROD-002Dashboard shows empty state for new userUser is logged in with no products1. Navigate to /business/apps/productsStats section is hidden. Empty state message “No products yet” is displayed.P1
PROD-003Unauthenticated user sees null statsUser is not logged in1. Navigate to /business/apps/productsPage loads with stats: null and empty recentProducts array. No crash.P1
PROD-004”New Product” button navigates correctlyUser is logged in1. Click “New Product” buttonBrowser navigates to /business/apps/products/new.P0
PROD-005Recent product links navigate to detail pageUser has at least one product1. Click a product in the recent products listBrowser navigates to /business/apps/products/{id}.P1
PROD-006Product status badges render correct variantsUser has products with draft, published, and inactive statuses1. View recent products listDraft shows “secondary” badge, published shows “default”, inactive shows “destructive”.P2
Test IDDescriptionPreconditionsStepsExpected ResultPriority
PROD-010Create product with all required fieldsUser is logged in1. Navigate to /business/apps/products/new 2. Fill in title (required) 3. Submit formProduct is created. User is redirected to /business/apps/products/{new_id}.P0
PROD-011Create product with all optional fieldsUser is logged in1. Navigate to /business/apps/products/new 2. Fill title, description, short_description, thumbnail_url, price, compare_price, typeProduct is created with all fields persisted. Redirect to detail page.P0
PROD-012Validation: empty title rejectedUser is logged in1. Navigate to /business/apps/products/new 2. Leave title blank 3. SubmitForm returns 400 with validation error “Title is required”.P0
PROD-013Validation: title exceeds 255 charactersUser is logged in1. Enter a title with 256+ characters 2. SubmitForm returns 400 with validation error for max length.P1
PROD-014Validation: short_description exceeds 500 charactersUser is logged in1. Enter short_description with 501+ characters 2. SubmitForm returns 400 with validation error for max length.P1
PROD-015Validation: negative price rejectedUser is logged in1. Enter price as -5 2. SubmitForm returns 400 with error “Price must be positive”.P1
PROD-016Validation: negative compare_price rejectedUser is logged in1. Enter compare_price as -1 2. SubmitForm returns 400 with error “Compare price must be positive”.P1
PROD-017Product type defaults correctlyUser is logged in1. Create product without specifying typeProduct is created with the schema default for type (optional/undefined).P2
PROD-018Product type: digitalUser is logged in1. Select type “digital” 2. SubmitProduct is created with type: "digital".P1
PROD-019Product type: physicalUser is logged in1. Select type “physical” 2. SubmitProduct is created with type: "physical".P1
PROD-020Unauthenticated user redirected from create pageUser is not logged in1. Navigate to /business/apps/products/newUser is redirected to /login.P0
Test IDDescriptionPreconditionsStepsExpected ResultPriority
PROD-030Load product detail pageUser owns the product1. Navigate to /business/apps/products/{id}Product data loads with details and associated orders.P0
PROD-031404 for non-existent productUser is logged in1. Navigate to /business/apps/products/{invalid_id}404 error “Product not found” is returned.P0
PROD-032403 for product owned by another userUser is logged in but does not own the product1. Navigate to /business/apps/products/{other_user_product_id}403 Forbidden error is returned.P0
PROD-033Publish a draft productUser owns a draft product1. Submit the publish action on the detail pageAction returns { published: true }. Product status updates to “published”.P0
PROD-034Delete a productUser owns a product1. Submit the delete action on the detail pageProduct is deleted. User is redirected to /business/apps/products.P0
PROD-035Delete action requires authenticationUser is not logged in1. POST to ?/deleteReturns 401 fail.P1
Test IDDescriptionPreconditionsStepsExpected ResultPriority
PROD-040Add image media to productUser owns a product1. Submit add-media with url, type: "image", product_idMedia is added. Returns { mediaAdded: true }.P0
PROD-041Add video media to productUser owns a product1. Submit add-media with url, type: "video", product_idMedia is added. Returns { mediaAdded: true }.P1
PROD-042Add media fails without URLUser owns a product1. Submit add-media without urlReturns 400 “Missing URL or product ID”.P1
PROD-043Add media fails without product_idUser owns a product1. Submit add-media without product_idReturns 400 “Missing URL or product ID”.P1
PROD-044Remove media by IDUser owns a product with media1. Submit remove-media with media_idMedia is removed. Returns { mediaRemoved: true }.P0
PROD-045Remove media fails without media_idUser is logged in1. Submit remove-media without media_idReturns 400 “Missing media ID”.P1
Test IDDescriptionPreconditionsStepsExpected ResultPriority
PROD-050Add file to productUser owns a product1. Submit add-file with title, file_path, product_idFile is added. Returns { fileAdded: true }.P0
PROD-051Add file fails with missing fieldsUser is logged in1. Submit add-file without title or file_path or product_idReturns 400 “Missing required fields”.P1
PROD-052Remove file by IDUser owns a product with files1. Submit remove-file with file_idFile is removed. Returns { fileRemoved: true }.P0
PROD-053Remove file fails without file_idUser is logged in1. Submit remove-file without file_idReturns 400 “Missing file ID”.P1
Test IDDescriptionPreconditionsStepsExpected ResultPriority
PROD-060Add specification to productUser owns a product1. Submit add-spec with key, value, product_idSpecification is added. Returns { specAdded: true }.P0
PROD-061Add spec fails with missing fieldsUser is logged in1. Submit add-spec without key or value or product_idReturns 400 “Missing required fields”.P1
PROD-062Remove specification by IDUser owns a product with specs1. Submit remove-spec with spec_idSpecification is removed. Returns { specRemoved: true }.P0
PROD-063Remove spec fails without spec_idUser is logged in1. Submit remove-spec without spec_idReturns 400 “Missing specification ID”.P1