test(source-scan): unit-test the stat fallback via an extracted helper

The fabricated-Dirent readdir mock could not satisfy both gates at once:
vi.mocked(readdirSync) resolves to Node's Dirent<NonSharedBuffer> overload, so
the mock needed a type assertion, and #19462's casting gate rejects new ones on
changed lines. Removing the cast then failed tsc.

Extract directoryEntryNeedsStat and test it directly with a structural probe.
No mock, no cast, no top-level await, and the DT_UNKNOWN case is pinned:
removing the fallback fails 'stats an entry whose type readdir could not report'.
This commit is contained in:
Neil
2026-09-12 22:29:36 -07:00
parent 7a16059adc
commit 7e7af82af4
2 changed files with 42 additions and 32 deletions
+18 -5
View File
@@ -29,6 +29,22 @@ export function isTestFile(relativePath: string): boolean {
export type ScannedFile = { path: string; relativePath: string; source: string }
/** The three readdir type predicates the walk consults. */
type DirentTypeProbe = {
isSymbolicLink(): boolean
isFile(): boolean
isDirectory(): boolean
}
/**
* Links need a stat to follow them, and so does DT_UNKNOWN (every predicate
* false) -- filesystems that do not report d_type would otherwise have a real
* directory silently dropped from the scan.
*/
export function directoryEntryNeedsStat(entry: DirentTypeProbe): boolean {
return entry.isSymbolicLink() || (!entry.isFile() && !entry.isDirectory())
}
/**
* Every `.ts`/`.tsx` file under `root`, with its text.
*
@@ -52,11 +68,8 @@ export function scanSourceTree(
continue
}
const path = join(directory, name)
// Ordinary entries carry their type from readdir. Links need a stat to follow
// them, and so does DT_UNKNOWN (every predicate false), or a real directory
// would be silently dropped from the scan.
const needsStat = entry.isSymbolicLink() || (!entry.isFile() && !entry.isDirectory())
if (needsStat ? statSync(path).isDirectory() : entry.isDirectory()) {
// Ordinary entries carry their type from readdir.
if (directoryEntryNeedsStat(entry) ? statSync(path).isDirectory() : entry.isDirectory()) {
visit(path)
continue
}
+24 -27
View File
@@ -11,7 +11,7 @@ import type * as Fs from 'node:fs'
import { tmpdir } from 'node:os'
import { join } from 'node:path'
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
import { scanSourceTree } from './source-tree-scan'
import { directoryEntryNeedsStat, scanSourceTree } from './source-tree-scan'
vi.mock('node:fs', async (importOriginal) => {
const actual = await importOriginal<typeof Fs>()
@@ -22,8 +22,6 @@ vi.mock('node:fs', async (importOriginal) => {
}
})
const actualFs = await vi.importActual<typeof Fs>('node:fs')
let root: string
beforeEach(() => {
@@ -110,30 +108,6 @@ describe('scanSourceTree filesystem traversal', () => {
expect(statSync).toHaveBeenCalledExactlyOnceWith(join(root, 'alias'))
})
it('stats an entry whose type readdir could not report instead of dropping its subtree', () => {
mkdirSync(join(root, 'nested'))
file(join('nested', 'inner.ts'), 'inner source')
// Filesystems without d_type yield a Dirent where every predicate is false.
vi.mocked(readdirSync).mockImplementationOnce(((directory: Fs.PathLike) =>
actualFs.readdirSync(directory, { withFileTypes: true }).map((entry) =>
entry.name === 'nested'
? Object.assign(Object.create(Object.getPrototypeOf(entry)), entry, {
isFile: () => false,
isDirectory: () => false,
isSymbolicLink: () => false
})
: entry
)) as typeof readdirSync)
expect(scanSourceTree(root)).toEqual([
{
path: join(root, 'nested', 'inner.ts'),
relativePath: 'nested/inner.ts',
source: 'inner source'
}
])
expect(statSync).toHaveBeenCalledExactlyOnceWith(join(root, 'nested'))
})
it('still reports a broken link instead of silently dropping it', () => {
const target = join(root, '.target')
@@ -145,3 +119,26 @@ describe('scanSourceTree filesystem traversal', () => {
expect(statSync).toHaveBeenCalledExactlyOnceWith(join(root, 'alias'))
})
})
describe('directoryEntryNeedsStat', () => {
const probe = (kind: 'file' | 'dir' | 'link' | 'unknown') => ({
isFile: () => kind === 'file',
isDirectory: () => kind === 'dir',
isSymbolicLink: () => kind === 'link'
})
it('skips the stat for entries readdir already typed', () => {
expect(directoryEntryNeedsStat(probe('file'))).toBe(false)
expect(directoryEntryNeedsStat(probe('dir'))).toBe(false)
})
it('stats links so they are followed', () => {
expect(directoryEntryNeedsStat(probe('link'))).toBe(true)
})
// Filesystems without d_type report DT_UNKNOWN: every predicate is false, and
// without the stat a real directory's whole subtree is silently dropped.
it('stats an entry whose type readdir could not report', () => {
expect(directoryEntryNeedsStat(probe('unknown'))).toBe(true)
})
})