Skip to content

Commit ce7e69b

Browse files
test(focus-announcer): cover empty and clipped render behavior (#311)
* test(focus-announcer): cover empty and clipped render behavior * test(focus-announcer): address review feedback
1 parent 8450f87 commit ce7e69b

File tree

2 files changed

+35
-1
lines changed

2 files changed

+35
-1
lines changed

docs/widgets/focus-announcer.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ ui.focusAnnouncer({
2626
- Uses semantic labels when provided via `accessibleLabel`.
2727
- Includes `field` metadata in announcements (for example required/error context).
2828
- Renders `emptyText` when focus is `null`.
29+
- Renders nothing when both the computed announcement and `emptyText` are empty.
30+
- Draws a single line and clips long announcements to the available width with ellipsis.
2931

3032
## Example
3133

packages/core/src/widgets/__tests__/basicWidgets.render.test.ts

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,12 @@ import {
33
parseDrawTextCommands as parseDecodedDrawTextCommands,
44
parseInternedStrings,
55
} from "../../__tests__/drawlistDecode.js";
6-
import { type DrawlistBuilder, type VNode, createDrawlistBuilder } from "../../index.js";
6+
import {
7+
type DrawlistBuilder,
8+
type VNode,
9+
createDrawlistBuilder,
10+
truncateWithEllipsis,
11+
} from "../../index.js";
712
import { layout } from "../../layout/layout.js";
813
import { renderToDrawlist } from "../../renderer/renderToDrawlist.js";
914
import { commitVNodeTree } from "../../runtime/commit.js";
@@ -242,6 +247,33 @@ describe("basic widgets render to drawlist", () => {
242247
assert.equal(fallback.includes("No focus"), true);
243248
});
244249

250+
test("focusAnnouncer renders nothing when both announcement and fallback are empty", () => {
251+
const commands = parseDrawTextCommands(
252+
renderBytes(ui.focusAnnouncer(), { cols: 40, rows: 4 }, {}),
253+
);
254+
assert.equal(commands.length, 0);
255+
});
256+
257+
test("focusAnnouncer clips long text to the available width", () => {
258+
const announcement = "Email input ready";
259+
const clippedAnnouncement = parseDrawTextCommands(
260+
renderBytes(ui.focusAnnouncer(), { cols: 8, rows: 2 }, { focusAnnouncement: announcement }),
261+
);
262+
assert.deepEqual(
263+
clippedAnnouncement.map((command) => command.text),
264+
[truncateWithEllipsis(announcement, 8)],
265+
);
266+
267+
const fallback = "No focus selected";
268+
const clippedFallback = parseDrawTextCommands(
269+
renderBytes(ui.focusAnnouncer({ emptyText: fallback }), { cols: 7, rows: 2 }, {}),
270+
);
271+
assert.deepEqual(
272+
clippedFallback.map((command) => command.text),
273+
[truncateWithEllipsis(fallback, 7)],
274+
);
275+
});
276+
245277
test("input renders placeholder text when value is empty", () => {
246278
const strings = parseInternedStrings(
247279
renderBytes(

0 commit comments

Comments
 (0)