diff --git a/.changeset/fix-lint-warnings.md b/.changeset/fix-lint-warnings.md new file mode 100644 index 00000000..a845151c --- /dev/null +++ b/.changeset/fix-lint-warnings.md @@ -0,0 +1,2 @@ +--- +--- diff --git a/packages/bundler/src/utils/clean.test.ts b/packages/bundler/src/utils/clean.test.ts index 01d9f65f..34cb4ced 100644 --- a/packages/bundler/src/utils/clean.test.ts +++ b/packages/bundler/src/utils/clean.test.ts @@ -38,7 +38,7 @@ function makeResolved( } } -describe('clean', () => { +describe(clean, () => { beforeEach(() => { mkdirSync(testDir, { recursive: true }) }) @@ -65,8 +65,8 @@ describe('clean', () => { expect(result.removed).toContain('index.js') expect(result.removed).toContain('index.js.map') - expect(existsSync(join(testDir, 'index.js'))).toBe(false) - expect(existsSync(join(testDir, 'index.js.map'))).toBe(false) + expect(existsSync(join(testDir, 'index.js'))).toBeFalsy() + expect(existsSync(join(testDir, 'index.js.map'))).toBeFalsy() }) it('should preserve foreign files and report them', async () => { @@ -77,7 +77,7 @@ describe('clean', () => { expect(result.removed).toContain('index.js') expect(result.foreign).toContain('README.md') - expect(existsSync(join(testDir, 'README.md'))).toBe(true) + expect(existsSync(join(testDir, 'README.md'))).toBeTruthy() }) it('should not remove extensionless files when compile is false', async () => { @@ -86,7 +86,7 @@ describe('clean', () => { const result = await clean({ resolved: makeResolved(), compile: false }) expect(result.foreign).toContain('cli-darwin-arm64') - expect(existsSync(join(testDir, 'cli-darwin-arm64'))).toBe(true) + expect(existsSync(join(testDir, 'cli-darwin-arm64'))).toBeTruthy() }) it('should remove exact binary names when compile is true', async () => { @@ -107,9 +107,9 @@ describe('clean', () => { expect(result.removed).toContain('my-app-darwin-arm64') expect(result.removed).toContain('my-app-linux-x64') expect(result.foreign).toContain('README.md') - expect(existsSync(join(testDir, 'my-app-darwin-arm64'))).toBe(false) - expect(existsSync(join(testDir, 'my-app-linux-x64'))).toBe(false) - expect(existsSync(join(testDir, 'README.md'))).toBe(true) + expect(existsSync(join(testDir, 'my-app-darwin-arm64'))).toBeFalsy() + expect(existsSync(join(testDir, 'my-app-linux-x64'))).toBeFalsy() + expect(existsSync(join(testDir, 'README.md'))).toBeTruthy() }) it('should remove windows .exe binary names in multi-target builds', async () => { diff --git a/packages/cli/src/lib/config-helpers.test.ts b/packages/cli/src/lib/config-helpers.test.ts index e9786795..0d61df10 100644 --- a/packages/cli/src/lib/config-helpers.test.ts +++ b/packages/cli/src/lib/config-helpers.test.ts @@ -2,7 +2,7 @@ import { describe, expect, it } from 'vitest' import { extractConfig } from './config-helpers.js' -describe('extractConfig', () => { +describe(extractConfig, () => { it('should return the config from a non-null result', () => { const result = { config: { entry: './src/main.ts' }, configFile: '/project/kidd.config.ts' } diff --git a/packages/cli/tsdown.config.ts b/packages/cli/tsdown.config.ts index 507dff8d..3a7519c2 100644 --- a/packages/cli/tsdown.config.ts +++ b/packages/cli/tsdown.config.ts @@ -4,7 +4,7 @@ export default defineConfig({ clean: true, deps: { // Bundle @kidd-cli/* packages so the published CLI is self-contained and - // does not depend on workspace packages being published with correct exports. + // Does not depend on workspace packages being published with correct exports. alwaysBundle: [/^@kidd-cli\//], // Keep packages with native bindings external — they cannot be inlined. neverBundle: ['tsdown', /^@rolldown\//, /^rolldown/], diff --git a/packages/core/src/context/resolve-defaults.test.ts b/packages/core/src/context/resolve-defaults.test.ts index b3589006..31679457 100644 --- a/packages/core/src/context/resolve-defaults.test.ts +++ b/packages/core/src/context/resolve-defaults.test.ts @@ -58,9 +58,10 @@ describe('mergeClackOpts()', () => { }) }) +// eslint-disable-next-line vitest/prefer-describe-function-title -- constant, not a function describe('EMPTY_CLACK_BASE', () => { it('should be a frozen empty object', () => { - expect(Object.isFrozen(EMPTY_CLACK_BASE)).toBe(true) + expect(Object.isFrozen(EMPTY_CLACK_BASE)).toBeTruthy() expect(Object.keys(EMPTY_CLACK_BASE)).toEqual([]) }) }) diff --git a/packages/core/src/context/status.test.ts b/packages/core/src/context/status.test.ts index 1bfec746..0a0c03d3 100644 --- a/packages/core/src/context/status.test.ts +++ b/packages/core/src/context/status.test.ts @@ -57,7 +57,7 @@ beforeEach(() => { describe('createContextStatus()', () => { it('should return a frozen object', () => { const status = createContextStatus() - expect(Object.isFrozen(status)).toBe(true) + expect(Object.isFrozen(status)).toBeTruthy() }) it('should have spinner, progress, tasks, and taskLog', () => { @@ -200,8 +200,8 @@ describe('createContextStatus()', () => { it('should convert readonly frames to a mutable array', () => { const frames = ['a', 'b', 'c'] as const createContextStatus({ spinnerConfig: { frames } }) - const call = (clack.spinner as Mock).mock.calls[0][0] - expect(Array.isArray(call.frames)).toBe(true) + const [[call]] = (clack.spinner as Mock).mock.calls + expect(Array.isArray(call.frames)).toBeTruthy() expect(call.frames).toEqual(['a', 'b', 'c']) }) diff --git a/packages/core/src/context/status.ts b/packages/core/src/context/status.ts index a01e35f7..dd269056 100644 --- a/packages/core/src/context/status.ts +++ b/packages/core/src/context/status.ts @@ -89,7 +89,7 @@ export function createContextStatus(options?: CreateContextStatusOptions): Statu async tasks(tasks: readonly TaskDef[]): Promise { // Accepted exception: kidd's TaskDef.task returns `Promise`, - // clack expects separate `Promise | Promise`. The cast bridges this. + // Clack expects separate `Promise | Promise`. The cast bridges this. await clack.tasks( tasks.map((t) => ({ title: t.title, diff --git a/packages/core/src/lib/log.test.ts b/packages/core/src/lib/log.test.ts index 5ad0eaef..48fd95f3 100644 --- a/packages/core/src/lib/log.test.ts +++ b/packages/core/src/lib/log.test.ts @@ -157,7 +157,7 @@ describe('createLog()', () => { describe('stream', () => { it('should call clack.stream.info with iterable', async () => { const log = createLog() - const iterable = (async function* () { + const iterable = (async function* streamChunks() { yield 'chunk' })() @@ -227,7 +227,7 @@ describe('createLog()', () => { it('should return a frozen object', () => { const log = createLog() - expect(Object.isFrozen(log)).toBe(true) + expect(Object.isFrozen(log)).toBeTruthy() }) }) }) diff --git a/packages/core/src/middleware/config/config.ts b/packages/core/src/middleware/config/config.ts index 7ea9a704..513b5f24 100644 --- a/packages/core/src/middleware/config/config.ts +++ b/packages/core/src/middleware/config/config.ts @@ -338,7 +338,9 @@ function validateConfig( schema: ZodTypeAny, context?: string ): Result> { - const prefix = context ? `Invalid ${context} config` : 'Invalid config' + const prefix = match(context) + .with(P.string, (ctx) => `Invalid ${ctx} config`) + .otherwise(() => 'Invalid config') const [validationError, validated] = validate({ createError: ({ message }) => new Error(`${prefix}:\n${message}`), params: data, diff --git a/packages/core/src/screen/output/screen-log.test.ts b/packages/core/src/screen/output/screen-log.test.ts index c9230152..0c1bdb6c 100644 --- a/packages/core/src/screen/output/screen-log.test.ts +++ b/packages/core/src/screen/output/screen-log.test.ts @@ -3,14 +3,14 @@ import { describe, expect, it } from 'vitest' import { createScreenLog } from './screen-log.js' import { createOutputStore } from './store.js' -describe('createScreenLog', () => { +describe(createScreenLog, () => { it('should push an info log entry', () => { const store = createOutputStore() const log = createScreenLog(store) log.info('hello') - const entries = store.getSnapshot().entries + const { entries } = store.getSnapshot() expect(entries).toHaveLength(1) expect(entries[0]).toMatchObject({ kind: 'log', level: 'info', text: 'hello' }) }) @@ -21,7 +21,7 @@ describe('createScreenLog', () => { log.success('done') - const entries = store.getSnapshot().entries + const { entries } = store.getSnapshot() expect(entries).toHaveLength(1) expect(entries[0]).toMatchObject({ kind: 'log', level: 'success', text: 'done' }) }) @@ -32,7 +32,7 @@ describe('createScreenLog', () => { log.error('fail') - const entries = store.getSnapshot().entries + const { entries } = store.getSnapshot() expect(entries).toHaveLength(1) expect(entries[0]).toMatchObject({ kind: 'log', level: 'error', text: 'fail' }) }) @@ -43,7 +43,7 @@ describe('createScreenLog', () => { log.warn('careful') - const entries = store.getSnapshot().entries + const { entries } = store.getSnapshot() expect(entries).toHaveLength(1) expect(entries[0]).toMatchObject({ kind: 'log', level: 'warn', text: 'careful' }) }) @@ -54,7 +54,7 @@ describe('createScreenLog', () => { log.step('installing') - const entries = store.getSnapshot().entries + const { entries } = store.getSnapshot() expect(entries).toHaveLength(1) expect(entries[0]).toMatchObject({ kind: 'log', level: 'step', text: 'installing' }) }) @@ -65,7 +65,7 @@ describe('createScreenLog', () => { log.message('note', { symbol: '>' }) - const entries = store.getSnapshot().entries + const { entries } = store.getSnapshot() expect(entries).toHaveLength(1) expect(entries[0]).toMatchObject({ kind: 'log', @@ -81,7 +81,7 @@ describe('createScreenLog', () => { log.message('bare') - const entries = store.getSnapshot().entries + const { entries } = store.getSnapshot() expect(entries).toHaveLength(1) expect(entries[0]).toMatchObject({ kind: 'log', level: 'message', text: 'bare' }) expect(entries[0]).toHaveProperty('symbol', undefined) @@ -93,7 +93,7 @@ describe('createScreenLog', () => { log.newline() - const entries = store.getSnapshot().entries + const { entries } = store.getSnapshot() expect(entries).toHaveLength(1) expect(entries[0]).toMatchObject({ kind: 'newline' }) }) @@ -104,7 +104,7 @@ describe('createScreenLog', () => { log.raw('raw text') - const entries = store.getSnapshot().entries + const { entries } = store.getSnapshot() expect(entries).toHaveLength(1) expect(entries[0]).toMatchObject({ kind: 'raw', text: 'raw text' }) }) diff --git a/packages/core/src/screen/output/screen-report.test.ts b/packages/core/src/screen/output/screen-report.test.ts index 851dbdbc..94a01361 100644 --- a/packages/core/src/screen/output/screen-report.test.ts +++ b/packages/core/src/screen/output/screen-report.test.ts @@ -3,7 +3,7 @@ import { describe, expect, it } from 'vitest' import { createScreenReport } from './screen-report.js' import { createOutputStore } from './store.js' -describe('createScreenReport', () => { +describe(createScreenReport, () => { it('should push a check entry to the store', () => { const store = createOutputStore() const report = createScreenReport(store) @@ -11,7 +11,7 @@ describe('createScreenReport', () => { report.check(input) - const entries = store.getSnapshot().entries + const { entries } = store.getSnapshot() expect(entries).toHaveLength(1) expect(entries[0]).toMatchObject({ kind: 'check', input }) }) @@ -27,7 +27,7 @@ describe('createScreenReport', () => { report.finding(input) - const entries = store.getSnapshot().entries + const { entries } = store.getSnapshot() expect(entries).toHaveLength(1) expect(entries[0]).toMatchObject({ kind: 'finding', input }) }) @@ -45,7 +45,7 @@ describe('createScreenReport', () => { report.summary(input) - const entries = store.getSnapshot().entries + const { entries } = store.getSnapshot() expect(entries).toHaveLength(1) expect(entries[0]).toMatchObject({ kind: 'summary', input }) }) @@ -60,7 +60,7 @@ describe('createScreenReport', () => { report.summary(input) - const entries = store.getSnapshot().entries + const { entries } = store.getSnapshot() expect(entries).toHaveLength(1) expect(entries[0]).toMatchObject({ kind: 'summary', input }) }) diff --git a/packages/core/src/screen/output/screen-spinner.test.ts b/packages/core/src/screen/output/screen-spinner.test.ts index 2199a972..7f048323 100644 --- a/packages/core/src/screen/output/screen-spinner.test.ts +++ b/packages/core/src/screen/output/screen-spinner.test.ts @@ -79,15 +79,15 @@ describe('createScreenSpinner()', () => { const store = createOutputStore() const spinner = createScreenSpinner(store) - expect(spinner.isCancelled).toBe(false) + expect(spinner.isCancelled).toBeFalsy() spinner.start() - expect(spinner.isCancelled).toBe(false) + expect(spinner.isCancelled).toBeFalsy() spinner.cancel() - expect(spinner.isCancelled).toBe(true) + expect(spinner.isCancelled).toBeTruthy() spinner.clear() - expect(spinner.isCancelled).toBe(false) + expect(spinner.isCancelled).toBeFalsy() }) }) diff --git a/packages/core/src/screen/output/store.test.ts b/packages/core/src/screen/output/store.test.ts index 409546b7..a2beb634 100644 --- a/packages/core/src/screen/output/store.test.ts +++ b/packages/core/src/screen/output/store.test.ts @@ -78,7 +78,7 @@ describe('createOutputStore()', () => { const snapshot = store.getSnapshot() - expect(Object.isFrozen(snapshot)).toBe(true) - expect(Object.isFrozen(snapshot.entries)).toBe(true) + expect(Object.isFrozen(snapshot)).toBeTruthy() + expect(Object.isFrozen(snapshot.entries)).toBeTruthy() }) }) diff --git a/packages/core/src/stories/check.test.ts b/packages/core/src/stories/check.test.ts index 8eb7657a..d1a5239a 100644 --- a/packages/core/src/stories/check.test.ts +++ b/packages/core/src/stories/check.test.ts @@ -5,6 +5,7 @@ import { z } from 'zod' import { MAX_EDITABLE_FIELDS, checkStories } from './check.js' import type { Story, StoryEntry, StoryGroup } from './types.js' +// eslint-disable-next-line vitest/prefer-describe-function-title -- constant, not a function describe('MAX_EDITABLE_FIELDS', () => { it('should equal 6', () => { expect(MAX_EDITABLE_FIELDS).toBe(6) @@ -37,7 +38,7 @@ describe('checkStories()', () => { const result = checkStories(entries) expect(result.storyCount).toBe(1) - expect(result.passed).toBe(true) + expect(result.passed).toBeTruthy() expect(result.diagnostics).toHaveLength(0) }) @@ -193,7 +194,7 @@ describe('checkStories()', () => { const entries = new Map([['ok', okStory]]) const passingResult = checkStories(entries) - expect(passingResult.passed).toBe(true) + expect(passingResult.passed).toBeTruthy() const schema = z.object({ n: z.number() }) const badStory = withTag( @@ -211,14 +212,14 @@ describe('checkStories()', () => { const failEntries = new Map([['bad', badStory]]) const failingResult = checkStories(failEntries) - expect(failingResult.passed).toBe(false) + expect(failingResult.passed).toBeFalsy() }) it('should return a frozen result', () => { const entries = new Map() const result = checkStories(entries) - expect(Object.isFrozen(result)).toBe(true) - expect(Object.isFrozen(result.diagnostics)).toBe(true) + expect(Object.isFrozen(result)).toBeTruthy() + expect(Object.isFrozen(result.diagnostics)).toBeTruthy() }) }) diff --git a/packages/core/src/ui/keys.ts b/packages/core/src/ui/keys.ts index 0d0a968d..3e601930 100644 --- a/packages/core/src/ui/keys.ts +++ b/packages/core/src/ui/keys.ts @@ -100,8 +100,8 @@ export function normalizeKey(input: string, key: Key): NormalizedKeyEvent { return { key: resolvedKey, ctrl: key.ctrl, - // Terminal escape (\x1b) doubles as the meta prefix — clear the meta - // flag when the resolved key is 'escape' since it is protocol noise. + // Terminal escape (\x1b) doubles as the meta prefix — Clear the meta + // Flag when the resolved key is 'escape' since it is protocol noise. meta: match(resolvedKey) .with('escape', () => false) .otherwise(() => key.meta), diff --git a/vitest.config.ts b/vitest.config.ts index 35b61fd1..4b5c4eca 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -17,9 +17,9 @@ export default defineConfig({ // ── React/Ink components ───────────────────────────────────── // These depend on Ink's rendering lifecycle, terminal I/O // (alt-screen buffers, resize events, stdin/stdout), and React - // hooks (useInput, useSyncExternalStore). They cannot be unit - // tested without a full terminal emulator. Covered implicitly - // by integration tests and the examples test suite. + // Hooks (useInput, useSyncExternalStore). They cannot be unit + // Tested without a full terminal emulator. Covered implicitly + // By integration tests and the examples test suite. '**/ui/layout/fullscreen.tsx', '**/ui/layout/use-size.tsx', '**/ui/layout/scroll-area.tsx', @@ -34,25 +34,25 @@ export default defineConfig({ // ── Stories viewer ─────────────────────────────────────────── // Full Ink TUI application with panels, focus management, and - // live component preview. Requires interactive terminal. + // Live component preview. Requires interactive terminal. '**/stories/viewer/**', '**/stories/decorators.tsx', // ── Dynamic module loading ─────────────────────────────────── // Patches Node module resolution at runtime via jiti and - // dynamic import(). Unsafe to unit test — the module patching - // side effects leak across test boundaries. + // Dynamic import(). Unsafe to unit test — the module patching + // Side effects leak across test boundaries. '**/stories/importer.ts', // ── Bun subprocess entry point ─────────────────────────────── // Runs inside a `bun` process (not Node.js). Calls Bun.build() - // which is a Bun-only API unavailable in Vitest/Node. + // Which is a Bun-only API unavailable in Vitest/Node. '**/build/bun-runner.ts', // ── CLI command handlers (integration-tested) ──────────────── // These are side-effect-heavy command handlers that spawn child - // processes, read process.argv/platform/arch, and depend on - // compiled binaries. Tested via integration test suite. + // Processes, read process.argv/platform/arch, and depend on + // Compiled binaries. Tested via integration test suite. '**/commands/run.ts', '**/commands/stories.ts', ],