Files
RenewCMS/features/article_title_rules.feature

86 lines
4.6 KiB
Gherkin

Feature: The article title rule is the same in the request and the domain
As the maintainer of RenewCMS
I want PostArticle's title validation and article.CreateArticle's title validation to
enforce the identical rule, counted the identical way
So that a title the request layer accepts can never be rejected by the domain as a
surprise 500, and a domain title rejection that does happen is always reported as a
400 with a client-facing apperr message instead of a raw 500
Background:
Given internal/domain/article defines the sentinel article.ErrInvalidTitle
And CreateArticleUseCase.CreateArticle rejects a title whose length, counted with
utf8.RuneCountInString (runes, not bytes), is below 3 or above 200, returning
article.ErrInvalidTitle and storing nothing
And api/handlers/article/articleHandler.go's PostArticle.Title carries
validate:"required,min=3,max=200", and go-playground/validator's min/max on a
string already count runes with utf8.RuneCountInString, so the request tag and the
domain check now agree on both the bound (3-200) and the unit (runes)
And api/pkg/apperr defines ArticleTitleErrorMessage as "Article title must be
between 3 and 200 characters.", a client-facing string distinct from both the raw
validator error text and "Failed to create article"
And Handler.PostArticle maps errors.Is(err, article.ErrInvalidTitle) from
CreateArticleUseCase.CreateArticle to a 400 response with body
apperr.ArticleTitleErrorMessage; any other error from CreateArticle still answers
500 with body "Failed to create article"
And POST /v1/article/ sits behind the jwtauth Verifier and Authenticator group and
requires a valid jwt cookie
And UpdateArticleUseCase exposes only UpdateBody, AddImage and UpdateIsOnline; no
route or use case updates an article's title after creation, so this feature only
concerns article creation
Scenario Outline: CreateArticle now measures title length in runes, not bytes
Given an empty article repository fake
When CreateArticle is called with a title made of <rune_count> repetitions of the
4-byte rune "😀" and a body "Some body text"
Then the result is <outcome>
Examples:
| rune_count | outcome |
| 2 | ErrInvalidTitle, nothing stored |
| 3 | created |
| 200 | created |
| 201 | ErrInvalidTitle, nothing stored |
Scenario Outline: POST /v1/article/ enforces the same 3-200 rune boundary over HTTP
Given a valid jwt cookie for a user with id 1
When the client sends POST /v1/article/ with that cookie, a title of <length> ASCII
characters and a body "Some body text"
Then the response status is <status>
And <storage_effect>
Examples:
| length | status | storage_effect |
| 2 | 400 | not created |
| 3 | 201 | created, is_online false |
| 200 | 201 | created, is_online false |
| 201 | 400 | not created |
Scenario: A 200-rune multibyte title is accepted end to end over HTTP
Given a valid jwt cookie for a user with id 1
When the client sends POST /v1/article/ with that cookie, a title made of 200
repetitions of the 4-byte rune "😀" (200 runes, 800 bytes) and a body
"Some body text"
Then the response status is 201
And the response body is the created article's JSON with that title
Scenario: The handler maps a domain title rejection to 400, not 500
Given a valid jwt cookie for a user with id 1
And the article repository fake is configured so its next Create call returns
article.ErrInvalidTitle directly, standing in for any layer beneath the use
case's own check rejecting the title with that same sentinel
When the client sends POST /v1/article/ with that cookie, title "Valid Title" and
body "Some body text" (both already satisfying PostArticle's own validate tags)
Then the response status is 400
And the response body is the text apperr.ArticleTitleErrorMessage
And the response body is not "Failed to create article"
Scenario: A non-title repository failure during creation still answers 500
Given a valid jwt cookie for a user with id 1
And the article repository fake is configured to fail on its next Create call with
a generic repository error, not article.ErrInvalidTitle
When the client sends POST /v1/article/ with that cookie, title "Valid Title" and
body "Some body text"
Then the response status is 500
And the response body is the text "Failed to create article"