# QA procedure: remove_article_image Package: `test` (black-box, extending `article_test.go` / `image_test.go`). ## Setup shared by every case 1. Call `validator.InitValidator()` once. 2. Reuse `mockArticleRepo` and `mockImageRepo` as-is. 3. Wire `useCases.NewDeleteImageUseCase(imageRepo)` (already used by `delete_article_cascades_images.qa.md`'s suite) alongside the existing use cases. 4. Build `image.NewHandler(...)` with its grown constructor including the delete use case, matching whatever parameter order the coder settles on. 5. Build a test `jwtauth.New("HS256", []byte("test-secret"), nil)`. 6. Mount `DELETE /{id}/image/{imageId}` alongside the existing article routes under the authenticated group, mirroring `api/router.go` after this slice. 7. Mint a valid jwt cookie for user id 1 as in `upload_article_image.qa.md`. ## HTTP checks 8. Seed `articleRepo.articles[1]` with `Images: []*image.Image{{ID: 10}}` and `imageRepo.images[10] = image.Image{ID: 10}`. Send `DELETE /v1/article/1/image/10` with the valid cookie. Assert status 204, empty body; assert `imageRepo.images` no longer has key 10. 9. Empty `articleRepo`; seed `imageRepo.images[10]`. Send `DELETE /v1/article/9999/image/10`. Assert 404, body `"Article not found\n"`; assert `imageRepo.images` still has key 10 (Delete never called — track via a call-count field on the fake, the same way the existing fakes already track `Create`). 10. Seed `articleRepo.articles[1]`; empty `imageRepo`. Send `DELETE /v1/article/1/image/9999`. Assert 404, body `"Image not found\n"`. 11. Seed `articleRepo.articles[1]` (empty Images) and `articleRepo.articles[2]` with `Images: []*image.Image{{ID: 10}}`; seed `imageRepo.images[10]`. Send `DELETE /v1/article/1/image/10`. Assert 204; assert `imageRepo.images` no longer has key 10 — asserts the shallow-check contract from the feature's fourth scenario. 12. Seed as in step 8. Send `DELETE /v1/article/1/image/10` with **no** cookie. Assert 401; assert `imageRepo.images` still has key 10. 13. Examples-driven: send `DELETE /v1/article/abc/image/10` and `DELETE /v1/article/1/image/abc` with the valid cookie. Assert 400, body `"The server expects the ID to be in the format of an unsigned 32-bit integer (uint32).\n"` for each. ## Also touched by this slice: upload_article_image's 201 body 14. Extend `upload_article_image.qa.md`'s existing 201-body assertion to also decode and check the `id` field equals the newly created image's `ID` in `imageRepo.images`. ## Manual verification (not exercised by the Go test) - Real DELETE against a real SQLite file and real UPLOAD_DIR: confirm the file is actually removed from disk and the `article_images` join row is gone, the same way `upload_article_image.qa.md`'s manual item covers the POST side. - SPA-visible behaviour: covered separately by `features/editor_image_removal.qa.md`. - No SMTP involvement.