Skip to content
Source
Sign inSign up

no-unreasoned-state-sync.test.ts

56 lines1.6 KB

1import { assert, describe } from "@effect/vitest";
2​
3import { createOxlintRuleHarness } from "../test/utils.ts";
4​
5const reports = (output: string) =>
6 output.match(/t3code\(no-unreasoned-state-sync\)/g)?.length ?? 0;
7const lint = (filename: string) =>
8 createOxlintRuleHarness("t3code/no-unreasoned-state-sync", { filename });
9​
10const component = lint("apps/web/src/Panel.tsx");
11​
12describe("t3code/no-unreasoned-state-sync", () => {
13 component.invalid(
14 "reports every effect hook, including member calls",
15 `import React, { useEffect } from "react";
16export function Panel() {
17 useEffect(() => {}, []);
18 React.useLayoutEffect(() => {});
19 React.useInsertionEffect(() => {});
20 return null;
22`,
23 (output) => assert.strictEqual(reports(output), 3),
24 );
25​
26 component.valid(
27 "ignores comments, strings and lookalike names",
28 `// useEffect(() => {}) in a comment
29/* React.useLayoutEffect(() => {}) */
30const label = "useEffect(() => {})";
31const pipeline = Effect.matchCauseEffect(effect, {});
32const alias = useEffect;
33`,
34 );
35​
36 component.valid(
37 "accepts an effect whose suppression states its reason",
38 `export function Panel() {
39 // oxlint-disable-next-line t3code/no-unreasoned-state-sync -- subscribes to the window's resize events
40 React.useEffect(() => {});
41 return null;
43`,
44 );
45​
46 for (const filename of [
47 "apps/web/src/Panel.test.tsx",
48 "apps/web/src/Panel.spec.tsx",
49 "apps/web/tests/Panel.tsx",
50 ]) {
51 lint(filename).valid(
52 `skips ${filename}`,
53 `export function Panel() { useEffect(() => {}); return null; }`,
54 );
55 }
56});