feat: remove the 10,000-character article body limit and make the New article body optional

This commit is contained in:
Florian Sylvain committed 2026-10-11 08:49:11 +02:00
1 parent 5e05b606a7
commit 10ec74c8cf
28 files changed
+860 -397

No files matched your search

+42 -63
View File
@@ -1,10 +1,10 @@
Feature: Creating a new article from NewArticleModal
As a verified RenewCMS owner
I want NewArticleModal to take a title and a first paragraph, create the article as a draft
over POST /v1/article/, and take me straight to the editor to keep writing
So that starting a new article is a two-field, low-friction step instead of a full form, and I
land where I can actually write it
I want NewArticleModal to take only a title, create the article as a draft
over POST /v1/article/, and take me straight to the editor to write it
So that starting a new article is a one-field, low-friction step and I land where I can
actually write it
Background:
Given NewArticleModal is a UModal opened from Home's "New article" action (mobile header
@@ -14,42 +14,37 @@ Feature: Creating a new article from NewArticleModal
And every time it opens, it starts in the Default state: title "New article", text "It's
saved as a draft. Titles can't be changed later, so check it now.", an empty, focused Title
field with placeholder "e.g. Choosing tiles for a small bathroom", a CharacterCounter
reading "0 / 200" and help "3 to 200 characters.", an empty First paragraph textarea with
placeholder "Start writing. You'll continue in the editor." and help "You can format it and
add images in the editor.", a "Cancel" button and a "Create draft" button
reading "0 / 200" and help "3 to 200 characters.", a "Cancel" button and a "Create draft"
button; there is no body or First paragraph field
And the Title field is sent as the request's title and is validated required, 3 to 200
characters, counted the same way as the CharacterCounter ([...str].length, which is rune
count, matching article_title_rules.feature's server-side rune counting)
And the First paragraph field is sent as the request's body and is validated required (at
least one character)
And each field validates on blur and again on submit; submitting while either field is
invalid sends no request, and shows both fields' errors at once if both are invalid: Title
under 3 characters shows "Use at least 3 characters." in place of its help text, with the
counter in its error style; an empty First paragraph shows "Add a first paragraph. It can
be a single sentence." in place of its help text
And activating "Create draft" while both fields are valid sends POST /v1/article/ with JSON
{"title": "<title>", "body": "<first paragraph>"}; while the request is in flight both
fields and both buttons are disabled, the confirm button reads "Creating…" with a loading
indicator, and the modal cannot be dismissed by Cancel, Esc or a backdrop click
And the request carries no body key; the server treats an absent body as "" per
features/article_body_unlimited.feature
And the Title field validates on blur and again on submit; submitting while it is invalid
sends no request: a title under 3 characters shows "Use at least 3 characters." in place of
its help text, with the counter in its error style
And activating "Create draft" while the title is valid sends POST /v1/article/ with JSON
{"title": "<title>"}; while the request is in flight the Title field and both buttons are
disabled, the confirm button reads "Creating…" with a loading indicator, and the modal
cannot be dismissed by Cancel, Esc or a backdrop click
And a 201 response closes the modal, emits created(article) with the response body, and (for
this slice) HomeView.vue's created handler navigates to /article/{id}/edit and raises a
toast: color success, icon i-lucide-circle-check, title "Draft created", description
"\"{title}\" is saved as a draft.", with id "article-created-{id}" per
docs/design/components.md's toast-id convention
And a 400 response — whether apperr.ArticleTitleErrorMessage for a title that passed this
form's own check but still failed the server's, or any other 400 — is never shown verbatim;
it re-enables the form with both fields' current values kept, shows "Check this title and
try again." in place of the Title field's help text, and shows an alert "Something in the
form isn't valid. Check the highlighted fields."; the First paragraph field shows no error
And a 500 response or a request that never reaches the server re-enables the form with both
fields' current values kept and shows an alert "Couldn't create the article. Your text is
still here. Try again in a moment.", with no field-level error
And "Cancel" always closes the modal immediately and discards both fields, with no
And a 400 response is never shown verbatim; it re-enables the form with the title kept,
shows "Check this title and try again." in place of the Title field's help text, and shows
an alert "Something in the form isn't valid. Check the highlighted fields."
And a 500 response or a request that never reaches the server re-enables the form with the
title kept and shows an alert "Couldn't create the article. Your text is still here. Try
again in a moment.", with no field-level error
And "Cancel" always closes the modal immediately and discards the title, with no
confirmation prompt, whenever the form is not disabled by an in-flight request
And a 401 response is handled entirely by useApi's existing global handling
(features/api_client_global_error_handling.feature): the session is cleared and the app
navigates to /login?redirect=<path>&reason=expired; this slice adds no draft-preservation
behavior for the modal's fields, unlike the editor's session-expiry handling
behavior for the modal's field, unlike the editor's session-expiry handling
Scenario: Opening the modal shows the Default state
Given the user is on /home
@@ -57,7 +52,7 @@ Feature: Creating a new article from NewArticleModal
Then NewArticleModal opens with title "New article" and the text "It's saved as a draft.
Titles can't be changed later, so check it now."
And the Title field is empty, focused, and its counter reads "0 / 200"
And the First paragraph field is empty
And there is no First paragraph field
And "Create draft" is present but the form has not been submitted
Scenario: Validation — a title under 3 characters on blur
@@ -67,34 +62,23 @@ Feature: Creating a new article from NewArticleModal
And the counter reads "2 / 200" in its error style
And no request is sent
Scenario: Validation — an empty first paragraph on blur
Given the modal is open with a valid Title
When the user leaves the First paragraph field empty and moves focus away
Then the First paragraph field shows the error "Add a first paragraph. It can be a single
sentence."
And no request is sent
Scenario: Validation — submitting with both fields invalid shows both errors and sends nothing
Given the modal is open with Title "Ti" and an empty First paragraph
Scenario: Validation — submitting an invalid title sends nothing
Given the modal is open with Title "Ti"
When the user activates "Create draft"
Then the Title field shows "Use at least 3 characters." and the First paragraph field shows
"Add a first paragraph. It can be a single sentence."
Then the Title field shows "Use at least 3 characters."
And POST /v1/article/ is never sent
Scenario: Submitting disables the form and cannot be dismissed
Given the modal is open with Title "Choosing tiles for a small bathroom" and First paragraph
"Small rooms show every grout line, so we start with the floor."
Given the modal is open with Title "Choosing tiles for a small bathroom"
When the user activates "Create draft"
Then POST /v1/article/ is sent with JSON {"title": "Choosing tiles for a small bathroom",
"body": "Small rooms show every grout line, so we start with the floor."}
And both fields become disabled, "Cancel" becomes disabled, and the confirm button reads
Then POST /v1/article/ is sent with JSON {"title": "Choosing tiles for a small bathroom"}
And the Title field becomes disabled, "Cancel" becomes disabled, and the confirm button reads
"Creating…" with a loading indicator
And pressing Esc or clicking the backdrop does not close the modal
Scenario: A successful create closes the modal and hands off to the editor with a toast
Given the user is on /home with the modal open, Title "Choosing tiles for a small bathroom"
and First paragraph "Small rooms show every grout line, so we start with the floor.", and
"Create draft" has been activated
Given the user is on /home with the modal open, Title "Choosing tiles for a small bathroom",
and "Create draft" has been activated
When POST /v1/article/ resolves 201 with the created article, id 42, is_online false
Then the modal closes
And the app navigates to /article/42/edit
@@ -104,33 +88,29 @@ Feature: Creating a new article from NewArticleModal
Scenario: Title rejected — a 400 that got past this form's own check
Given the modal is open with Title "Choosing tiles for a small bathroom" (already valid by
this form's own rule) and First paragraph "Small rooms show every grout line, so we start
with the floor.", and "Create draft" has been activated
this form's own rule), and "Create draft" has been activated
When POST /v1/article/ resolves 400
Then the modal re-enables, keeping both field values
Then the modal re-enables, keeping the title
And the Title field shows "Check this title and try again." in place of its help text
And an alert reads "Something in the form isn't valid. Check the highlighted fields."
And the First paragraph field shows no error
Scenario Outline: Error — a 500 or a network failure keeps the text and offers to retry
Given the modal is open with Title "Choosing tiles for a small bathroom" and First paragraph
"Small rooms show every grout line, so we start with the floor.", and "Create draft" has
been activated
Given the modal is open with Title "Choosing tiles for a small bathroom", and "Create draft"
has been activated
When POST /v1/article/ <failure>
Then the modal re-enables, keeping both field values
Then the modal re-enables, keeping the title
And an alert reads "Couldn't create the article. Your text is still here. Try again in a
moment."
And neither field shows a field-level error
And the Title field shows no field-level error
Examples:
| failure |
| failure |
| resolves with a 500 response |
| never reaches the server |
Scenario: Retrying after an Error succeeds
Given the modal is in the Error state after a 500, with Title "Choosing tiles for a small
bathroom" and First paragraph "Small rooms show every grout line, so we start with the
floor." still in the fields
bathroom" still in the field
When the user activates "Create draft" again
Then POST /v1/article/ is sent again with the same JSON body
When it resolves 201 with the created article, id 42
@@ -138,9 +118,8 @@ Feature: Creating a new article from NewArticleModal
success, icon i-lucide-circle-check, title "Draft created", description "\"Choosing tiles
for a small bathroom\" is saved as a draft.", id "article-created-42"
Scenario: Cancel discards the fields with no confirmation
Given the modal is open with Title "Choosing tiles for a small bathroom" and First paragraph
"Small rooms show every grout line, so we start with the floor."
Scenario: Cancel discards the title with no confirmation
Given the modal is open with Title "Choosing tiles for a small bathroom"
When the user activates "Cancel"
Then the modal closes immediately, with no confirmation prompt
And no request is sent