| 1 | import { assert, describe } from "@effect/vitest"; |
| 2 | |
| 3 | import { createOxlintRuleHarness } from "../test/utils.ts"; |
| 4 | |
| 5 | const rule = createOxlintRuleHarness("t3code/no-manual-effect-runtime-in-tests", { |
| 6 | filename: "fixture.test.ts", |
| 7 | }); |
| 8 | |
| 9 | describe("t3code/no-manual-effect-runtime-in-tests", () => { |
| 10 | rule.valid( |
| 11 | "allows @effect/vitest effect tests", |
| 12 | ` |
| 13 | import { it } from "@effect/vitest"; |
| 14 | import * as Effect from "effect/Effect"; |
| 15 | |
| 16 | it.effect("runs an Effect", () => Effect.succeed("ok")); |
| 17 | `, |
| 18 | ); |
| 19 | |
| 20 | const runtimeMethods = [ |
| 21 | "runCallback", |
| 22 | "runCallbackWith", |
| 23 | "runFork", |
| 24 | "runForkWith", |
| 25 | "runPromise", |
| 26 | "runPromiseExit", |
| 27 | "runPromiseExitWith", |
| 28 | "runPromiseWith", |
| 29 | "runSync", |
| 30 | "runSyncExit", |
| 31 | "runSyncExitWith", |
| 32 | "runSyncWith", |
| 33 | ] as const; |
| 34 | |
| 35 | for (const method of runtimeMethods) { |
| 36 | rule.invalid( |
| 37 | `reports Effect.${method}`, |
| 38 | ` |
| 39 | import * as Effect from "effect/Effect"; |
| 40 | |
| 41 | test("runs an Effect", () => { |
| 42 | Effect.${method}(Effect.succeed("ok")); |
| 43 | }); |
| 44 | `, |
| 45 | (output) => { |
| 46 | assert.match(output, /Use @effect\/vitest with it\.effect/); |
| 47 | }, |
| 48 | ); |
| 49 | } |
| 50 | |
| 51 | rule.invalid( |
| 52 | "reports ManagedRuntime.make", |
| 53 | ` |
| 54 | import * as Layer from "effect/Layer"; |
| 55 | import * as ManagedRuntime from "effect/ManagedRuntime"; |
| 56 | |
| 57 | test("makes a runtime", () => { |
| 58 | ManagedRuntime.make(Layer.empty); |
| 59 | }); |
| 60 | `, |
| 61 | ); |
| 62 | }); |
| 63 | |
| 64 | const productionRule = createOxlintRuleHarness("t3code/no-manual-effect-runtime-in-tests"); |
| 65 | |
| 66 | productionRule.valid( |
| 67 | "allows production runtime boundaries", |
| 68 | ` |
| 69 | import * as Effect from "effect/Effect"; |
| 70 | |
| 71 | export const main = () => Effect.runPromise(Effect.void); |
| 72 | `, |
| 73 | ); |
| 74 | |
| 75 | const legacyRule = createOxlintRuleHarness("t3code/no-manual-effect-runtime-in-tests", { |
| 76 | filename: "legacy.test.ts", |
| 77 | ruleOptions: [{ maxOccurrences: 2 }], |
| 78 | }); |
| 79 | |
| 80 | describe("t3code/no-manual-effect-runtime-in-tests with maxOccurrences", () => { |
| 81 | legacyRule.valid( |
| 82 | "allows occurrences up to the ceiling", |
| 83 | ` |
| 84 | import * as Effect from "effect/Effect"; |
| 85 | |
| 86 | test("first", () => Effect.runSync(Effect.void)); |
| 87 | test("second", () => Effect.runSync(Effect.void)); |
| 88 | `, |
| 89 | ); |
| 90 | |
| 91 | legacyRule.invalid( |
| 92 | "reports occurrences beyond the ceiling", |
| 93 | ` |
| 94 | import * as Effect from "effect/Effect"; |
| 95 | |
| 96 | test("first", () => Effect.runSync(Effect.void)); |
| 97 | test("second", () => Effect.runSync(Effect.void)); |
| 98 | test("third", () => Effect.runSync(Effect.void)); |
| 99 | `, |
| 100 | (output) => { |
| 101 | assert.equal(output.match(/no-manual-effect-runtime-in-tests/g)?.length, 1); |
| 102 | }, |
| 103 | ); |
| 104 | }); |