diff options
| author | Jerop Kipruto <[email protected]> | 2025-08-20 10:53:53 +0900 |
|---|---|---|
| committer | GitHub <[email protected]> | 2025-08-20 01:53:53 +0000 |
| commit | 1049d388451120587a8643a401fd71430a8cd5fe (patch) | |
| tree | 337bc2f3a15bcdd59920ba2ea09f0105276d7746 /packages/cli/src/ui/commands/setupGithubCommand.test.ts | |
| parent | c93c06711a383e92aa29eeb2555db400edeb16c7 (diff) | |
feat: update .gitignore in /setup-github (#6591)
Diffstat (limited to 'packages/cli/src/ui/commands/setupGithubCommand.test.ts')
| -rw-r--r-- | packages/cli/src/ui/commands/setupGithubCommand.test.ts | 135 |
1 files changed, 134 insertions, 1 deletions
diff --git a/packages/cli/src/ui/commands/setupGithubCommand.test.ts b/packages/cli/src/ui/commands/setupGithubCommand.test.ts index 38589e58..2dd9f97f 100644 --- a/packages/cli/src/ui/commands/setupGithubCommand.test.ts +++ b/packages/cli/src/ui/commands/setupGithubCommand.test.ts @@ -10,7 +10,7 @@ import fs from 'node:fs/promises'; import { vi, describe, expect, it, afterEach, beforeEach } from 'vitest'; import * as gitUtils from '../../utils/gitUtils.js'; -import { setupGithubCommand } from './setupGithubCommand.js'; +import { setupGithubCommand, updateGitignore } from './setupGithubCommand.js'; import { CommandContext, ToolActionReturn } from './types.js'; import * as commandUtils from '../utils/commandUtils.js'; @@ -102,5 +102,138 @@ describe('setupGithubCommand', async () => { const contents = await fs.readFile(workflowFile, 'utf8'); expect(contents).toContain(workflow); } + + // Verify that .gitignore was created with the expected entries + const gitignorePath = path.join(scratchDir, '.gitignore'); + const gitignoreExists = await fs + .access(gitignorePath) + .then(() => true) + .catch(() => false); + expect(gitignoreExists).toBe(true); + + if (gitignoreExists) { + const gitignoreContent = await fs.readFile(gitignorePath, 'utf8'); + expect(gitignoreContent).toContain('.gemini/'); + expect(gitignoreContent).toContain('gha-creds-*.json'); + } + }); +}); + +describe('updateGitignore', () => { + let scratchDir = ''; + + beforeEach(async () => { + scratchDir = await fs.mkdtemp(path.join(os.tmpdir(), 'update-gitignore-')); + }); + + afterEach(async () => { + if (scratchDir) await fs.rm(scratchDir, { recursive: true }); + }); + + it('creates a new .gitignore file when none exists', async () => { + await updateGitignore(scratchDir); + + const gitignorePath = path.join(scratchDir, '.gitignore'); + const content = await fs.readFile(gitignorePath, 'utf8'); + + expect(content).toBe('.gemini/\ngha-creds-*.json\n'); + }); + + it('appends entries to existing .gitignore file', async () => { + const gitignorePath = path.join(scratchDir, '.gitignore'); + const existingContent = '# Existing content\nnode_modules/\n'; + await fs.writeFile(gitignorePath, existingContent); + + await updateGitignore(scratchDir); + + const content = await fs.readFile(gitignorePath, 'utf8'); + + expect(content).toBe( + '# Existing content\nnode_modules/\n\n.gemini/\ngha-creds-*.json\n', + ); + }); + + it('does not add duplicate entries', async () => { + const gitignorePath = path.join(scratchDir, '.gitignore'); + const existingContent = '.gemini/\nsome-other-file\ngha-creds-*.json\n'; + await fs.writeFile(gitignorePath, existingContent); + + await updateGitignore(scratchDir); + + const content = await fs.readFile(gitignorePath, 'utf8'); + + expect(content).toBe(existingContent); + }); + + it('adds only missing entries when some already exist', async () => { + const gitignorePath = path.join(scratchDir, '.gitignore'); + const existingContent = '.gemini/\nsome-other-file\n'; + await fs.writeFile(gitignorePath, existingContent); + + await updateGitignore(scratchDir); + + const content = await fs.readFile(gitignorePath, 'utf8'); + + // Should add only the missing gha-creds-*.json entry + expect(content).toBe('.gemini/\nsome-other-file\n\ngha-creds-*.json\n'); + expect(content).toContain('gha-creds-*.json'); + // Should not duplicate .gemini/ entry + expect((content.match(/\.gemini\//g) || []).length).toBe(1); + }); + + it('does not get confused by entries in comments or as substrings', async () => { + const gitignorePath = path.join(scratchDir, '.gitignore'); + const existingContent = [ + '# This is a comment mentioning .gemini/ folder', + 'my-app.gemini/config', + '# Another comment with gha-creds-*.json pattern', + 'some-other-gha-creds-file.json', + '', + ].join('\n'); + await fs.writeFile(gitignorePath, existingContent); + + await updateGitignore(scratchDir); + + const content = await fs.readFile(gitignorePath, 'utf8'); + + // Should add both entries since they don't actually exist as gitignore rules + expect(content).toContain('.gemini/'); + expect(content).toContain('gha-creds-*.json'); + + // Verify the entries were added (not just mentioned in comments) + const lines = content + .split('\n') + .map((line) => line.split('#')[0].trim()) + .filter((line) => line); + expect(lines).toContain('.gemini/'); + expect(lines).toContain('gha-creds-*.json'); + expect(lines).toContain('my-app.gemini/config'); + expect(lines).toContain('some-other-gha-creds-file.json'); + }); + + it('handles file system errors gracefully', async () => { + // Try to update gitignore in a non-existent directory + const nonExistentDir = path.join(scratchDir, 'non-existent'); + + // This should not throw an error + await expect(updateGitignore(nonExistentDir)).resolves.toBeUndefined(); + }); + + it('handles permission errors gracefully', async () => { + const consoleSpy = vi.spyOn(console, 'debug').mockImplementation(() => {}); + + const fsModule = await import('node:fs'); + const writeFileSpy = vi + .spyOn(fsModule.promises, 'writeFile') + .mockRejectedValue(new Error('Permission denied')); + + await expect(updateGitignore(scratchDir)).resolves.toBeUndefined(); + expect(consoleSpy).toHaveBeenCalledWith( + 'Failed to update .gitignore:', + expect.any(Error), + ); + + writeFileSpy.mockRestore(); + consoleSpy.mockRestore(); }); }); |
