57 lines
6.0 KiB
Markdown
57 lines
6.0 KiB
Markdown
# QA procedure: Roles sync pass 6, final copy and role activity events
|
|
|
|
Spec: features/roles_sync_copy_activity.feature. Vitest + Vue Test Utils under `task test:web`, /v1 mocked with the existing kits (useApi mock of views/__tests__, access bodies from web/src/test/access.ts, activityFixtures.ts). The backend Rule adds a Go test. No live server, no real SMTP.
|
|
|
|
## Honesty rules
|
|
0. First run `task test:web` and `task test` on the unmodified tree and record exit codes and failing specs (known Go failure from slice 7: TestRouterRoutesAreInTheCatalogue).
|
|
1. If a runner cannot execute, every item of that side is NOT RUN, never passing.
|
|
2. Report each new or edited spec and which already failed in the baseline.
|
|
3. Assert only copy the design gives. FR is asserted only where the design table gives it. The fallback sentences of the feature are a design gap and are asserted as the coder writes them, flagged in the report.
|
|
4. No spec freezes the system date; fixed `created_at` strings; no relative-date assertion.
|
|
|
|
## Automated (Vitest)
|
|
| Spec | Cases |
|
|
|---|---|
|
|
| lib/__tests__/activitySentence.spec.ts (extend) | the six success sentences EN/FR, role.reassign with moved 3 and 1 and to_name, the six failed sentences EN/FR, the three fallback rows (no "undefined"), unknown action |
|
|
| lib/__tests__/activityCategories.spec.ts (extend) | category list and order, "Users and invites", "Roles" requests `category=roles`, "Users & invites" absent |
|
|
| views/__tests__/ActivityRoles.spec.ts (extend) | list with the six events, the six failed rows with the Failed badge |
|
|
| views/__tests__/ActivityFilters.spec.ts (extend) | the select options EN/FR |
|
|
| components/__tests__/ChangeRoleDialog.spec.ts (extend) | success toast EN/FR with member and role names, "Couldn't change the role" alert for 500 and network, choice kept, button enabled |
|
|
| views/__tests__/RoleEditorView.spec.ts (extend) | save failed (500, network) for POST and PUT: alert, "Try again", edits kept, Save enabled |
|
|
| components/__tests__/DeleteRoleDialog.spec.ts (extend) | 409 target_role_not_found: alert, picker cleared, action off; 400 invalid_reassign keeps the existing refusal; role_has_members with the live count; 500 on reassign keeps the choice and sends no DELETE |
|
|
| components/__tests__/InviteUserModal.spec.ts (extend) | the four invite errors placement (under Email, under Role, alert), email and role kept |
|
|
| i18n/roleMessages.spec.ts (extend) | every key of the "Final copy" table exists in EN and FR, placeholders match |
|
|
| i18n/neutralWording.spec.ts (new) | no EN value in the roles, users, profile, api-key and activity keys matches \b(he\|she\|his\|her\|him)\b |
|
|
|
|
Mocks to reuse: Ines Duarte, Jonas Weber, Marta Alves; roles Owner, Admin, Writer, Contributor, Content lead, Intern (1 member).
|
|
|
|
## Automated (Go, httptest, in-memory fakes) in test/
|
|
Build the role handler with `NewHandler(...)` over the use cases and the in-memory fakes of role.Repository, user.Repository and the audit recorder of the existing roles API tests. Mount on a fresh `chi.NewRouter()` mirroring api/router.go with `jwtauth.Verifier` + `Authenticator` and a test `jwtauth.New("HS256", …)`. Call `validator.InitValidator()`. No SQLite file, no SMTP. New fake names must be unique across the package.
|
|
|
|
| Test | Steps and assertions |
|
|
|---|---|
|
|
| TestReassignRecordsDestinationName | POST /v1/role/{Contributor}/reassign {target_role_id: Writer} with 4 members: the recorded event params are from, to, moved 4 and to_name "Writer" |
|
|
| TestReassignZeroMovedRecordsNothing | 0 members: 200 `{"moved":0}`, no event (unchanged) |
|
|
| TestReassignRefusalRecordsNothing | a refusal (400, 403, 404, 409) records no event |
|
|
|
|
Extend, do not duplicate, test/roles_api_usecases_test.go line ~735 (the existing params assertion). Mutation scope for the touched use case: `MUTATE_FILES=ReassignRoleMembers.go MUTATE_RUN='TestReassign' task mutate -- ./internal/infrastructure/useCases`. docs/api.md gains one line for `to_name`. `task lint:go` and `gofmt -l` apply.
|
|
|
|
## Visual (task visual:check)
|
|
Screens `roles` and `activity`; states from docs/design/screens/roles.md groups 8, 12 and 13. Sample data is the board's: Ines Duarte, Jonas Weber, Marta Alves, Contributor, Intern, Writer, Content lead, 3 members moved. Gate: every capture within 10 % in light and dark, desktop and mobile. `skip: clock-sensitive` for any activity row whose rendering depends on relative time; the role rows use fixed timestamps from the frame and are checked.
|
|
States: Role changed toast, Role editor save failed, Change role failed, Delete role target deleted / role gained members / move failed, Invite invalid email / account exists / role above yours / send failed, Activity role events list, failed role events, category filter open.
|
|
|
|
## Manual checks
|
|
1. Toast durations (6 s; warnings stay until dismissed or Reload), polite announcement.
|
|
2. Keyboard: focus lands on "Try again", and on the field with the error in the invite dialog.
|
|
3. Real browser, FR: read every message of the table once.
|
|
4. Real flow: move members of a role to another and read the event in /activity with the destination name.
|
|
5. `task lint:web` (eslint and vue-tsc) green; `task test:web` and `task test` exit 0.
|
|
|
|
## Design gaps and notes
|
|
- G1 FR for strings the design gives in EN only (Read = Own banners and empty states, Profile card tags, Integration copy) is proposed by the coder and not asserted.
|
|
- G2 The activity reasons ("Why it failed") are out of this slice by decision.
|
|
- G3 Fallback wordings for role.reassign events without to_name or moved ("Moved 3 members from Intern to another role", "Moved the members of the role Intern", "Failed to move the members of the role Intern") are not in the design.
|
|
- G4 Singular "Failed to move 1 member" is derived from the success sentence; the design gives the failed sentence for 3 only. A failed reassign does not record `moved`, so the failed full sentence appears only if the event carries it.
|
|
- G5 The user.remove sentences are in features/roles_sync_remove_user.feature.
|
|
- Backend change: the additive `to_name` param only.
|