Skip to content

Commit 6f8ee0d

Browse files
authored
chore(merge): improve folder-kebab-case rule to skip non-directory entries and enhance test cases (#28)
2 parents df98534 + a8f4db0 commit 6f8ee0d

File tree

2 files changed

+25
-6
lines changed

2 files changed

+25
-6
lines changed

src/rules/folder-kebab-case.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,15 +20,17 @@ export const folderKebabCase = createRule<VueModularRuleModule>({
2020

2121
if (!fs.existsSync(root)) return
2222
try {
23-
const entries = fs.readdirSync(root, { recursive: true })
23+
const entries: fs.Dirent[] = fs.readdirSync(root, { recursive: true }) as unknown as fs.Dirent[]
2424

2525
entries.forEach((dir) => {
26+
if (dir.isDirectory() === false) return
2627
const fullPath = path.join(root, String(dir))
2728
if (isIgnored(fullPath, options.ignores)) return
2829
const base = path.basename(fullPath)
2930
const kebab = toKebabCase(base)
3031
if (kebab !== base) {
31-
context.report({ node, messageId: 'folderNotKebab', data: { folder: String(dir), kebab } })
32+
context.report({ node, messageId: 'folderNotKebab', data: { folder: String(dir), expected: kebab } })
33+
return
3234
}
3335
})
3436
} catch {

tests/rules/folder-kebab-case.test.ts

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import fs from 'fs'
77
describe('folder-kebab-case', () => {
88
beforeEach(() => setupTest())
99

10+
const makeDirent = (n: string, isDir = true) => ({ name: Buffer.from(n), isDirectory: () => isDir, toString: () => n })
11+
1012
it('does nothing when project root does not exist', () => {
1113
vi.spyOn(fs, 'existsSync').mockReturnValue(false)
1214
const context = runRule(folderKebabCase, 'filename.ts')
@@ -15,25 +17,40 @@ describe('folder-kebab-case', () => {
1517

1618
it('reports non-kebab folder entries', () => {
1719
vi.spyOn(fs, 'existsSync').mockReturnValue(true)
18-
vi.spyOn(fs, 'readdirSync').mockReturnValue(['FooBar', 'baz-qux'] as unknown as fs.Dirent<Buffer<ArrayBufferLike>>[])
20+
vi.spyOn(fs, 'readdirSync').mockReturnValue([makeDirent('FooBar'), makeDirent('baz-qux')] as unknown as fs.Dirent<Buffer>[])
1921
const context = runRule(folderKebabCase, 'filename.ts')
2022
expect(context.report).toHaveBeenCalledTimes(1)
2123
})
2224

2325
it('does not report when entry is already kebab-case', () => {
2426
vi.spyOn(fs, 'existsSync').mockReturnValue(true)
25-
vi.spyOn(fs, 'readdirSync').mockReturnValue(['foo-bar', 'baz-qux'] as unknown as fs.Dirent<Buffer<ArrayBufferLike>>[])
27+
vi.spyOn(fs, 'readdirSync').mockReturnValue([makeDirent('foo-bar'), makeDirent('baz-qux')] as unknown as fs.Dirent<Buffer>[])
2628
const context = runRule(folderKebabCase, 'filename.ts')
2729
expect(context.report).not.toHaveBeenCalled()
2830
})
2931

3032
it('respects ignores (skips ignored folders)', () => {
3133
vi.spyOn(fs, 'existsSync').mockReturnValue(true)
32-
vi.spyOn(fs, 'readdirSync').mockReturnValue(['FooBar', 'baz-qux', 'IgnoreMe'] as unknown as fs.Dirent<Buffer<ArrayBufferLike>>[])
34+
vi.spyOn(fs, 'readdirSync').mockReturnValue([
35+
makeDirent('FooBar'),
36+
makeDirent('baz-qux'),
37+
makeDirent('IgnoreMe'),
38+
] as unknown as fs.Dirent<Buffer>[])
3339
const context = runRule(folderKebabCase, 'filename.ts', [{ ignores: ['**/IgnoreMe'] }])
3440
expect(context.report).toHaveBeenCalledTimes(1)
3541
})
3642

43+
it('skips non-directory entries (files)', () => {
44+
vi.spyOn(fs, 'existsSync').mockReturnValue(true)
45+
vi.spyOn(fs, 'readdirSync').mockReturnValue([
46+
makeDirent('FooBar', false), // a file-like entry
47+
makeDirent('NotKebab', true),
48+
] as unknown as fs.Dirent<Buffer>[])
49+
const context = runRule(folderKebabCase, 'filename.ts')
50+
// only the real directory 'NotKebab' should be reported
51+
expect(context.report).toHaveBeenCalledTimes(1)
52+
})
53+
3754
it('handles fs errors gracefully (does not throw)', () => {
3855
vi.spyOn(fs, 'existsSync').mockReturnValue(true)
3956
vi.spyOn(fs, 'readdirSync').mockImplementation(() => {
@@ -45,7 +62,7 @@ describe('folder-kebab-case', () => {
4562

4663
it('does nothing when runOnce returns false', () => {
4764
vi.spyOn(fs, 'existsSync').mockReturnValue(true)
48-
vi.spyOn(fs, 'readdirSync').mockReturnValue(['FooBar', 'baz-qux'] as unknown as fs.Dirent<Buffer<ArrayBufferLike>>[])
65+
vi.spyOn(fs, 'readdirSync').mockReturnValue([makeDirent('FooBar'), makeDirent('baz-qux')] as unknown as fs.Dirent<Buffer>[])
4966
const context1 = runRule(folderKebabCase, 'filename1.ts')
5067
const context2 = runRule(folderKebabCase, 'filename2.ts')
5168
expect(context1.report).toHaveBeenCalledTimes(1)

0 commit comments

Comments
 (0)