110 lines
7.3 KiB
Gherkin
110 lines
7.3 KiB
Gherkin
Feature: Variants and Media screens match the merged design: visual setups, and the variant form as a bottom sheet on mobile
|
||
|
||
As the maintainer of RenewCMS
|
||
I want the visual check to cover every state of the image variants screens, and the variant form to follow the overlay pattern
|
||
So that the SPA matches the merged design on desktop and mobile, in light and dark
|
||
|
||
Background:
|
||
Given the spec of record is docs/design/screens/image-variants.md, docs/design/screens/media.md, docs/design/screens/media-picker.md, docs/design/states.md, docs/design/routes.md and the overlay pattern of docs/design/components.md
|
||
And this slice is SPA only: no Go file, route or API contract changes
|
||
And the behaviours of features/image_variants_media_screens.feature, features/image_variants_screens.feature and features/image_variants_editor_picker.feature stay as they are except where this file says so
|
||
And the merged board is "RenewCMS Screens Back-office.dc.html" and web/visual/check.ts already points to it, with state names in the form "V1a · Loaded"
|
||
And every new English string has a French entry in web/src/i18n/messages.ts, the page uses Nuxt UI components and design tokens only, and no comment is added to any file
|
||
And the session is the owner "Marta Alves" unless a scenario says otherwise
|
||
|
||
Rule: Every state of the six groups has a visual setup that passes
|
||
|
||
Scenario Outline: A group of the merged board is fully covered
|
||
Given the group "<group>" of the merged board lists the states "<states>"
|
||
When "task visual:check -- image-variants" runs
|
||
Then each of those states has a setup in web/visual/states.ts keyed by its exact board name
|
||
And each capture prints PASS at desktop and mobile, in light and dark, within 10 %
|
||
And no /v1 call is left unmocked and no size mismatch is reported
|
||
|
||
Examples:
|
||
| group | states |
|
||
| Variants list | V1a to V1l |
|
||
| Add edit variant | V2a to V2k |
|
||
| Media library | V3a to V3f |
|
||
| Image detail | V4a to V4h |
|
||
| Cache panel | V5a to V5j |
|
||
| Editor picker | V6a to V6e |
|
||
|
||
Scenario: Setups reuse the board's own sample data
|
||
Then each setup mocks /v1 with the titles, names, sizes, counts and variant rows drawn in the board frame
|
||
|
||
Scenario: Clock-sensitive states are skipped, not tuned
|
||
Given a state whose rendering depends on the current date or time
|
||
Then its setup carries skip: 'clock-sensitive', the check prints SKIP and no Vitest spec freezes the system date
|
||
|
||
Scenario: No visual exception is added without the user's approval
|
||
Given a capture cannot get within 10 %
|
||
Then the setup or the SPA is fixed
|
||
And no "exception" entry is added unless the user approved it explicitly (approvedBy)
|
||
|
||
Scenario: The gate is hard
|
||
When any capture exceeds 10 %, a state has no setup, or a /v1 call is unmocked
|
||
Then "task visual:check -- image-variants" exits non-zero
|
||
|
||
Rule: The Media library V3 states render the existing variants filter and total-size sort
|
||
|
||
The filter, the sort and their request parameters already exist. Media code changes only if a V3 capture fails the check.
|
||
|
||
Scenario Outline: The V3 states render the filter and the sort
|
||
Given the 12-image fixture of features/image_variants_media_screens.feature
|
||
When the setup of "<state>" is loaded on /media
|
||
Then the SPA shows "<visible>"
|
||
And GET /v1/media/ carries "<request>"
|
||
|
||
Examples:
|
||
| state | visible | request |
|
||
| V3a · Grid with badges | "N variants" badges on cards with cached files, none on cards without, "All" selected | no variants parameter |
|
||
| V3b · Sort menu | sort menu open, "Largest total size (original + variants)" last | n/a |
|
||
| V3c · Filter: With variants, sorted by total size | "With variants" selected, meta lines "total · original + variants" | variants=with&sort=total_size |
|
||
| V3d · Filter: Without variants | "Without" selected, no variants badge | variants=without |
|
||
| V3e · Filter: nothing to show | "With variants" selected, empty cache, "No images with variants" | variants=with |
|
||
|
||
Scenario: Existing filter and sort behaviour is unchanged
|
||
Then the URL, request and meta-line behaviour of "The variants filter" and "Sorting by total size" in features/image_variants_media_screens.feature still holds
|
||
|
||
Rule: The variant form follows the overlay pattern
|
||
|
||
Scenario: Add variant is a right slide-over on desktop
|
||
Given the viewport is 640 px wide or more
|
||
When the admin activates "Add variant"
|
||
Then the form opens as a slide-over 960 px wide at the right over the scrim, full height, with the list behind it
|
||
And the header has the title and a close button (x icon, accessible name "Close")
|
||
And the form is on the left and the live preview on the right
|
||
|
||
Scenario: Add variant is a tall bottom sheet on mobile
|
||
Given the viewport is below 640 px
|
||
When the admin activates "Add variant"
|
||
Then the form opens as a bottom sheet flush to the bottom, full width, 92 % of the viewport height
|
||
And a grabber (36 × 4, --ui-border-accented) is drawn at the top, with a close x button (44 px) in the header
|
||
And it is not a full page: the list stays visible above the sheet behind the scrim
|
||
And the Preview section is stacked under the form and the body scrolls
|
||
And the footer is sticky with "Cancel" and the primary action sharing the width, 44 px high
|
||
|
||
Scenario: Edit uses the same container
|
||
When the admin chooses "Edit" on the row "hero"
|
||
Then the form opens in the same container as Add variant at the current viewport and the title is "Edit variant: hero"
|
||
|
||
Scenario Outline: Dismissing the mobile sheet
|
||
Given the viewport is below 640 px
|
||
When the user <gesture>
|
||
Then <result>
|
||
|
||
Examples:
|
||
| gesture | result |
|
||
| closes a pristine form with x or Cancel | the sheet closes with no dialog and focus returns to the opener |
|
||
| swipes down or taps the scrim, pristine | the sheet closes |
|
||
| closes a dirty form (x, Cancel, Escape, swipe, scrim) | the "Discard changes?" dialog opens and the sheet stays |
|
||
| any dismissal while Saving | nothing closes |
|
||
|
||
Scenario: Mobile no longer shows a back arrow
|
||
Given the viewport is below 640 px
|
||
Then no arrow-left back button is in the form header
|
||
|
||
Scenario: Focus
|
||
Then focus is trapped in the sheet or slide-over and returns to the opener on close, and on open it moves to the Name field in create mode
|