Skip to content

QA Testing Plan: Blog

This document covers QA test cases for the Blog business app located at /business/apps/blog. The app supports creating and editing articles with rich content, cover images, categories, tags, publish/draft lifecycle, and URL-based status filtering.

RoutePurpose
/business/apps/blogArticle list with status filter tabs and category display
/business/apps/blog/newCreate article form (superforms + createArticleSchema)
/business/apps/blog/[id]Article detail with publish, unpublish, and delete actions
/business/apps/blog/categoriesCategory CRUD (create, update, delete)
RouteActionMethodKey Fields
/business/apps/blog/newdefaultPOSTtitle, excerpt, content, cover_image_url, category_id, is_featured, allow_comments, tags
/business/apps/blog/[id]publishPOST(none)
/business/apps/blog/[id]unpublishPOST(none)
/business/apps/blog/[id]deletePOST(none)
/business/apps/blog/categoriescreatePOSTname, description (via createCategorySchema)
/business/apps/blog/categoriesupdatePOSTid, name, description
/business/apps/blog/categoriesdeletePOSTid

Test IDDescriptionPreconditionsStepsExpected ResultPriority
BLOG-001Article list loads for authenticated userUser is logged in with articles1. Navigate to /business/apps/blogArticle list is displayed with title, cover image, category name, date, and status badge.P0
BLOG-002Empty state when no articlesUser is logged in with no articles1. Navigate to /business/apps/blogEmpty state “No articles found.” with CTA “Write your first article”.P1
BLOG-003Unauthenticated user gets empty dataUser is not logged in1. Navigate to /business/apps/blogPage loads with empty articles, categories, and empty filters. No crash.P1
BLOG-004Status filter: All (default)User has draft and published articles1. Navigate to /business/apps/blog (no query params)All articles are shown. “All” tab is highlighted.P0
BLOG-005Status filter: Draft via URLUser has draft articles1. Navigate to /business/apps/blog?status=draftOnly draft articles are shown. “Draft” tab is highlighted.P0
BLOG-006Status filter: Published via URLUser has published articles1. Navigate to /business/apps/blog?status=publishedOnly published articles are shown. “Published” tab is highlighted.P0
BLOG-007Status filter tabs update URLUser is logged in1. Click “Draft” tab 2. Click “Published” tab 3. Click “All” tabURL updates to ?status=draft, ?status=published, and clears the param respectively. Uses replaceState.P0
BLOG-008Category name displays from category mapArticles have category_id set1. View article listCategory name is resolved from the category map. Articles without category show “Uncategorized”.P1
BLOG-009Status badges render correctlyDraft and published articles exist1. View article listdraft = secondary badge, published = default badge.P2
BLOG-010Cover image displays when availableArticle has cover_image_url1. View article listCover image thumbnail renders as 10x10 rounded image.P2
BLOG-011Placeholder icon when no cover imageArticle has no cover_image_url1. View article listArticleIcon placeholder renders in a muted background.P2
Test IDDescriptionPreconditionsStepsExpected ResultPriority
BLOG-020Create article with required fieldsUser is logged in1. Navigate to /business/apps/blog/new 2. Fill title 3. SubmitArticle is created. User is redirected to /business/apps/blog/{new_id}?new=1.P0
BLOG-021Create article with all fieldsUser is logged in1. Fill title, excerpt, content, cover_image_url, category_id, is_featured, allow_comments, tags 2. SubmitArticle is created with all fields persisted.P0
BLOG-022Validation: empty title rejectedUser is logged in1. Leave title blank 2. SubmitForm returns 400 with error “Title is required”.P0
BLOG-023Validation: title exceeds 255 charactersUser is logged in1. Enter title with 256+ characters 2. SubmitForm returns 400 with max length error.P1
BLOG-024Validation: excerpt exceeds 500 charactersUser is logged in1. Enter excerpt with 501+ characters 2. SubmitForm returns 400 with max length error.P1
BLOG-025Tags array persists correctlyUser is logged in1. Provide tags as an array of strings 2. SubmitArticle is created with tags stored.P1
BLOG-026is_featured boolean persistsUser is logged in1. Set is_featured: true 2. SubmitArticle is created with is_featured: true.P2
BLOG-027allow_comments boolean persistsUser is logged in1. Set allow_comments: false 2. SubmitArticle is created with allow_comments: false.P2
BLOG-028Categories loaded for selection on create pageUser is logged in with categories1. Navigate to /business/apps/blog/newcategories array is populated for the category dropdown.P1
BLOG-029Server error returns message to formUser is logged in, service throws1. Trigger server error during creationForm returns 500 with error message via superforms.P1
BLOG-030Unauthenticated user redirected from create pageUser is not logged in1. Navigate to /business/apps/blog/newUser is redirected to /login.P0
Test IDDescriptionPreconditionsStepsExpected ResultPriority
BLOG-040Load article detail pageUser is the author1. Navigate to /business/apps/blog/{id}Article data loads with categories for editing.P0
BLOG-041404 for non-existent articleUser is logged in1. Navigate to /business/apps/blog/{invalid_id}404 error “Article not found” is returned.P0
BLOG-042403 for article owned by another userUser is not the article author1. Navigate to /business/apps/blog/{other_user_article}403 Forbidden error is returned.P0
BLOG-043Publish a draft articleUser is the author of a draft article1. Submit the publish actionReturns { published: true }. Article status updates to “published”.P0
BLOG-044Unpublish a published articleUser is the author of a published article1. Submit the unpublish actionReturns { unpublished: true }. Article status reverts to “draft”.P0
BLOG-045Delete an articleUser is the author1. Submit the delete actionArticle is deleted. User is redirected to /business/apps/blog.P0
BLOG-046Publish action handles server errorUser is the author, service throws1. Trigger server error during publishReturns 500 with error message “Failed to publish”.P1
BLOG-047Unpublish action handles server errorUser is the author, service throws1. Trigger server error during unpublishReturns 500 with error message “Failed to unpublish”.P1
BLOG-048Delete action handles server errorUser is the author, service throws1. Trigger server error during deleteReturns 500 with error message “Failed to delete”.P1
Test IDDescriptionPreconditionsStepsExpected ResultPriority
BLOG-060Categories page loads with list and formUser is logged in1. Navigate to /business/apps/blog/categoriesCategory list and create form are displayed.P0
BLOG-061Create category with valid dataUser is logged in1. Fill name and optional description 2. Submit create actionCategory is created. Success message “Category created!” is returned.P0
BLOG-062Create category validation failureUser is logged in1. Submit create with invalid data per createCategorySchemaReturns 400 with form errors.P1
BLOG-063Create category handles server errorUser is logged in, service throws1. Trigger server error during creationReturns 500 with error message via superforms.P1
BLOG-064Update category name and descriptionUser is logged in with categories1. Submit update with id, name, optional descriptionCategory is updated. Returns { updated: true }.P0
BLOG-065Update category fails without id or nameUser is logged in1. Submit update without id or nameReturns 400 “Missing fields”.P1
BLOG-066Update category handles server errorUser is logged in, service throws1. Trigger server errorReturns 500 with error message.P1
BLOG-067Delete category by IDUser is logged in with categories1. Submit delete with idCategory is deleted. Returns { deleted: true }.P0
BLOG-068Delete category fails without idUser is logged in1. Submit delete without idReturns 400 “Missing category ID”.P1
BLOG-069Delete category handles server errorUser is logged in, service throws1. Trigger server errorReturns 500 with error message.P1
BLOG-070Create category requires authenticationUser is not logged in1. POST to ?/createReturns 401 fail.P1