104 lines
5.2 KiB
Gherkin
104 lines
5.2 KiB
Gherkin
Feature: An authenticated user can edit an article's body
|
|
|
|
As an authenticated RenewCMS user managing the CMS
|
|
I want to change an existing article's body from an HTTP endpoint
|
|
So that a published or draft article's content can be corrected or updated without
|
|
deleting and recreating it
|
|
|
|
Background:
|
|
Given internal/domain/article.Repository already exposes
|
|
UpdateBody(id uint32, body string) (Article, error), and
|
|
UpdateArticleUseCase.UpdateBody delegates to it unchanged
|
|
And UpdateArticleUseCase is already built in api/dependecyInjection.go as
|
|
container.UpdateArticleUseCase, but before this slice no handler or route calls
|
|
UpdateBody
|
|
And this slice adds Handler.UpdateArticleBody, backed by
|
|
UpdateArticleUseCase.UpdateBody(id, body)
|
|
And this slice mounts PATCH /v1/article/{id} inside the same jwtauth Verifier +
|
|
Authenticator group as GET /v1/article/{id}, POST /v1/article/,
|
|
DELETE /v1/article/{id}, PATCH /v1/article/{id}/publish and
|
|
PATCH /v1/article/{id}/unpublish in api/router.go, so it also requires a valid
|
|
jwt cookie
|
|
And the request body is JSON {"body": "..."}; the Body field carries no validate tag
|
|
(no max, not required), as PostArticle.Body, per
|
|
features/article_body_unlimited.feature
|
|
And a successful edit answers 200 with the JSON body of the updated article.Article,
|
|
the same shape GetArticle, PostArticle, PublishArticle and UnpublishArticle
|
|
already return; the article's title, is_online flag and images are unchanged
|
|
And an id that does not parse as a uint32 answers 400 with body
|
|
apperr.IdUint32ErrorMessage, the same as GetArticle, DeleteArticle,
|
|
PublishArticle and UnpublishArticle
|
|
And a body that is not valid JSON answers 400 with body apperr.BodyErrorMessage,
|
|
the same as PostArticle
|
|
And no body value fails validation: an empty or absent body and a body of any length
|
|
are accepted
|
|
And an id absent from the article repository answers 404 with body
|
|
apperr.ArticleNotFoundErrorMessage, backed by
|
|
errors.Is(err, article.ErrArticleNotFound), the same as DeleteArticle,
|
|
PublishArticle and UnpublishArticle already do per
|
|
features/write_not_found_errors.feature
|
|
And this slice does not add any way to change an article's title after creation,
|
|
per features/article_title_rules.feature
|
|
|
|
Scenario: Editing an existing article's body updates only the body
|
|
Given a valid jwt cookie for a user with id 1
|
|
And the article repository contains an online article titled
|
|
"Backyard Renovation Update" with id 1 and body "Old body text"
|
|
When the client sends PATCH /v1/article/1 with that cookie and body
|
|
{"body": "New body text"}
|
|
Then the response status is 200
|
|
And the response body is the article with id 1, "body": "New body text",
|
|
"title": "Backyard Renovation Update" and "is_online": true
|
|
|
|
Scenario: Editing an offline article's body leaves it offline
|
|
Given a valid jwt cookie for a user with id 1
|
|
And the article repository contains an offline article titled
|
|
"Draft: Kitchen Remodel" with id 2 and body "Draft notes"
|
|
When the client sends PATCH /v1/article/2 with that cookie and body
|
|
{"body": "Revised draft notes"}
|
|
Then the response status is 200
|
|
And the response body is the article with id 2, "body": "Revised draft notes"
|
|
and "is_online": false
|
|
|
|
Scenario: Editing an unknown article answers 404
|
|
Given a valid jwt cookie for a user with id 1
|
|
And the article repository has no article with id 9999
|
|
When the client sends PATCH /v1/article/9999 with that cookie and body
|
|
{"body": "New body text"}
|
|
Then the response status is 404
|
|
And the response body is the text "Article not found"
|
|
|
|
Scenario: A malformed id answers 400 before any repository call
|
|
Given a valid jwt cookie for a user with id 1
|
|
When the client sends PATCH /v1/article/not-a-number with that cookie and body
|
|
{"body": "New body text"}
|
|
Then the response status is 400
|
|
And the response body is the text apperr.IdUint32ErrorMessage
|
|
|
|
Scenario: A non-JSON request body answers 400 with the body error message
|
|
Given a valid jwt cookie for a user with id 1
|
|
And the article repository contains an article with id 1
|
|
When the client sends PATCH /v1/article/1 with that cookie and a body that is not
|
|
valid JSON
|
|
Then the response status is 400
|
|
And the response body is the text apperr.BodyErrorMessage
|
|
|
|
Scenario Outline: A body of any length, including empty, is accepted
|
|
Given a valid jwt cookie for a user with id 1
|
|
And the article repository contains an article with id 1
|
|
When the client sends PATCH /v1/article/1 with that cookie and body <payload>
|
|
Then the response status is 200
|
|
And the stored body equals the sent body
|
|
|
|
Examples:
|
|
| payload |
|
|
| {"body": ""} |
|
|
| {"body": "<10001-character string>"} |
|
|
|
|
Scenario: Editing an article requires authentication
|
|
Given no jwt cookie is sent
|
|
And the article repository contains an article with id 1
|
|
When the client sends PATCH /v1/article/1 without a cookie and body
|
|
{"body": "New body text"}
|
|
Then the response status is 401
|