Files
RenewCMS/features/sites_authors_screens.feature

635 lines
34 KiB
Gherkin

Feature: Sites and Authors screens
As a RenewCMS owner or admin
I want /settings/sites and /authors to list, add, edit and delete sites and authors
So that every article belongs to a frontend and credits the right bylines
Background:
Given /settings/sites is a verified route rendered as SitesView and /authors is a verified route
rendered as AuthorsView, both inside DashboardShell, per docs/design/routes.md
And both screens are built from the shared directory pieces, defined once and not redrawn:
DirectoryList, DirectoryPanel (the slide-over), ReassignDialog, SlugField and MediaField
And the screens call, with relative URLs through useApi only, GET, POST, PATCH and DELETE on
/v1/site/ and /v1/author/, PATCH /v1/site/{id}/default and GET /v1/user/
And POST /v1/author/me and the changes to the Editor, Articles and Profile screens are specified in features/sites_authors_integration.feature
And a site has the fields id, name, key, base_url, default_social_image_id, default_robots
("index" or "noindex"), locale, is_default and article_count
And an author has the fields id, name, slug, bio, avatar_id, website, social_links, user_id,
is_linked, article_count and, for owner and admin only, user_email
And an error answered by the API is a plain-text code, and the SPA maps the code to the copy
of docs/design/states.md, never showing the code itself
And the sites fixture is, in list order:
| name | key | base_url | articles | default |
| Renew | renew | https://renew.example | 268 | yes |
| Journal | journal | https://journal.example | 38 | no |
| Projects | projects | https://projects.example | 6 | no |
| Archive | archive | https://archive.example | 0 | no |
And the authors fixture includes "Inès Duarte" (slug ines-duarte, linked, 9 articles),
"Camille Roche" (slug camille-roche, guest, 3 articles), "Léa Fontaine" (slug lea-fontaine,
guest, 0 articles) and one author with 1 article
And every visible string goes through t(...) with the English text as the key and its French
entry in web/src/i18n/messages.ts
And the screens use Nuxt UI components and design tokens only, with no raw colors
And the board frames of docs/design/source/DirectoryFrame.dc.html are the layout tiebreaker
Rule: Sites list
Scenario: Sites: default (owner)
Given the session role is "owner"
And GET /v1/site/ answers 200 with the sites fixture
When the user navigates to /settings/sites
Then the page shows "Sites", "The frontends that display your content." and a primary
"Add site" button
And the columns are "Site", "Base URL" and "Articles"
And each row shows the name with its key and the base URL
And the counts read "268 articles", "38 articles", "6 articles" and "No articles"
And "Renew" carries a "Default" badge
And a site whose default_robots is "noindex" carries a "Noindex" badge
And below md the rows are cards and a full-width "Add site" button is pinned to the bottom
Scenario: Sites: only the default site
Given GET /v1/site/ answers 200 with only the default site
When the owner navigates to /settings/sites
Then the row is listed and the hint "Add another site if your content is shown on more than one
frontend. Each article belongs to one site." appears under the list
And no empty-state wall is drawn
Scenario: Sites: loading
Given GET /v1/site/ is pending
When the owner navigates to /settings/sites
Then no skeleton shows before 150 ms
And after 150 ms skeleton rows are drawn and the list has aria-busy "true"
Scenario Outline: Sites: error on load
Given GET /v1/site/ fails with <failure>
When the owner navigates to /settings/sites
Then an alert shows "Couldn't load sites", "Check your connection and try again." and a
"Try again" action
And no rows are drawn
When the user activates "Try again"
Then GET /v1/site/ is requested again and, on 200, the list replaces the alert
Examples:
| failure |
| status 500 |
| a network error |
Scenario: Sites: row menu
Given the sites list is shown
When the user activates the ellipsis button of "Journal", or presses Enter on it
Then a menu offers "Edit", "Set as default" and "Delete…"
And below md the menu is a bottom sheet titled "Journal"
Scenario: Sites: delete unavailable on the default site
Given the sites list is shown
When the user opens the menu of "Renew"
Then "Delete…" has aria-disabled "true" and stays focusable
And a tooltip on desktop, and text in the sheet on touch, reads "The default site can't be
deleted. Make another site the default first."
And activating it opens no dialog and sends no request
Scenario: Sites: set as default, confirm and success
Given the sites list is shown
When the user chooses "Set as default" on "Journal"
Then a dialog titled "Make Journal the default site?" reads "New articles start on this site.
Articles that are already on other sites stay where they are." with "Cancel" and
"Make default"
When the user activates "Make default"
Then exactly one PATCH /v1/site/2/default is sent with no body
And the button reads "Saving…" while it runs
And on 200 the "Default" badge moves to "Journal" and a toast shows "Default site changed" and
"\"Journal\" is now the default site."
Scenario Outline: Sites: set as default, failures
Given the "Make Journal the default site?" dialog is open
When PATCH /v1/site/2/default answers <status>
Then <outcome>
Examples:
| status | outcome |
| 500 | the dialog stays open with the notice "Couldn't save the site. Your changes are still here. Try again in a moment." |
| 404 | the dialog closes, the row leaves the list and an info toast shows "That site no longer exists" and "It was deleted somewhere else, so we removed it from the list." |
| 403 | the dialog closes and an error toast shows "Only the owner can manage sites" and "Ask the owner of this site." |
Rule: Sites access
Scenario: Sites: hidden entry for an admin
Given the session role is "admin"
When the user opens /settings
Then the sidebar has no "Publishing" group and no "Sites" entry
And the page has no "Publishing" card and no "Manage sites" row
Scenario: Sites: the owner sees the entry
Given the session role is "owner"
When the user opens /settings
Then the sidebar has a "Publishing" group with a "Sites" entry linking to /settings/sites
And Settings has a "Publishing" card with a "Manage sites" row linking to /settings/sites
Scenario Outline: Sites: forbidden (403 page)
Given the session role is "<role>"
When the user opens <path>
Then the page shows "You don't have access to Sites", "Only the owner can manage sites. Ask the
owner of this site if you need a change." and a "Back to Settings" button
And the user is not redirected, no slide-over opens and the sidebar has no Sites entry
When the user activates "Back to Settings"
Then the user lands on /settings
Examples:
| role | path |
| admin | /settings/sites |
| member | /settings/sites |
| admin | /settings/sites?edit=journal |
Scenario: Sites: the API answers 403 where the SPA expected the owner
Given the session role is "owner" but the API answers 403 "Only the owner can do this."
When the answer is for a page load
Then the 403 page shows
When the answer is for an action
Then an error toast shows "Only the owner can manage sites" and "Ask the owner of this site."
Rule: Sites form
Scenario: Sites form: add, empty
Given the sites list is shown and the default site is "Renew"
When the user activates "Add site" (the page header button, or the pinned bottom button below md)
Then a slide-over titled "Add site" opens, a 92 % bottom sheet below md
And it has the fields Name (placeholder "e.g. Journal"), Key (placeholder "Generated from the
name"), Base URL (placeholder "https://blog.example.com", help "The public address of the
frontend. Use https and no path."), "Default social image (optional)" with "Choose image"
and "Used when an article has no image of its own.", "Default robots policy" with "Index"
and "Noindex" and "Search engines may list this site's pages.", "Locale (optional)"
(placeholder "e.g. en or fr-CH", help "A language tag. Leave empty if the site has no
single language."), and the switch "Make this the default site" with "New articles start
here. The current default is Renew."
And a "Canonical URL preview" is shown, plus "Cancel" and "Add site"
And Name has focus
Scenario: Sites form: key from the name
Given the Add site slide-over is open
When the user types "Journal" in Name
Then Key shows "journal" with an "Auto" badge and the help "Lowercase letters, numbers and
hyphens. Used in API paths. It can't be changed after the site is added."
When the user activates the pencil
Then Key becomes editable and no longer follows the name
Scenario Outline: Sites form: base URL not valid
Given the Add site slide-over is open with a valid name and key
When the user enters base URL "<value>" and leaves the field or submits
Then no request is sent
And the Base URL error reads "<message>"
Examples:
| value | message |
| http://blog.example.com | Use https. For example https://blog.example.com. |
| https://blog.example.com/en | Remove the path. Use only the host, like https://blog.example.com. |
| blog | Enter a full URL, like https://blog.example.com. |
Scenario: Sites form: base URL refused by the server
Given the form passed the client checks
When POST or PATCH answers 400 invalid_site_url
Then Base URL shows "Enter a full URL, like https://blog.example.com."
Scenario Outline: Sites form: loopback hosts accept http
Given the Add site slide-over is open
When the user enters base URL "<value>"
Then no base URL error is shown
Examples:
| value |
| http://localhost:5173 |
| http://127.0.0.1:8081 |
| http://[::1]:5173 |
Scenario: Sites form: add succeeds
Given the Add site slide-over is filled with name "Journal", key "journal", base URL
"https://journal.example", robots "Noindex", empty locale and the default switch off
When the user activates "Add site"
Then exactly one POST /v1/site/ is sent with name, key, base_url, default_robots "noindex",
no locale, no default_social_image_id and is_default false
And the button reads "Saving…" while the request runs and the fields are disabled
And on 201 the slide-over closes and the new site is listed
Scenario: Sites form: duplicate key
Given the Add site slide-over has key "journal" and a site with that key is in the loaded list
When the user leaves Key, or submits and POST /v1/site/ answers 409 site_key_taken
Then Key shows "A site with the key \"journal\" already exists. Choose another key." and a
suggestion "Use journal-2"
And activating the suggestion sets Key to "journal-2"
Scenario Outline: Sites form: save failed
Given the Add site slide-over is filled
When the save fails with <failure>
Then a notice in the panel reads "Couldn't save the site. Your changes are still here. Try again in a moment."
And all the values are kept and the form is enabled again
Examples:
| failure |
| status 500 |
| a network error |
Scenario: Sites form: invalid locale from the server
Given the form has locale "english"
When the save answers 400 invalid_locale
Then Locale shows "Use a language tag like en or fr-CH." and the panel stays open
Scenario: Sites form: edit the default site
When the owner chooses "Edit" on "Renew"
Then a slide-over titled "Edit Renew" opens with the fields filled
And Key shows "renew" read-only with a lock and "Used in API paths, so it can't change."
And "Default site" is on and locked with "New articles start on the default site. To change it,
make another site the default."
And the submit reads "Save changes"
Scenario: Sites form: edit another site, noindex
When the owner chooses "Edit" on "Projects" whose robots is "noindex"
Then the slide-over is titled "Edit Projects", Key is read-only and locked, "Noindex" is
selected with "Asks search engines not to list this site's pages." and the switch
"Make this the default site" is available
When the user changes the name and activates "Save changes"
Then exactly one PATCH /v1/site/3 is sent without the key field
Scenario: Sites form: make another site the default from the form
Given the "Projects" edit form has the default switch turned on
When the user activates "Save changes"
Then the SPA sends PATCH /v1/site/3 for the changed fields, then PATCH /v1/site/3/default
And is_default is never sent in the first PATCH
Scenario: Sites form: discard changes
Given a slide-over is open with a changed field
When the user closes it with "Cancel", Escape or the backdrop
Then the existing "Discard changes?" dialog is asked
And an unchanged form closes without it
Scenario: Sites form: deep link
Given the session role is "owner"
When the user opens /settings/sites?edit=projects
Then the "Edit Projects" slide-over opens
When the user opens /settings/sites?edit=nope
Then an info toast shows "That site no longer exists" and the slide-over stays closed
Rule: Sites delete
Scenario: Sites delete: site with articles
Given the sites list is shown
When the owner chooses "Delete…" on "Journal"
Then a dialog titled "Delete this site?" reads "\"Journal\" will be deleted. 38 articles belong
to it, so choose a site to move them to. This can't be undone."
And "Move articles to" defaults to the default site "Renew" shown with "renew.example"
And the text "38 articles will move to Renew. Their canonical host changes to renew.example."
is shown, with "Cancel" and "Move 38 articles and delete"
Scenario: Sites delete: choose destination
Given the "Delete this site?" dialog is open for "Journal"
When the user opens the select
Then "Journal" is not offered and each option shows the name and the host
Scenario: Sites delete: with articles succeeds
Given the dialog is open for "Journal" (id 2) with destination "Renew" (id 1)
When the user activates "Move 38 articles and delete"
Then exactly one DELETE /v1/site/2?reassign_to=1 is sent
And the button reads "Moving articles…" while it runs
And on 204 the dialog closes, the row leaves the list and a toast shows "Site deleted" and
"38 articles moved to Renew."
Scenario: Sites delete: no articles
When the owner chooses "Delete…" on "Archive"
Then a dialog titled "Delete this site?" reads "\"Archive\" will be deleted. No articles belong
to it. This can't be undone." with "Cancel" and "Delete site" and no select
When the user activates "Delete site"
Then DELETE /v1/site/4 is sent with no reassign_to and, on 204, the row leaves the list
Scenario Outline: Sites delete: failures
Given the delete dialog is open for "Journal"
When DELETE answers <status>
Then <outcome>
Examples:
| status | outcome |
| 500 or network | the dialog stays open with the notice titled "Couldn't delete the site" and text "Nothing was changed. Try again in a moment." |
| 409 site_has_articles | the dialog stays open and shows "Choose where the articles go. This site has 38 articles." |
| 403 default_site | the dialog closes and an error toast shows "The default site can't be deleted. Make another site the default first." |
| 404 | the dialog closes, the row leaves the list and the info toast "That site no longer exists" shows |
Rule: Authors list
Scenario Outline: Authors: default
Given the session role is "<role>"
And GET /v1/author/ answers 200 with the authors fixture
When the user navigates to /authors
Then the sidebar entry "Authors" sits between "Media" and "Users" and carries aria-current "page"
And the page shows "Authors", "The names readers see on your articles. An author doesn't need
an account.", a primary "Add author" button and the search field "Search by name or slug"
And the columns are "Author", "Slug", "Account" and "Articles"
And each row shows the avatar and name, the slug, a "Linked" or "Guest" badge, and
"9 articles", "1 article" or "No articles"
And a long name is truncated and shown in full on hover
And the first request is GET /v1/author/?page=1&size=25
Examples:
| role |
| owner |
| admin |
Scenario: Authors: loading
Given GET /v1/author/ is pending
When the user navigates to /authors
Then skeleton rows are drawn and the list has aria-busy "true"
Scenario Outline: Authors: error on load
Given GET /v1/author/ fails with <failure>
When the user navigates to /authors
Then an alert shows "Couldn't load authors", "Check your connection and try again." and "Try again"
When the user activates "Try again"
Then the list is requested again
Examples:
| failure |
| status 500 |
| a network error |
Scenario Outline: Authors: empty, first run
Given GET /v1/author/ answers 200 with total 0 and no search
And the session role is "<role>"
When the user navigates to /authors
Then the toolbar is hidden and the empty state shows "No authors yet" and "Authors are the names
readers see on articles. They don't need an account."
And <button>
Examples:
| role | button |
| owner | an "Add author" button is shown |
| admin | an "Add author" button is shown |
| member | no "Add author" button is shown |
Scenario: Authors: no results
Given the user has searched "zoe" and GET /v1/author/?q=zoe answers 200 with total 0
Then the state shows "No authors match \"zoe\"", "Check the spelling, or search for a shorter
part of the name." and "Clear search"
When the user activates "Clear search"
Then q leaves the URL and the full list is requested
Scenario: Authors: search and pagination in the URL
When the user types "cam" in the search field
Then after the debounce GET /v1/author/?q=cam&page=1&size=25 is sent and the URL holds q=cam
When the user opens /authors?q=camille&page=2&size=50
Then GET /v1/author/?q=camille&page=2&size=50 is sent
And the Articles paginator is shown only when total exceeds 25, with page sizes 5, 25, 50, 100
Scenario Outline: Authors: invalid page or size in the URL
When the user opens /authors?<query>
Then the invalid value is replaced by its default with no notice and the API 400 never reaches the user
Examples:
| query |
| size=30 |
| page=abc |
| page=0 |
Scenario: Authors: row menu (owner or admin)
When the user activates the ellipsis of "Camille Roche" (a guest)
Then a menu offers "Edit", "Link user" and "Delete…"
And for "Inès Duarte" (linked) the menu offers "Edit" and "Delete…"
And below md the menu is a bottom sheet
Scenario: Authors: read-only list (other roles)
Given the session role is "member"
When the user navigates to /authors
Then the description reads "The names readers see on your articles. Only an owner or admin can
change authors."
And there is no "Add author" button, no pinned bottom button, no row menu and no slide-over form
And search still works and each row shows a chevron
And the "Authors" sidebar entry is visible
Scenario: Authors: read-only detail
Given the session role is "member"
When the user opens the row "Inès Duarte"
Then a panel of the same width as the form shows "Inès Duarte", "Linked", "9 articles", "Bio",
"Website" and "Only an owner or admin can change this author."
And no field is editable, the account email is not shown and "Close" is the only action
When the user opens /authors?edit=ines-duarte
Then the same read-only detail opens
Rule: Authors form
Scenario: Authors form: add, empty
Given the session role is "owner" or "admin"
When the user activates "Add author"
Then a slide-over titled "Add author" opens, a 92 % bottom sheet below md
And it shows "Avatar (optional)" with "Choose image", Name (placeholder "e.g. Camille Roche"),
Slug (placeholder "Generated from the name"), "Bio (optional)" (placeholder "A sentence or two
about the author.") with the counter "0 / 280", "Website (optional)" (placeholder
"https://example.com"), "Social links (optional)" with "Add link" and "0 of 5", "Linked user
(optional)" showing "No linked user" with "Link a CMS user if this author has an account.
Guest writers need no link.", and a "Byline preview" ("Author name", "The bio appears here.")
And the buttons are "Cancel" and "Add author"
Scenario: Authors form: slug from the name
When the user types "Camille Roche" in Name
Then Slug shows "camille-roche" with an "Auto" badge, an "Edit slug" pencil and the help
"Generated from the name. Used in public author URLs and API paths. Unique across all authors."
And the byline preview shows the typed name
Scenario: Authors form: add succeeds
Given the form has name "Camille Roche", the automatic slug, a bio, a website and one link
When the user activates "Add author"
Then exactly one POST /v1/author/ is sent with name, slug "camille-roche", bio, avatar_id,
website, social_links [{type,url}] and user_id
And the button reads "Saving…" while it runs
And on 201 the slide-over closes and the author is listed
Scenario: Authors form: slug collision
Given the form has slug "camille-roche" and POST answers 409 author_slug_taken
Then Slug shows "The slug \"camille-roche\" is already used by another author.", a suggestion
"Use camille-roche-2" and "Reset to match the name"
And activating a suggestion rewrites the slug and keeps the other values
Scenario Outline: Authors form: validation
Given the Add author slide-over is open
When the user submits with <input>
Then no request is sent and <message> is shown under <field>
Examples:
| input | field | message |
| an empty name | Name | Enter a name. |
| a bio of 291 characters | Bio | Shorten the bio to 280 characters. with the counter "291 / 280" in error color |
| website "example.com" | Website | Enter a full URL starting with https://. |
| a social link with url "http://x" | its row | Enter a full URL starting with https://. |
Scenario Outline: Authors form: server validation codes
When the save answers <status> <code>
Then <message> is shown under <field>
Examples:
| status | code | field | message |
| 422 | bio_too_long | Bio | Shorten the bio to 280 characters. |
| 422 | invalid_url | the field | Enter a full URL starting with https://. |
| 409 | user_already_linked | Linked user | That user already has an author. Choose another user. |
Scenario: Authors form: social links
When the user activates "Add link"
Then a row with a type select (X, LinkedIn, GitHub, Mastodon, Custom) and a URL field is added
And the placeholders per type are "https://x.com/username", "https://www.linkedin.com/in/username",
"https://github.com/username", "https://mastodon.social/@username" and "https://example.com"
And an invalid link shows "Enter a full URL starting with https://."
And after the fifth row "Add link" is disabled and "You can add up to 5 links." is shown
And the links are sent as social_links with the lowercase types x, linkedin, github, mastodon, custom
Scenario: Authors form: linked user, choose
Given the options are the users of GET /v1/user/ minus every user_id found by paging
GET /v1/author/?size=100
When the user opens the Linked user select
Then under the title "Choose a user" the group "Users without an author" lists "Marta Alves"
with "marta@renew.example" and "Rui Santos" with "rui@renew.example"
And when no user is left it reads "Every user already has an author."
Scenario: Authors form: edit a linked author
When the user chooses "Edit" on "Inès Duarte"
Then the slide-over is titled "Edit Inès Duarte" with the fields filled
And Linked user shows "ines.duarte@renew.example" with "Unlink" and "New articles by this user
start with this author."
And the submit reads "Save changes"
And saving sends one PATCH /v1/author/{id} with only the changed fields
Scenario: Authors form: unlink
Given the edit form of "Inès Duarte" is open (owner or admin)
When the user activates "Unlink"
Then a dialog titled "Unlink Inès Duarte?" reads "Inès Duarte will stay on their articles. New
articles by ines.duarte@renew.example will no longer start with this author." with "Cancel"
and "Unlink user"
When the user activates "Unlink user"
Then exactly one PATCH /v1/author/{id} is sent with {"user_id": null}
And on 200 the field returns to "No linked user" and a toast shows "User unlinked" and
"Inès Duarte is now a guest author."
Scenario: Authors form: link a guest
When the user chooses "Link user" on "Camille Roche", in the row menu or the form
Then a dialog titled "Link Camille Roche to a user?" reads "Only users without an author are
listed." with the same user list, "Cancel" and "Link user"
When the user picks a user and activates "Link user"
Then exactly one PATCH /v1/author/{id} is sent with that user_id and the row shows "Linked"
Scenario: Authors form: avatar picker
When the user activates "Choose image"
Then the existing media picker opens titled "Choose an image" with "The avatar for Camille Roche."
and "Shown as a square. Choose an image with the face or logo near the middle." and "Use image"
When the user picks an image and activates "Use image"
Then the avatar shows as a square and avatar_id is sent on save
And the Sites default social image uses this same picker and sends default_social_image_id
Scenario Outline: Authors form: save failed
When the save fails with <failure>
Then a notice in the panel reads "Couldn't save the author. Your changes are still here. Try again in a moment."
And the values are kept
Examples:
| failure |
| status 500 |
| a network error |
Scenario: Authors form: role changed while open
When the save answers 403 author_rights
Then an error toast shows "Only an owner or admin can change authors" and "You can still edit
your own author profile."
Scenario: Authors form: deep link
When an owner or admin opens /authors?edit=camille-roche
Then the "Edit Camille Roche" slide-over opens
When the slug is unknown
Then an info toast shows "That author no longer exists" and nothing opens
Scenario: Authors form: own author, any role, by deep link only
Given the session role is "member" and GET /v1/auth/me carries an author with slug "ines-duarte"
When the user opens /authors?edit=ines-duarte
Then the form opens with the linked user locked, no "Unlink", no "Link user" and no delete action
And saving sends PATCH /v1/author/{id} with only the changed fields
When the same member opens /authors?edit=camille-roche
Then the read-only detail opens
Rule: Authors delete
Scenario: Authors delete: reassign (recommended)
When an owner or admin chooses "Delete…" on "Camille Roche" (id 7, 3 articles)
Then a dialog titled "Delete this author?" reads "\"Camille Roche\" will be deleted and is
credited on 3 articles. This can't be undone."
And "Credit these articles to" is preselected on the first other author, with "Where an article
has several authors, Camille Roche is removed and the others stay."
And the options come from GET /v1/author/?size=100 without the deleted author
And the buttons are "Cancel" and "Delete and reassign 3 articles"
And for a linked author the line "Linked to ines.duarte@renew.example. The user account isn't
affected." is added
Scenario: Authors delete: reassign succeeds
Given the dialog is open with destination "Inès Duarte" (id 2)
When the user activates "Delete and reassign 3 articles"
Then exactly one DELETE /v1/author/7?reassign_to=2 is sent
And the button reads "Reassigning…" while it runs
And on 204 the row leaves the list and a toast shows "Author deleted" and "3 articles now credit
Inès Duarte."
Scenario: Authors delete: choose who
When the user opens the select
Then the deleted author is not listed and the last option is "Nobody" with "Remove the byline"
Scenario: Authors delete: nobody
When the user chooses "Nobody"
Then the text "The articles keep any other authors. Articles with only this author will have no
byline." is shown
When the user confirms
Then DELETE /v1/author/7?reassign_to=none is sent
Scenario Outline: Authors delete: failed (notice shared by site and author delete)
Given an author delete dialog is open
When DELETE fails with <failure>
Then the dialog stays open with "Couldn't delete the author" and "Nothing was changed. Try again in a moment."
And the buttons are enabled again
Examples:
| failure |
| status 500 |
| a network error |
Scenario: Authors delete: server fallback (409)
When DELETE answers 409 author_has_articles
Then a dialog titled "Can't delete this author" reads "\"Camille Roche\" is credited on 3
articles. Choose another author to credit instead, or remove Camille Roche from those
articles first."
And its buttons are "Close" and "Reassign articles"
And "Reassign articles" reopens the reassign dialog
Scenario: Authors delete: no articles
When the user chooses "Delete…" on "Léa Fontaine"
Then a dialog titled "Delete this author?" reads "\"Léa Fontaine\" will be deleted. No articles
credit this author. This can't be undone." with "Cancel" and "Delete author" and no select
When the user confirms
Then DELETE /v1/author/{id} is sent with no reassign_to and the row leaves the list
Scenario: Authors delete: author already gone
When DELETE answers 404 author_not_found
Then the dialog closes, the row leaves the list and the info toast "That author no longer
exists" shows
Rule: Cross-cutting
Scenario Outline: Session problems use the app-wide handling
Given a load of <path> answers <status>
Then <outcome>
Examples:
| path | status | outcome |
| /authors | 401 | the user lands on /login?redirect=/authors&reason=expired |
| /settings/sites | 401 | the user lands on /login?redirect=/settings/sites&reason=expired |
| /authors | 403 (unverified) | the user lands on /register/pending |
Scenario: Slide-over accessibility
When a slide-over or dialog is open
Then focus moves into it, is trapped, and returns to the opening control on close
And Escape closes it unless a request is running
Scenario: Language: every string has a French entry
Given the language is "fr"
When the user opens each state of both screens
Then every visible string is the French message and none falls back to English
Scenario: Editor, Articles and Profile
Then their changes are specified in features/sites_authors_integration.feature