58 lines
4.0 KiB
Markdown
58 lines
4.0 KiB
Markdown
# QA procedure: article_publishing
|
|
|
|
Package: `test` (black-box, extending `article_test.go`).
|
|
|
|
## Setup shared by every case
|
|
1. Call `validator.InitValidator()` once.
|
|
2. Reuse `mockArticleRepo` (`test/article_test.go`) as-is; its `UpdateIsOnline` and `FindByFilters`
|
|
already support everything this slice needs, no fake changes expected.
|
|
3. Wire the real use cases over the fake: `useCases.NewCreateArticleUseCase`,
|
|
`useCases.NewGetArticleUseCase`, `useCases.NewListArticlesUseCase`,
|
|
`useCases.NewDeleteArticleUseCase`, `useCases.NewUpdateArticleUseCase`. Build
|
|
`article.NewHandler(...)` extended to also take the update use case (matching whatever
|
|
`NewHandler` signature the coder lands on), exposing the new `PublishArticle` and
|
|
`UnpublishArticle` methods.
|
|
4. Build a test `jwtauth.New("HS256", []byte("test-secret"), nil)`.
|
|
5. Mount the routes on a fresh `chi.NewRouter()` mirroring `api/router.go`'s current shape
|
|
(per `public_article_listing.qa.md`): `GET /` under `jwtauth.Verifier` only; `GET /{id}`,
|
|
`POST /`, `DELETE /{id}` under `jwtauth.Verifier` + `jwtauth.Authenticator`. Add
|
|
`PATCH /{id}/publish` and `PATCH /{id}/unpublish` to that same authenticated group.
|
|
6. Mint a valid jwt cookie for user id 1: `token.Encode(map[string]any{"user_id": uint32(1)})`,
|
|
set as the `jwt` cookie on the relevant `httptest.NewRequest`.
|
|
7. Seed the repo directly via the map pattern already used elsewhere, e.g.
|
|
`repo.articles[1] = article.Article{ID: 1, Title: "Backyard Renovation Update", IsOnline: true}`
|
|
and `repo.articles[2] = article.Article{ID: 2, Title: "Draft: Kitchen Remodel", IsOnline: false}`.
|
|
|
|
## HTTP checks
|
|
8. `PATCH /v1/article/2/publish` with the valid cookie, repo seeded per step 7 -> status `200`;
|
|
decode the JSON body and assert `id == 2` and `is_online == true`; assert `repo.articles[2].IsOnline`
|
|
is now `true`.
|
|
9. `PATCH /v1/article/1/unpublish` with the valid cookie, repo seeded per step 7 -> status `200`;
|
|
decode the JSON body and assert `id == 1` and `is_online == false`; assert
|
|
`repo.articles[1].IsOnline` is now `false`.
|
|
10. `PATCH /v1/article/1/publish` with the valid cookie against an article already seeded
|
|
`IsOnline: true` -> status `200`, body `is_online == true`, no error (idempotency).
|
|
11. `PATCH /v1/article/2/unpublish` with the valid cookie against an article already seeded
|
|
`IsOnline: false` -> status `200`, body `is_online == false`, no error (idempotency).
|
|
12. `PATCH /v1/article/9999/publish` with the valid cookie, empty repo id `9999` -> status `404`,
|
|
body `"Article not found\n"`. Repeat for `PATCH /v1/article/9999/unpublish` -> same assertions.
|
|
13. `PATCH /v1/article/not-a-number/publish` with the valid cookie -> status `400`, body matching
|
|
`apperr.IdUint32ErrorMessage + "\n"`. Repeat for `.../unpublish`.
|
|
14. `PATCH /v1/article/1/publish` with **no** cookie, repo seeded with article id 1 -> status `401`.
|
|
Repeat for `PATCH /v1/article/1/unpublish` with no cookie -> status `401`.
|
|
15. Integration with the public listing: seed repo with an offline article id 2, call
|
|
`PATCH /v1/article/2/publish` with the valid cookie (assert `200`), then call
|
|
`GET /v1/article/` with no cookie and assert the decoded JSON array contains an element with
|
|
id `2`.
|
|
16. Mirror check: seed repo with an online article id 1, call `PATCH /v1/article/1/unpublish` with
|
|
the valid cookie (assert `200`), then call `GET /v1/article/` with no cookie and assert the
|
|
decoded JSON array does not contain an element with id `1`.
|
|
|
|
## Manual verification (not exercised by the Go test)
|
|
- SPA-visible behaviour: confirm the back-office article editor exposes a publish/unpublish
|
|
control that calls the new endpoints and updates the visible online/offline state, against the
|
|
real embedded frontend and a real SQLite file. Not exercised by `task test`; requires `task dev`
|
|
or a built `task build` binary. (No such UI exists yet as of this slice — this note applies once
|
|
the SPA is wired to the new endpoints.)
|
|
- No SMTP involvement.
|