Files
RenewCMS/features/article_publishing.qa.md

4.0 KiB

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

  1. 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.
  2. 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.
  3. 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).
  4. 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).
  5. 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.
  6. PATCH /v1/article/not-a-number/publish with the valid cookie -> status 400, body matching apperr.IdUint32ErrorMessage + "\n". Repeat for .../unpublish.
  7. 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.
  8. 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.
  9. 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.