-
-
Notifications
You must be signed in to change notification settings - Fork 939
[WIP] Add tests for .ignore file behavior with customPatterns (#959) #960
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,80 @@ | ||
| import { describe, expect, test } from 'vitest'; | ||
| import { mergeConfigs } from '../../src/config/configLoad.js'; | ||
| import type { RepomixConfigCli, RepomixConfigFile } from '../../src/config/configSchema.js'; | ||
|
|
||
| describe('configMerge', () => { | ||
| describe('ignore settings merge', () => { | ||
| test('should preserve useDotIgnore when customPatterns is defined in fileConfig', () => { | ||
| const cwd = '/test/dir'; | ||
| const fileConfig: RepomixConfigFile = { | ||
| ignore: { | ||
| customPatterns: ['bin/'], | ||
| }, | ||
| }; | ||
| const cliConfig: RepomixConfigCli = {}; | ||
|
|
||
| const merged = mergeConfigs(cwd, fileConfig, cliConfig); | ||
|
|
||
| // useDotIgnore should be true by default and should not be affected by customPatterns | ||
| expect(merged.ignore.useDotIgnore).toBe(true); | ||
| expect(merged.ignore.useGitignore).toBe(true); | ||
| expect(merged.ignore.useDefaultPatterns).toBe(true); | ||
| expect(merged.ignore.customPatterns).toEqual(['bin/']); | ||
| }); | ||
|
|
||
| test('should preserve all ignore settings when customPatterns is defined', () => { | ||
| const cwd = '/test/dir'; | ||
| const fileConfig: RepomixConfigFile = { | ||
| ignore: { | ||
| customPatterns: ['bin/', 'tmp/'], | ||
| }, | ||
| }; | ||
| const cliConfig: RepomixConfigCli = {}; | ||
|
|
||
| const merged = mergeConfigs(cwd, fileConfig, cliConfig); | ||
|
|
||
| expect(merged.ignore).toEqual({ | ||
| useGitignore: true, | ||
| useDotIgnore: true, | ||
| useDefaultPatterns: true, | ||
| customPatterns: ['bin/', 'tmp/'], | ||
| }); | ||
| }); | ||
|
|
||
| test('should allow explicitly disabling useDotIgnore', () => { | ||
| const cwd = '/test/dir'; | ||
| const fileConfig: RepomixConfigFile = { | ||
| ignore: { | ||
| useDotIgnore: false, | ||
| customPatterns: ['bin/'], | ||
| }, | ||
| }; | ||
| const cliConfig: RepomixConfigCli = {}; | ||
|
|
||
| const merged = mergeConfigs(cwd, fileConfig, cliConfig); | ||
|
|
||
| expect(merged.ignore.useDotIgnore).toBe(false); | ||
| expect(merged.ignore.useGitignore).toBe(true); | ||
| expect(merged.ignore.customPatterns).toEqual(['bin/']); | ||
| }); | ||
|
|
||
| test('should merge customPatterns from all sources', () => { | ||
| const cwd = '/test/dir'; | ||
| const fileConfig: RepomixConfigFile = { | ||
| ignore: { | ||
| customPatterns: ['from-file/'], | ||
| }, | ||
| }; | ||
| const cliConfig: RepomixConfigCli = { | ||
| ignore: { | ||
| customPatterns: ['from-cli/'], | ||
| }, | ||
| }; | ||
|
|
||
| const merged = mergeConfigs(cwd, fileConfig, cliConfig); | ||
|
|
||
| expect(merged.ignore.customPatterns).toEqual(['from-file/', 'from-cli/']); | ||
| expect(merged.ignore.useDotIgnore).toBe(true); | ||
| }); | ||
| }); | ||
| }); | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,42 @@ | ||
| import { describe, expect, test } from 'vitest'; | ||
| import { repomixConfigFileSchema } from '../../src/config/configSchema.js'; | ||
|
|
||
| describe('configSchema - Zod parsing behavior', () => { | ||
| test('should parse config with only customPatterns', () => { | ||
| const input = { | ||
| ignore: { | ||
| customPatterns: ['bin/'], | ||
| }, | ||
| }; | ||
|
|
||
| const result = repomixConfigFileSchema.parse(input); | ||
|
|
||
| // useDotIgnore should not be set when not provided in input | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This test is revealing the likely root cause of issue #959! When ignore: {
...baseConfig.ignore, // useDotIgnore: true
...fileConfig.ignore, // useDotIgnore: undefined
...cliConfig.ignore,
}The spread of Recommendation: This is actually the expected Zod behavior - it only includes fields that are explicitly set. The fix should be in |
||
| expect(result.ignore?.useDotIgnore).toBeUndefined(); | ||
| expect(result.ignore?.useGitignore).toBeUndefined(); | ||
| expect(result.ignore?.useDefaultPatterns).toBeUndefined(); | ||
| expect(result.ignore?.customPatterns).toEqual(['bin/']); | ||
| }); | ||
|
|
||
| test('should parse config with useDotIgnore explicitly set', () => { | ||
| const input = { | ||
| ignore: { | ||
| useDotIgnore: true, | ||
| customPatterns: ['bin/'], | ||
| }, | ||
| }; | ||
|
|
||
| const result = repomixConfigFileSchema.parse(input); | ||
|
|
||
| expect(result.ignore?.useDotIgnore).toBe(true); | ||
| expect(result.ignore?.customPatterns).toEqual(['bin/']); | ||
| }); | ||
|
|
||
| test('should parse empty config', () => { | ||
| const input = {}; | ||
|
|
||
| const result = repomixConfigFileSchema.parse(input); | ||
|
|
||
| expect(result.ignore).toBeUndefined(); | ||
| }); | ||
| }); | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,111 @@ | ||||||||||||||||||||||||||||
| import * as fs from 'node:fs/promises'; | ||||||||||||||||||||||||||||
| import * as path from 'node:path'; | ||||||||||||||||||||||||||||
| import { afterEach, describe, expect, test } from 'vitest'; | ||||||||||||||||||||||||||||
| import { searchFiles } from '../../../src/core/file/fileSearch.js'; | ||||||||||||||||||||||||||||
| import { createMockConfig } from '../../testing/testUtils.js'; | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| describe('fileSearch - .ignore integration', () => { | ||||||||||||||||||||||||||||
| const testDir = path.join(process.cwd(), 'tests/fixtures/ignore-test-temp'); | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| afterEach(async () => { | ||||||||||||||||||||||||||||
| // Clean up test directory | ||||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||||
| await fs.rm(testDir, { recursive: true, force: true }); | ||||||||||||||||||||||||||||
| } catch { | ||||||||||||||||||||||||||||
| // Ignore errors | ||||||||||||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Potential test isolation issue: Using a fixed directory name Consider using a unique directory per test run: const testDir = path.join(process.cwd(), 'tests/fixtures', `ignore-test-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`);Or use vitest's test context to ensure proper isolation. |
||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| test('should respect .ignore file when customPatterns is defined in config', async () => { | ||||||||||||||||||||||||||||
| // Setup test directory structure | ||||||||||||||||||||||||||||
| await fs.mkdir(testDir, { recursive: true }); | ||||||||||||||||||||||||||||
| await fs.mkdir(path.join(testDir, 'bin'), { recursive: true }); | ||||||||||||||||||||||||||||
| await fs.mkdir(path.join(testDir, 'spec', 'data'), { recursive: true }); | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| // Create test files | ||||||||||||||||||||||||||||
| await fs.writeFile(path.join(testDir, 'bin', 'test.sh'), 'bin content'); | ||||||||||||||||||||||||||||
| await fs.writeFile(path.join(testDir, 'spec', 'data', 'test.txt'), 'test content'); | ||||||||||||||||||||||||||||
| await fs.writeFile(path.join(testDir, 'main.js'), 'main content'); | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| // Create .ignore file | ||||||||||||||||||||||||||||
| await fs.writeFile(path.join(testDir, '.ignore'), 'spec/data/\n'); | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| // Create config with customPatterns | ||||||||||||||||||||||||||||
| const config = createMockConfig({ | ||||||||||||||||||||||||||||
| ignore: { | ||||||||||||||||||||||||||||
|
Comment on lines
+34
to
+35
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Critical issue: This test doesn't match the bug scenario reported in #959! The bug report shows users defining ONLY {
"ignore": {
"customPatterns": ["bin/"]
}
}But this test explicitly sets all flags including
Suggested change
This would test the actual merge behavior and expose whether the bug exists. |
||||||||||||||||||||||||||||
| useGitignore: false, | ||||||||||||||||||||||||||||
| useDotIgnore: true, | ||||||||||||||||||||||||||||
| useDefaultPatterns: false, | ||||||||||||||||||||||||||||
| customPatterns: ['bin/'], | ||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| const result = await searchFiles(testDir, config); | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| // Both bin/ (from customPatterns) and spec/data/ (from .ignore) should be excluded | ||||||||||||||||||||||||||||
| expect(result.filePaths).not.toContain('bin/test.sh'); | ||||||||||||||||||||||||||||
| expect(result.filePaths).not.toContain('spec/data/test.txt'); | ||||||||||||||||||||||||||||
| expect(result.filePaths).toContain('main.js'); | ||||||||||||||||||||||||||||
| expect(result.filePaths).toContain('.ignore'); | ||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| test('should respect .ignore file when customPatterns is empty', async () => { | ||||||||||||||||||||||||||||
| // Setup test directory structure | ||||||||||||||||||||||||||||
| await fs.mkdir(testDir, { recursive: true }); | ||||||||||||||||||||||||||||
| await fs.mkdir(path.join(testDir, 'spec', 'data'), { recursive: true }); | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| // Create test files | ||||||||||||||||||||||||||||
| await fs.writeFile(path.join(testDir, 'spec', 'data', 'test.txt'), 'test content'); | ||||||||||||||||||||||||||||
| await fs.writeFile(path.join(testDir, 'main.js'), 'main content'); | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| // Create .ignore file | ||||||||||||||||||||||||||||
| await fs.writeFile(path.join(testDir, '.ignore'), 'spec/data/\n'); | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| // Create config without customPatterns | ||||||||||||||||||||||||||||
| const config = createMockConfig({ | ||||||||||||||||||||||||||||
| ignore: { | ||||||||||||||||||||||||||||
| useGitignore: false, | ||||||||||||||||||||||||||||
| useDotIgnore: true, | ||||||||||||||||||||||||||||
| useDefaultPatterns: false, | ||||||||||||||||||||||||||||
| customPatterns: [], | ||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| const result = await searchFiles(testDir, config); | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| // spec/data/ (from .ignore) should be excluded | ||||||||||||||||||||||||||||
| expect(result.filePaths).not.toContain('spec/data/test.txt'); | ||||||||||||||||||||||||||||
| expect(result.filePaths).toContain('main.js'); | ||||||||||||||||||||||||||||
| expect(result.filePaths).toContain('.ignore'); | ||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| test('should not use .ignore when useDotIgnore is false', async () => { | ||||||||||||||||||||||||||||
| // Setup test directory structure | ||||||||||||||||||||||||||||
| await fs.mkdir(testDir, { recursive: true }); | ||||||||||||||||||||||||||||
| await fs.mkdir(path.join(testDir, 'spec', 'data'), { recursive: true }); | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| // Create test files | ||||||||||||||||||||||||||||
| await fs.writeFile(path.join(testDir, 'spec', 'data', 'test.txt'), 'test content'); | ||||||||||||||||||||||||||||
| await fs.writeFile(path.join(testDir, 'main.js'), 'main content'); | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| // Create .ignore file | ||||||||||||||||||||||||||||
| await fs.writeFile(path.join(testDir, '.ignore'), 'spec/data/\n'); | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| // Create config with useDotIgnore: false | ||||||||||||||||||||||||||||
| const config = createMockConfig({ | ||||||||||||||||||||||||||||
| ignore: { | ||||||||||||||||||||||||||||
| useGitignore: false, | ||||||||||||||||||||||||||||
| useDotIgnore: false, | ||||||||||||||||||||||||||||
| useDefaultPatterns: false, | ||||||||||||||||||||||||||||
| customPatterns: [], | ||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| const result = await searchFiles(testDir, config); | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| // spec/data/ should NOT be excluded because useDotIgnore is false | ||||||||||||||||||||||||||||
| expect(result.filePaths).toContain('spec/data/test.txt'); | ||||||||||||||||||||||||||||
| expect(result.filePaths).toContain('main.js'); | ||||||||||||||||||||||||||||
| expect(result.filePaths).toContain('.ignore'); | ||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The comment states this "should not be affected" but that's exactly what we're testing for in #959!
If the bug exists, this assertion might actually fail (which would be correct - exposing the bug). Consider adding an explicit check:
Also, it would be valuable to verify what the
fileConfig.ignoreobject looks like after Zod parsing to confirm whetheruseDotIgnoreis undefined or not present.