126 lines
7.4 KiB
Gherkin
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 |
|