Files
RenewCMS/features/home.feature
T

126 lines
7.4 KiB
Gherkin

Feature: Home screen
As a logged-in RenewCMS owner
I want /home to summarize how many articles I have, how many are online or drafts, and my five
most recently updated articles, all from the single GET /v1/article/ call the route already
makes
So that I land somewhere useful after logging in, instead of an empty dashboard or a screen that
silently fails
Background:
Given /home is a verified route (meta.auth "verified") rendered as HomePage inside
DashboardShell, per docs/design/routes.md
And HomePage calls GET /v1/article/ once per navigation; there is no separate stats endpoint,
so the three stat tiles and the recent list are both derived from that one response
And the PageHeader shows breadcrumb "Home" (mobile title "Home") and a primary action "New
article" opening NewArticleModal
And a "Connect your website" card is always rendered on the page, in every state (Loading,
Default, Empty and Error alike): icon plug, title "Connect your website", text "Your site
reads published articles from RenewCMS. Share this guide with whoever builds it.", and a
link "Open the guide" navigating to /integration
And a greeting reading "{greeting}, {name}" sits above the subtitle in every state
(Loading, Default, Empty and Error alike); name is the session's display name when it is
not empty and the session's username otherwise; it is computed from that name and
the device's local hour via Date.getHours(), needs no request of its own since the session
is already resolved by the app-boot flow before HomePage ever renders, and so never has its
own loading or error state
And hours 0 through 11 give the greeting "Good morning", hours 12 through 17 give "Good
afternoon", and hours 18 through 23 give "Good evening"
And once the list resolves with at least one article, the subtitle reads "Here's where things
stand on your site.", three stat tiles show the total article count labelled "articles", the
online count labelled "online" and the draft count labelled "drafts", and a recent list shows
the 5 most recently updated articles, each with its title, an ArticleStatusBadge (online or
draft) and its updated date, linking to /article/:id/edit
And while the list request is in flight, skeleton placeholders replace the stat tiles and the
recent list rows, but only after 150 ms, so a fast response never flashes a skeleton
And when the list resolves with zero articles, the subtitle reads "Welcome to RenewCMS.", and
the stat tiles and recent list are replaced by an empty state: icon file-text, title "Write
your first article", text "It starts as a draft, so nothing appears on your site until you
publish it.", and a single action "New article" that opens NewArticleModal
And when the list request fails with a 500 or a network error, the breadcrumb, greeting and
subtitle stay visible, the subtitle stays "Here's where things stand on your site.", and the
stat tiles and recent list are replaced by an inline role="alert" banner: icon circle-x,
title "Couldn't load your articles", text "Check your connection and try again.", and a
single action "Try again"
Scenario: Skeletons appear only after 150 ms, never for a fast response
Given the user navigates to /home for the first time in this session
When GET /v1/article/ has not resolved 150 ms after the navigation
Then skeleton placeholders replace the three stat tiles and the five recent-list rows
And the recent list container is aria-busy="true"
When GET /v1/article/ then resolves 200 with a non-empty list of articles
Then the skeletons are replaced by the Default state's stat tiles and recent list
Given a second, separate navigation to /home
When GET /v1/article/ resolves in under 150 ms with a non-empty list of articles
Then no skeleton is ever shown, and the Default state's content renders directly
Scenario: Default — the list loaded with a mix of online and draft articles
Given GET /v1/article/ resolves 200 with 6 articles, 4 online and 2 drafts, most recently
updated first: "How we price a bathroom renovation" (online), "Winter checklist for timber
windows" (online), "Choosing tiles for a small bathroom" (draft), "A guide to underfloor
heating" (online), "When to reseal a stone worktop" (draft), and "Small bathroom lighting
ideas" (online, least recently updated)
When the user navigates to /home
Then the subtitle reads "Here's where things stand on your site."
And the stat tiles read "6" "articles", "4" "online" and "2" "drafts"
And the recent list shows exactly the first 5 articles above, in that order, each with its
ArticleStatusBadge and updated date, and each row links to its /article/:id/edit
And "Small bathroom lighting ideas" does not appear in the recent list
And the "Connect your website" card's "Open the guide" link navigates to /integration, and
the header's "New article" action opens NewArticleModal
Scenario: Empty, first run — zero articles
Given GET /v1/article/ resolves 200 with zero articles
When the user navigates to /home
Then the subtitle reads "Welcome to RenewCMS."
And no stat tiles are shown
And an empty state is shown in place of the recent list: icon file-text, title "Write your
first article", text "It starts as a draft, so nothing appears on your site until you
publish it.", and a single action "New article"
When the user activates "New article"
Then NewArticleModal opens
Scenario Outline: Error — a 500 or a network failure shows the same inline alert
Given GET /v1/article/ <failure>
When the user navigates to /home
Then the breadcrumb, greeting and subtitle remain visible, and the subtitle stays "Here's
where things stand on your site."
And no stat tiles or recent list are shown
And an inline alert with role="alert" is shown in their place: icon circle-x, title
"Couldn't load your articles", text "Check your connection and try again.", and a single
action "Try again"
Examples:
| failure |
| fails with a 500 response |
| never reaches the server |
Scenario: Retry re-issues the request and recovers into the Default state
Given the user is on /home in the Error state, because GET /v1/article/ failed
When the user activates "Try again"
Then GET /v1/article/ is called again
When it resolves 200 with 6 articles, 4 online and 2 drafts
Then the Alert is replaced by the stat tiles reading "6" "articles", "4" "online", "2" "drafts",
and the recent list
Scenario: The list is fetched exactly once per navigation
Given the user navigates to /home
Then GET /v1/article/ is called exactly once
And both the stat tiles and the recent list are derived from that single response, with no
second request made for either
Scenario Outline: The greeting matches the hour of day
Given the session's username is "marta" and it has no display name
And the device's local hour is <hour>
When the user views /home
Then the greeting above the subtitle reads "<greeting>, marta"
Examples:
| hour | greeting |
| 0 | Good morning |
| 11 | Good morning |
| 12 | Good afternoon |
| 17 | Good afternoon |
| 18 | Good evening |
| 23 | Good evening |