mirror of
https://github.com/stablyai/orca.git
synced 2026-09-22 00:02:31 +00:00
The rule rejects `vi.mock` / `vi.doMock` / `vi.unstable_mockModule` and the
`jest` equivalents, on the argument that a test which rewrites the module graph
asserts against a stand-in the production code never sees. It is already off for
`**/*.test.{ts,tsx}`, `**/*.spec.{ts,tsx}`, `tests/**` and `**/__mocks__/**` via
the existing override in config/oxlint-anti-slop.json; that override is
unchanged here. What the rule actually catches is module mocking that has drifted
out of a spec and into a first-party `.ts` support module, where nothing marks it
as test-only.
73 violations at baseline, all of them in test-support code. 9 were relocated
back into spec files the override already exempts; the remaining 64 sit in 10
files that are test-only but do not match the override globs, and carry a
file-level disable naming the rule and the reason.
Relocated:
- terminal-hydration-store-test-bootstrap.ts: the sonner / sync-runtime-graph /
pty-transport `vi.mock` calls moved into the two specs that import it
(terminals-hydration-canonical-rows, terminals-hydration-canonical-pty-overlap).
Vitest hoists `vi.mock` inside a test file, so registration is strictly earlier
than the previous module-eval-time call; the bootstrap keeps only the preload
API proxy. Both importers were updated.
- ipc-events-ssh-authority-test-fixtures.ts: the 6 direct-ssh `vi.doMock` calls
moved into useIpcEvents-agent-status-ssh-authority.test.ts as a local
`stubDirectSshModules()` helper, which also de-duplicates the three copies the
spec already had inline. The fixture now returns the store state and coordinator
doubles it builds, typed via the exported DirectSshReconnectCoordinatorDouble.
Suppressed, with justification (each is `/* oxlint-disable
anti-slop/no-module-mocking -- ... */`, rule named, no blanket disable):
- config/scripts/headless-serve-shutdown-matrix.test.mjs (1) - a genuine Vitest
spec that the override misses only because its globs say {ts,tsx}. The script
under test is a top-level CLI module; the alternative is spawning real docker.
- src/main/codex-accounts/runtime-home-service-test-harness.ts (1) - stubs one
probe predicate in ../pty/shell-startup-env, imported directly by several
main-process readers; 17 specs share it.
- src/main/computer/desktop-script-provider-test-harness.ts (2) - stubs
child_process/fs-promises for a provider that shells out; 8 specs share it.
- src/main/github/work-item-search-test-harness.ts (4) - one consumer lives in
tests/e2e, where the relative mock ids resolve differently, so moving the calls
into the specs would silently stop mocking there.
- src/renderer/src/components/automations/automations-page-test-harness.tsx (14)
- the mount rig for 10 AutomationsPage specs.
- src/renderer/src/components/terminal-pane/remote-runtime-pty-transport-test-harness.ts
(1) - stubs refreshWebRuntimeSessionTabsSnapshot, imported directly by several
renderer runtime modules; 18 specs share it.
- src/renderer/src/hooks/ipc-events-agent-status-window-test-fixtures.ts (7) -
stubReactSyncEffect/stubAuxiliaryModules, shared by 11 specs.
- src/renderer/src/hooks/ipc-events-close-routing-test-harness.ts (11) - stubs
and hook invocation are one unit; 4 specs share it.
- src/renderer/src/hooks/ipc-events-terminal-create-test-harness.ts (13) - its
only spec is at 799 of an 800 max-lines budget.
- src/renderer/src/hooks/ipc-events-test-harness.ts (10) - shared by 8 specs.
No violation was converted to real dependency injection, and no max-lines disable
was added.
Verified: the audit command exits 0 with no output (and reports errors on a
planted probe, so the rule is live); node config/scripts/run-typecheck-projects-in-parallel.mjs
exits 0; 354 spec files / 2506 tests covering every importer of every touched
file pass. No mobile/ file was touched.
The changed-code quality gate's root Oxlint scan runs without --config so it never
loads the anti-slop JS plugin, which made all 10 of those file-level suppressions
read as "Unused oxlint-disable directive". check-changed-code-quality.mjs now
exempts directives naming an anti-slop rule from that unused-directive warning,
the same carve-out isCastingDirectiveUnusedWarning already makes for the casting
suppressions the casting config enforces. Such a directive can never suppress a
root-config rule, so nothing the root scan would otherwise report is hidden;
audit:anti-slop remains the scan that enforces the rule.
157 lines
5.8 KiB
JavaScript
157 lines
5.8 KiB
JavaScript
import { mkdtempSync, rmSync, writeFileSync } from 'node:fs'
|
|
import path from 'node:path'
|
|
import { describe, expect, it } from 'vitest'
|
|
import {
|
|
OXLINT_SCANS,
|
|
diagnosticTouchesAddedLines,
|
|
isAntiSlopDirectiveUnusedWarning,
|
|
isMovedCode,
|
|
isRootCodeQualityPath,
|
|
overlapsAddedLines,
|
|
parseAddedLineRanges
|
|
} from './check-changed-code-quality.mjs'
|
|
|
|
describe('changed-code quality line matching', () => {
|
|
it('parses added and replaced hunk ranges while ignoring deletions', () => {
|
|
const ranges = parseAddedLineRanges(
|
|
['@@ -10,2 +10,3 @@', '@@ -20 +21 @@', '@@ -40,4 +42,0 @@', '@@ -50 +48,2 @@'].join('\n')
|
|
)
|
|
|
|
expect(ranges).toEqual([
|
|
{ start: 10, end: 12 },
|
|
{ start: 21, end: 21 },
|
|
{ start: 48, end: 49 }
|
|
])
|
|
})
|
|
|
|
it('matches diagnostics that overlap any added line', () => {
|
|
const ranges = [
|
|
{ start: 5, end: 7 },
|
|
{ start: 12, end: 12 }
|
|
]
|
|
|
|
expect(overlapsAddedLines(3, 5, ranges)).toBe(true)
|
|
expect(overlapsAddedLines(8, 11, ranges)).toBe(false)
|
|
expect(overlapsAddedLines(12, 14, ranges)).toBe(true)
|
|
})
|
|
|
|
it('normalizes absolute diagnostic paths before matching', () => {
|
|
const root = process.cwd()
|
|
const file = 'config/scripts/check-changed-code-quality.test.mjs'
|
|
const diagnostic = {
|
|
filename: `${root}/${file}`,
|
|
labels: [{ span: { line: 24 } }]
|
|
}
|
|
|
|
expect(
|
|
diagnosticTouchesAddedLines(diagnostic, new Map([[file, [{ start: 24, end: 24 }]]]), root)
|
|
).toBe(true)
|
|
})
|
|
|
|
// Why: pinning --config disables nested-config discovery, so root rules that
|
|
// mobile/.oxlintrc.json turns off would fail the gate on mobile files.
|
|
it('lets the untyped scan discover nested configs instead of pinning the root config', () => {
|
|
const scan = OXLINT_SCANS.find((candidate) => candidate.label === 'code quality')
|
|
|
|
expect(scan.args).not.toContain('--config')
|
|
expect(scan.args).not.toContain('--disable-nested-config')
|
|
})
|
|
|
|
it('leaves Cloud source to the independent Cloud quality checks', () => {
|
|
expect(isRootCodeQualityPath('cloud/apps/relay/src/index.ts')).toBe(false)
|
|
expect(isRootCodeQualityPath('src/main/index.ts')).toBe(true)
|
|
})
|
|
})
|
|
|
|
describe('moved-code exemption', () => {
|
|
it('treats a verbatim contiguous block from the base as moved', () => {
|
|
const base = [['const a = 1', 'items.map((item, index) => (', 'key={index}', '))']]
|
|
expect(isMovedCode(['items.map((item, index) => (', 'key={index}', '))'], base)).toBe(true)
|
|
})
|
|
|
|
it('ignores indentation and whitespace changes from the move', () => {
|
|
const base = [[' items.map((item, index) => (', ' key={index}']]
|
|
expect(isMovedCode(['items.map((item, index) => (', 'key={index}'], base)).toBe(true)
|
|
})
|
|
|
|
it('does not exempt a genuinely new violation', () => {
|
|
const base = [['const a = 1', 'const b = 2']]
|
|
expect(isMovedCode(['rows.map((row, i) => <td key={i} />)'], base)).toBe(false)
|
|
})
|
|
|
|
it('does not exempt a block that is only partly present in the base', () => {
|
|
const base = [['doThing()', 'unrelated()']]
|
|
expect(isMovedCode(['doThing()', 'newlyAddedSideEffect()'], base)).toBe(false)
|
|
})
|
|
|
|
it('tolerates a few lines appended inside the moved block', () => {
|
|
// A split commonly grows a hook dependency array when closure variables
|
|
// become props; the moved body around it is still moved.
|
|
const body = Array.from({ length: 20 }, (_, i) => `line${i}()`)
|
|
const base = [body]
|
|
const moved = [...body.slice(0, 19), 'newDep,', body[19]]
|
|
expect(isMovedCode(moved, base)).toBe(true)
|
|
})
|
|
|
|
it('does not exempt when the anchor line is absent from the base', () => {
|
|
const base = [['doThing()', 'filler()', 'other()']]
|
|
expect(isMovedCode(['brandNewCall()', 'doThing()', 'other()'], base)).toBe(false)
|
|
})
|
|
|
|
it('does not exempt when most of the block is absent from the base', () => {
|
|
const base = [['keep0()', 'keep1()', 'unrelated()']]
|
|
const mostlyNew = ['keep0()', ...Array.from({ length: 18 }, (_, i) => `fresh${i}()`)]
|
|
expect(isMovedCode(mostlyNew, base)).toBe(false)
|
|
})
|
|
|
|
it('ignores blank lines when matching', () => {
|
|
const base = [['a()', 'b()']]
|
|
expect(isMovedCode(['a()', '', 'b()'], base)).toBe(true)
|
|
})
|
|
|
|
it('never exempts an empty highlight', () => {
|
|
expect(isMovedCode(['', ' '], [['a()']])).toBe(false)
|
|
})
|
|
})
|
|
|
|
describe('anti-slop directive unused warning', () => {
|
|
const root = path.resolve(import.meta.dirname, '..', '..')
|
|
// Assembled so no line here is itself a directive the gate would scan.
|
|
const directive = (rule) => `/* oxlint-disable ${rule} -- reason */`
|
|
|
|
const withFixture = (firstLine, assert) => {
|
|
const directory = mkdtempSync(path.join(root, 'config', 'anti-slop-directive-test-'))
|
|
try {
|
|
const file = path.join(directory, 'fixture.ts')
|
|
writeFileSync(file, [firstLine, 'export const value = 1', ''].join('\n'))
|
|
assert({
|
|
message: 'Unused oxlint-disable directive (no problems were reported).',
|
|
filename: file,
|
|
labels: [{ span: { line: 1 } }]
|
|
})
|
|
} finally {
|
|
rmSync(directory, { recursive: true, force: true })
|
|
}
|
|
}
|
|
|
|
it('exempts a suppression the root scan cannot resolve', () => {
|
|
withFixture(directive('anti-slop/no-module-mocking'), (diagnostic) => {
|
|
expect(isAntiSlopDirectiveUnusedWarning(diagnostic, root)).toBe(true)
|
|
})
|
|
})
|
|
|
|
it('still reports an unused directive for a rule the root scan does load', () => {
|
|
withFixture(directive('unicorn/no-array-reduce'), (diagnostic) => {
|
|
expect(isAntiSlopDirectiveUnusedWarning(diagnostic, root)).toBe(false)
|
|
})
|
|
})
|
|
|
|
it('ignores diagnostics that are not unused-directive warnings', () => {
|
|
withFixture(directive('anti-slop/no-module-mocking'), (diagnostic) => {
|
|
expect(
|
|
isAntiSlopDirectiveUnusedWarning({ ...diagnostic, message: 'Unexpected any.' }, root)
|
|
).toBe(false)
|
|
})
|
|
})
|
|
})
|