1import { assert, describe } from "@effect/vitest";
2
3import { createOxlintRuleHarness } from "../test/utils.ts";
4
5const rule = createOxlintRuleHarness("t3code/no-native-title-tooltip", {
6 filename: "fixture.tsx",
7});
8
9describe("t3code/no-native-title-tooltip", () => {
10 rule.valid(
11 "allows intrinsic elements without a title attribute",
12 `const el = <span className="truncate">Truncated text</span>;`,
13 );
14
15 rule.valid(
16 "allows title props on custom components",
17 `const el = <SettingsRow id="word-wrap" title="Word wrap" description="Wrap long lines." />;`,
18 );
19
20 rule.valid(
21 "allows title on member expression components",
22 `const el = <Foo.Bar title="Not a native tooltip" />;`,
23 );
24
25 rule.valid(
26 "allows title as an accessible name on embedded content",
27 `const el = <iframe title="Embedded widget" src="https://example.com" />;`,
28 );
29
30 rule.valid("allows the svg title child element", `const el = <svg><title>QR code</title></svg>;`);
31
32 rule.valid("allows document.title assignments", `document.title = "Thread · T3 Code";`);
33
34 rule.invalid(
35 "reports title on a truncating span",
36 `const el = <span className="min-w-0 truncate" title="Full repository name">Repo</span>;`,
37 (output) => {
38 assert.match(output, /native title attribute/);
39 },
40 );
41
42 rule.invalid(
43 "reports title on a button",
44 `const el = <button type="button" aria-label="Scroll to end" title="Scroll to end" />;`,
45 (output) => {
46 assert.match(output, /Tooltip \+ TooltipTrigger \+ TooltipPopup/);
47 },
48 );
49
50 rule.invalid(
51 "reports title on a paragraph",
52 `const el = <p className="truncate text-xs" title={path}>src/main.ts</p>;`,
53 );
54
55 rule.invalid(
56 "reports title on a code element",
57 `const el = <code className="truncate" title={pairingUrl}>abc</code>;`,
58 );
59
60 rule.invalid("reports title on an anchor", `const el = <a href="#" title="Learn more">More</a>;`);
61});