@jsenv/navi 0.29.155 → 0.29.156

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/docs/testid.md CHANGED
@@ -78,6 +78,27 @@ than to the box around it (`id`, `name`, `type`, `value`, `tabIndex`,
78
78
  so a `data-test-id` or a `data-qa` of your own would name the wrapper, which is
79
79
  the second reason to keep the standard spelling.
80
80
 
81
+ `aria-label` and `aria-labelledby` take the same road, and for the reason the
82
+ section above gives: the name has to be where the role is. The root box has no
83
+ role — it is a wrapper — so a name left on it would be announced by nothing and
84
+ found by nothing, while the host is what the user focuses and what
85
+ `getByRole(role, { name })` and `getByLabel()` read.
86
+
87
+ ```jsx
88
+ <Picker variant="icon" aria-label="Aide" ui={<Icon>…</Icon>} />
89
+ ```
90
+
91
+ ```html
92
+ <div class="navi_picker" navi-control="picker" aria-expanded="false">
93
+ <input navi-control-host="picker" aria-label="Aide" readonly />
94
+ </div>
95
+ ```
96
+
97
+ Which role that host answers to is the control's own: a picker's host is an
98
+ `<input>` (`textbox`), a button's is a `<button>`. A picker trigger is not
99
+ `getByRole("button")`, whatever it is drawn like — target its name, or give it
100
+ a `data-testid`.
101
+
81
102
  When the wrapper IS what the test wants — a whole field with its label and its
82
103
  error message, a section, a row — put the testid on the surrounding component
83
104
  (`<Field data-testid="email-field">`, `<Box data-testid="cart-row">`); anything
@@ -97,7 +118,32 @@ Most tests do not need it — a testid on what the popup holds (`<Box
97
118
  data-testid="place-pick">` among the children) names the screen, not the frame,
98
119
  and is the better name for a test that reads or clicks the content. Reach for
99
120
  `popupTestId` when the frame IS what the test looks at: a screenshot of the
100
- popup's surface, its position, its size, its backdrop.
121
+ popup's surface, its position, its size, its backdrop. It names the popup in
122
+ every mode, including `mode="callout"`, where the frame is a callout rather
123
+ than a sheet.
124
+
125
+ ## A callout is a role first
126
+
127
+ A callout — a control's `readOnlyMessage` or failing constraint, a
128
+ `mode="callout"` picker, a direct `openCallout()` — is drawn by navi from end to
129
+ end: the application supplies the sentence and nothing else, so there is often
130
+ nothing of its own to name. It carries a role for that, and the role is the
131
+ contract: `alert` when it says something went wrong (`warning`, `error`),
132
+ `status` otherwise (`info`, `success`, or no status at all).
133
+
134
+ ```js
135
+ await page.getByRole("button", { name: "Publier" }).click();
136
+ await expect(page.getByRole("alert")).toHaveText("Il manque le lieu");
137
+ ```
138
+
139
+ That is not a testing convenience: a message appearing without the user asking
140
+ for it is what a live region is for, and the role is what makes a screen reader
141
+ read it out. A test targeting it asserts that.
142
+
143
+ When the role is not enough — two callouts up at once, a screenshot of one
144
+ particular surface — `openCallout` takes a `testId`, and a picker's
145
+ `popupTestId` covers the one it opens. Waiting on `.navi_callout` is the thing
146
+ to replace: it is a navi class like any other.
101
147
 
102
148
  `<ControlSwap.Side>` answers the same situation the other way: the cap at the
103
149
  end of the row is drawn by navi, and every prop the side does not use for
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jsenv/navi",
3
- "version": "0.29.155",
3
+ "version": "0.29.156",
4
4
  "type": "module",
5
5
  "description": "Library of components including navigation to create frontend applications",
6
6
  "repository": {