Add 4 new unit test suites for greenfield test plan coverage
Add 87 new tests (384 total) covering ValidationRules/ValidationError, PasswordResetViewModel navigation and client-side validation, WidgetAction Codable/Equatable/accessors, parseDate, and ThemeID enum properties. Updates greenfield CSV for AUTH-012/017/018, NOTIF-006/007, WID-003, THEME-002. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -10,13 +10,13 @@
|
||||
"AUTH-009","Authentication","Registration","Create account success then verify-email step","Manual + E2E UI","P0","iOS, Android, Web, Desktop","Unique email/username","Submit valid registration","Session established and verify-email screen appears","Existing email conflict","Register API auto-authenticates","Automate","🟢 testR103_successfulRegistrationTransitionsToVerificationGate"
|
||||
"AUTH-010","Authentication","Registration validation","Invalid email/password formats rejected","Manual + UI","P1","iOS, Android, Web, Desktop","No session","Try invalid email, short password, weak password","User-friendly validation errors","Unicode emails, long usernames","Validation rules are enforced consistently","Automate","🟢 test03_registrationWithEmptyFields | test04_registrationWithInvalidEmail | test06_registrationWithWeakPassword"
|
||||
"AUTH-011","Authentication","Email verification","Valid 6-digit code verifies account","Manual + E2E UI","P0","iOS, Android, Web, Desktop","Logged-in unverified user","Enter 6-digit numeric code","Account marked verified and app routes forward","Code already used","Code must be exactly 6 digits","Automate","🟢 testR105_validVerificationCodeTransitionsToMainApp | test07_successfulRegistrationAndVerification"
|
||||
"AUTH-012","Authentication","Email verification","Non-numeric/short/long code blocked","Manual + UI","P1","iOS, Android, Web, Desktop","On verify-email screen","Enter invalid codes","Verify action disabled or error shown","Pasted with spaces","Code input sanitizes to digits","Automate","🟢 testR107_invalidVerificationCodeShowsErrorAndStaysBlocked | testR109_verifyButtonDisabledForIncompleteCode | test10_verificationCodeFieldValidation"
|
||||
"AUTH-012","Authentication","Email verification","Non-numeric/short/long code blocked","Manual + UI","P1","iOS, Android, Web, Desktop","On verify-email screen","Enter invalid codes","Verify action disabled or error shown","Pasted with spaces","Code input sanitizes to digits","Automate","🟢 testR107_invalidVerificationCodeShowsErrorAndStaysBlocked | testR109_verifyButtonDisabledForIncompleteCode | test10_verificationCodeFieldValidation | emptyCodeReturnsRequired | wrongLengthReturnsInvalidCode | nonNumericCodeReturnsInvalidCode | validSixDigitCodeReturnsNil | customLengthFourDigitCode | customLengthWrongDigitCount (ValidationRulesTests)"
|
||||
"AUTH-013","Authentication","Logout","Logout clears token, user data, lookups, and returns to login","Manual + E2E UI","P0","iOS, Android, Web, Desktop","Logged in","Tap logout","Login shown; protected API calls fail without token","Logout API fails network-side","Client clears state even if API call fails","Automate","🟢 test06_logout | testR205_logoutFromMainAppReturnsToLoginRoot"
|
||||
"AUTH-014","Authentication","Forgot password","Request reset by email success path","Manual + E2E UI","P0","iOS, Android, Web, Desktop","Known account email","Submit forgot-password email","Success message and next step available","Unknown email behavior privacy-safe","Backend may still return generic success","Automate","🟢 test05_forgotPasswordNavigation | testF206_ForgotPasswordButtonIsAccessible | testF209_ForgotPasswordNavigatesToResetFlow"
|
||||
"AUTH-015","Authentication","Reset code verification","Verify reset code success path","Manual + E2E UI","P0","iOS, Android, Web, Desktop","Reset email submitted","Enter correct code","Reset-token available for password reset","Expired code","Code verification endpoint returns token","Automate","🟢 test03_verifyResetCodeSuccess"
|
||||
"AUTH-016","Authentication","Password reset","Reset password success with matching confirmation","Manual + E2E UI","P0","iOS, Android, Web, Desktop","Valid reset token","Enter new password + confirm","Password changed; user can log in (or auto-login flow)","Token expires mid-flow","Reset endpoint ignores confirm field","Automate","🟢 test04_resetPasswordSuccessAndLogin"
|
||||
"AUTH-017","Authentication","Password reset","Mismatched password confirmation blocked","Manual + UI","P1","iOS, Android, Web, Desktop","Reset password screen","Enter mismatch","Inline error; no reset request","Trailing spaces","Client validates before submit","Automate","🟢 mismatchedPasswordsFails | caseSensitiveMismatchFails (ValidationHelpersTests)"
|
||||
"AUTH-018","Authentication","Deep link reset","Password-reset deep link opens flow with token prefilled","Manual + E2E UI","P0","iOS, Android","Installed app with deep-link support","Open reset deep link","Forgot/reset flow opens and token is consumed","Malformed token in URL","Deep link token can be cleared on back","Automate",""
|
||||
"AUTH-017","Authentication","Password reset","Mismatched password confirmation blocked","Manual + UI","P1","iOS, Android, Web, Desktop","Reset password screen","Enter mismatch","Inline error; no reset request","Trailing spaces","Client validates before submit","Automate","🟢 mismatchedPasswordsFails | caseSensitiveMismatchFails (ValidationHelpersTests) | matchingPasswordsReturnsNil | mismatchedPasswordsReturnsMismatch | caseSensitiveMismatch (ValidationRulesTests) | requiredFieldErrorDescription | invalidEmailErrorDescription | passwordTooShortErrorDescription | passwordMismatchErrorDescription | passwordMissingLetterErrorDescription | passwordMissingNumberErrorDescription | invalidCodeErrorDescription | invalidUsernameErrorDescription | customMessageErrorDescription (ValidationRulesTests)"
|
||||
"AUTH-018","Authentication","Deep link reset","Password-reset deep link opens flow with token prefilled","Manual + E2E UI","P0","iOS, Android","Installed app with deep-link support","Open reset deep link","Forgot/reset flow opens and token is consumed","Malformed token in URL","Deep link token can be cleared on back","Automate","🟢 defaultInitStartsAtRequestCode | initWithTokenStartsAtResetPassword | moveToNextStepFromRequestCode | moveToNextStepFromVerifyCode | moveToNextStepFromResetPassword | moveToNextStepFromLoggingIn | moveToNextStepFromSuccessIsNoOp | moveToPreviousStepFromVerifyCode | moveToPreviousStepFromResetPassword | moveToPreviousStepFromRequestCodeIsNoOp | moveToPreviousStepFromLoggingInIsNoOp | moveToPreviousStepFromSuccessIsNoOp | resetClearsAllState | clearErrorNilsOutErrorMessage | clearSuccessNilsOutSuccessMessage | verifyResetCodeWithEmptyCodeSetsError | verifyResetCodeWithNonNumericCodeSetsError | resetPasswordWithEmptyPasswordSetsError | resetPasswordWithWeakPasswordSetsError | resetPasswordWithMismatchedPasswordsSetsError | resetPasswordWithNilTokenSetsError | allCasesHasFiveValues | allCasesContainsExpectedSteps (PasswordResetViewModelTests)"
|
||||
"AUTH-019","Authentication","SSO Apple","Apple Sign-In success creates or signs in account","Manual + Integration","P1","iOS","Apple-capable test device/simulator","Complete Apple sign-in","Session established; verification state handled","User hides email, first-login only email scope","Apple credential mapped to backend request","Automate partially (mock)",""
|
||||
"AUTH-020","Authentication","SSO Google","Google Sign-In success path","Manual + Integration","P1","Android, Web, KMP UI","Google sign-in configured","Complete Google sign-in","Session established with backend token","Revoked Google token","Backend validates ID token","Automate partially",""
|
||||
"ONB-001","Onboarding","Intent split","Start Fresh path goes through value props and name residence","Manual + E2E UI","P0","iOS, Android (KMP)","Fresh install","Choose Start Fresh and continue","Step order matches intended flow","Back navigation at each step","Flow differs by intent","Automate","🟢 testF101_StartFreshFlowReachesCreateAccount | testR002_startFreshFlowReachesCreateAccount"
|
||||
@@ -89,8 +89,8 @@
|
||||
"NOTIF-003","Notifications","Token refresh","New push token triggers backend re-registration","Manual + Integration","P1","iOS, Android","Previously registered token","Simulate token rotation","Backend receives updated registration id","No token change should skip call","Last registered token cache used","Automate",""
|
||||
"NOTIF-004","Notifications","Foreground notification","Foreground notifications display banner/sound and update read state","Manual","P1","iOS, Android","Permission granted, send test push","Receive push while app active","Banner shown; notification handled","Malformed payload missing type","Foreground presentation explicitly enabled","Manual",""
|
||||
"NOTIF-005","Notifications","Notification tap navigation","Tap task push opens app and routes to tasks context","Manual + E2E","P0","iOS, Android","Task-linked push sent","Tap push from background/terminated","App opens on tasks flow for target task","Task no longer exists","Task id may be string or int","Automate partially",""
|
||||
"NOTIF-006","Notifications","Action buttons premium","Premium users see and can execute task action buttons","Manual + Integration","P0","iOS, Android","Premium subscription active","Receive actionable task notification, tap action","Action API executes and UI refreshes","Action timeout/network loss","Actions gated by premium/limitationsEnabled","Manual",""
|
||||
"NOTIF-007","Notifications","Action buttons free-tier gating","Free users with limitations enabled are routed home/not allowed actions","Manual","P0","iOS, Android","Free user limitationsEnabled=true","Tap actionable notification","No privileged task action executed","Subscription cache stale nil","Nil subscription defaults allow on iOS currently","Manual",""
|
||||
"NOTIF-006","Notifications","Action buttons premium","Premium users see and can execute task action buttons","Manual + Integration","P0","iOS, Android","Premium subscription active","Receive actionable task notification, tap action","Action API executes and UI refreshes","Action timeout/network loss","Actions gated by premium/limitationsEnabled","Manual","🟢 encodeDecodeRoundTrip | decodedValuesMatch | sameValuesAreEqual | differentTaskIdNotEqual | differentTaskTitleNotEqual | taskIdReturnsCorrectValue | taskTitleReturnsCorrectValue (WidgetActionTests)"
|
||||
"NOTIF-007","Notifications","Action buttons free-tier gating","Free users with limitations enabled are routed home/not allowed actions","Manual","P0","iOS, Android","Free user limitationsEnabled=true","Tap actionable notification","No privileged task action executed","Subscription cache stale nil","Nil subscription defaults allow on iOS currently","Manual","🟢 encodeDecodeRoundTrip | sameValuesAreEqual | differentTaskIdNotEqual | differentTaskTitleNotEqual (WidgetActionTests)"
|
||||
"NOTIF-008","Notifications","Preferences","Load and update notification preference toggles","Manual + Integration","P1","iOS, Android, Web, Desktop","Logged in","Open notification preferences, toggle settings, save","Preferences persist and affect server payloads","Partial update failures","Preferences API supports patch/update","Automate",""
|
||||
"NOTIF-009","Notifications","History/read state","Notification history list and mark-read operations","Manual + Integration","P2","iOS, Android, Web, Desktop","Notifications exist","Open history, mark one and mark all","Unread counts decrement correctly","Race with incoming push","Unread count endpoint consistent","Automate",""
|
||||
"SUB-001","Subscription","Status load","Subscription status loads at app launch/foreground","Manual + Integration","P0","iOS, Android, Web, Desktop","Logged in","Launch then background/foreground app","Status cache updates and UI gating accurate","Backend temporarily unavailable","Status refresh should be non-fatal","Automate",""
|
||||
@@ -103,7 +103,7 @@
|
||||
"SUB-008","Subscription","Feature gating","Pro-only features hidden/disabled for limited users","Manual + E2E","P0","iOS, Android, Web, Desktop","Test free and pro accounts","Traverse gated features (actions, limits, upgrades)","Gating consistent across surfaces","Cache stale after plan change","Gating uses subscription status + limitationsEnabled","Automate",""
|
||||
"WID-001","Widgets","Small widget rendering","Small widget shows counts and opens app","Manual","P1","Android","Widget added, logged in","Place small widget and tap","Correct counts; tap opens app","No data cached yet","Widget reads from shared preferences state","Manual",""
|
||||
"WID-002","Widgets","Medium widget list","Medium widget shows top tasks and overdue badge","Manual","P1","Android","Tasks exist","Place medium widget","Task rows and overdue badge correct","Malformed tasks_json","JSON parse fallback to empty list","Manual",""
|
||||
"WID-003","Widgets","Large widget interactions","Large widget actions execute for pro users","Manual + Integration","P0","Android","Pro account, widget configured","Tap row and action controls","Opens task or executes action as expected","Free user should not see/execute pro actions","Widget passes task_id in intent","Manual",""
|
||||
"WID-003","Widgets","Large widget interactions","Large widget actions execute for pro users","Manual + Integration","P0","Android","Pro account, widget configured","Tap row and action controls","Opens task or executes action as expected","Free user should not see/execute pro actions","Widget passes task_id in intent","Manual","🟢 encodeDecodeRoundTrip | decodedValuesMatch | taskIdReturnsCorrectValue | taskTitleReturnsCorrectValue (WidgetActionTests)"
|
||||
"WID-004","Widgets","Widget refresh","Widgets refresh after task state changes","Manual","P1","Android","Widget present","Complete/cancel task in app","Widget counts/list update within expected interval","Background restrictions","Widget update manager triggers refresh","Manual",""
|
||||
"SHR-001","Sharing/Import","File association",".casera files open app import flow","Manual","P1","Android","Have .casera file","Open file from files app/share sheet","Import confirmation dialog shown","Multiple apps can open same MIME","Intent filter handles application/json with extension","Manual",""
|
||||
"SHR-002","Sharing/Import","Security","Import rejects when unauthenticated","Manual","P0","Android","Logged out, .casera file ready","Attempt import","Error shown, no data mutation","Stale token in storage","Auth check occurs before API call","Manual",""
|
||||
@@ -134,7 +134,7 @@
|
||||
"I18N-001","Localization","String coverage","No missing keys/placeholders across supported locales","Manual + Static check","P1","iOS, Android, Web, Desktop","Run app in each locale","Traverse major screens","No raw keys, no placeholder mismatches","Pluralization and gender strings","Locales include es/fr/de/it/ja/ko/nl/pt/zh etc.","Automate (lint + screenshot)",""
|
||||
"I18N-002","Localization","Layout expansion","Long translations do not break onboarding/forms/buttons","Manual","P1","iOS, Android, Web, Desktop","Switch to longest-string locale","Review high-density screens","No clipping/overlap","RTL future locale support","Current locales may be LTR only","Manual",""
|
||||
"THEME-001","Theming","Theme persistence","Theme choice persists across app restarts","Manual + Integration","P1","iOS, Android, Web, Desktop","Logged in or logged out","Change theme then relaunch","Selected theme reapplied","Theme ID missing/corrupt in storage","Theme stored separately from auth data","Automate","🟢 defaultThemeIdIsDefault | setThemeIdUpdatesValue | clearDoesNotResetTheme | themeIdIsPreservedAsOceanAfterClear (ThemePersistenceTests) | test09_themePersistsAcrossRestart"
|
||||
"THEME-002","Theming","Theme switch live update","Changing theme updates active screen without broken states","Manual + UI","P2","iOS, Android, Web, Desktop","Open app on any tab","Change theme in profile/settings","Immediate UI recolor with legible components","Transition while modal open","Theme manager publishes updates","Manual",""
|
||||
"THEME-002","Theming","Theme switch live update","Changing theme updates active screen without broken states","Manual + UI","P2","iOS, Android, Web, Desktop","Open app on any tab","Change theme in profile/settings","Immediate UI recolor with legible components","Transition while modal open","Theme manager publishes updates","Manual","🟢 allCasesCountIsEleven | allDisplayNamesAreNonEmpty | allDescriptionsAreNonEmpty | rawValueRoundTripsForAllCases | allRawValuesAreUnique | brightDisplayNameIsDefault | oceanRawValueIsOcean (ThemeIDTests)"
|
||||
"NAV-001","Navigation","Bottom tabs","Residences/Tasks/Contractors/Documents tabs navigate and preserve expected state","Manual + E2E UI","P0","iOS, Android","Logged in","Switch tabs repeatedly","Correct screens shown; no stuck navigation","Push navigation then tab switch back","Nested nav stacks differ per platform","Automate","🟢 test03_navigationBetweenTabs | test10_navigateBetweenTabs | testR309_navigationAcrossPrimaryTabsAndBackToResidences"
|
||||
"NAV-002","Navigation","Back stack safety","Back from details/forms returns to correct parent","Manual + E2E UI","P0","iOS, Android, Web, Desktop","Navigate into detail/edit screens","Use back gestures/buttons","Parent state intact and refreshed as expected","Direct deep-link entry without parent","Saved-state refresh flags used in KMP nav","Automate","🟢 test02_cancelRegistration | test04_cancelResidenceCreation | test02_cancelTaskCreation | test19_CancelDocumentCreation"
|
||||
"NAV-003","Navigation","Duplicate routes","Avoid duplicate screen instances from repeated tap/navigation actions","Manual","P2","iOS, Android, Web, Desktop","Rapidly tap nav actions","Observe back stack and UI","No duplicate stacking or loops","Double tap race conditions","NavHost popUpTo rules applied","Manual","🟢 testP003_RapidDoubleTapOnValuePropsContinueLandsOnNameResidence | testP004_StartFreshThenBackToWelcomeThenJoinExistingDoesNotCorruptState | testP005_RepeatedLoginNavigationRemainsStable"
|
||||
|
||||
|
Reference in New Issue
Block a user