1import { describe } from "@effect/vitest";
2
3import { createOxlintRuleHarness } from "../test/utils.ts";
4
5const rule = createOxlintRuleHarness("t3code/no-manual-memo", {
6 filename: "fixture.tsx",
7});
8
9describe("t3code/no-manual-memo", () => {
10 rule.valid("allows plain derived values", `const total = items.length * 2;`);
11
12 rule.valid("allows useStableCallback", `const onClick = useStableCallback(() => save());`);
13
14 rule.valid("allows other React members", `const ref = React.useRef(null);`);
15
16 rule.valid("allows other directives", `function Panel() { "use client"; return null; }`);
17
18 rule.invalid(
19 'reports a "use memo" directive',
20 `function useTotal(items) { "use memo"; return items.length; }`,
21 );
22
23 rule.invalid("reports useMemo", `const total = useMemo(() => items.length, [items]);`);
24
25 rule.invalid("reports useCallback", `const onClick = useCallback(() => save(), []);`);
26
27 rule.invalid(
28 "reports React.useMemo",
29 `const total = React.useMemo(() => items.length, [items]);`,
30 );
31
32 rule.invalid('reports "use no memo"', `function Panel() { "use no memo"; return null; }`);
33
34 rule.invalid('reports a module-level "use no forget"', `"use no forget";\nexport const a = 1;`);
35
36 rule.valid("allows the same text as a string value", `const label = "use no memo";`);
37});
38
39const ratchet = createOxlintRuleHarness("t3code/no-manual-memo", {
40 filename: "fixture.tsx",
41 ruleOptions: [{ allowMemoHooks: true }],
42});
43
44describe("t3code/no-manual-memo with allowMemoHooks", () => {
45 ratchet.valid("allows useMemo", `const total = useMemo(() => items.length, [items]);`);
46
47 ratchet.valid("allows useCallback", `const onClick = useCallback(() => save(), []);`);
48
49 ratchet.invalid(
50 'still reports "use no memo"',
51 `function Panel() { "use no memo"; return null; }`,
52 );
53});