-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: test using mocks in Jest, as well as the nock module
- feat: add initial handleConfigOption test - feat!: change coverage script to test:coverage - docs: add examples of CLI commands for testing - docs: update CONTRIBUTING.md with watch scripts - build: add nock devDependency & test:watch script - fix: remove fake test file - feat: add file_functions tests which uses jest mocks - fix: variable names within handleConfigOption.test.js - feat: add initial tests using 'nock' for groqConfig.test.js - feat: add initial tests for geminiConfig.test.js - can't use nock
- Loading branch information
1 parent
e8e4cb8
commit df3a854
Showing
13 changed files
with
891 additions
and
19 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
# Terms with regards to testing | ||
|
||
- code paths | ||
- fuzz testing | ||
- assertions | ||
- match | ||
- mocks | ||
- independent from the environment from where it runs | ||
- don't need to talk to a real database | ||
- don't need to use the actual file system | ||
- test against _fake_ implementations | ||
- coverage | ||
- which code paths were visited | ||
- do we need to write more tests to _cover_ everything |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,135 @@ | ||
// tests/unit/ai/config/geminiConfig.test.js | ||
import { jest } from '@jest/globals'; | ||
|
||
// Mock objects | ||
const mockGenerateContent = jest.fn(); | ||
const mockGetGenerativeModel = jest.fn(() => ({ | ||
generateContent: mockGenerateContent, | ||
})); | ||
|
||
// Export GoogleGenerativeAI as both default and named export | ||
const MockGoogleGenerativeAI = jest.fn(() => ({ | ||
getGenerativeModel: mockGetGenerativeModel, | ||
})); | ||
|
||
// Mock the module with both default and named exports | ||
jest.unstable_mockModule('@google/generative-ai', () => ({ | ||
default: MockGoogleGenerativeAI, | ||
GoogleGenerativeAI: MockGoogleGenerativeAI, | ||
})); | ||
|
||
const apiKey = 'test-api-key'; | ||
process.env.GEMINI_KEY = apiKey; | ||
|
||
// Import the module under test after mocking | ||
const { promptGemini } = await import('../../../../src/ai/config/geminiConfig.js'); | ||
|
||
describe('src/ai/config/geminiConfig.js tests', () => { | ||
const model = 'gemini-pro'; | ||
|
||
beforeAll(() => { | ||
process.env.NODE_ENV = 'test'; | ||
}); | ||
|
||
beforeEach(() => { | ||
jest.clearAllMocks(); | ||
|
||
// Reset mock implementations | ||
MockGoogleGenerativeAI.mockImplementation(() => ({ | ||
getGenerativeModel: mockGetGenerativeModel, | ||
})); | ||
|
||
mockGetGenerativeModel.mockImplementation(() => ({ | ||
generateContent: mockGenerateContent, | ||
})); | ||
}); | ||
|
||
// TODO: Fix this test | ||
// test('should return a valid response from Gemini API', async () => { | ||
// const prompt = 'Hello, how are you?'; | ||
// const temperature = 0.7; | ||
|
||
// mockGenerateContent.mockResolvedValue({ | ||
// response: { | ||
// text: () => 'I am fine, thank you!', | ||
// usageMetadata: { | ||
// promptTokenCount: 5, | ||
// candidatesTokenCount: 5, | ||
// totalTokenCount: 10, | ||
// }, | ||
// }, | ||
// }); | ||
|
||
// const result = await promptGemini(prompt, model, temperature); | ||
|
||
// expect(result.responseText).toBe('I am fine, thank you!'); | ||
// expect(MockGoogleGenerativeAI).toHaveBeenCalledWith(apiKey); // Why isn't this called | ||
// expect(mockGetGenerativeModel).toHaveBeenCalledWith({ | ||
// model, | ||
// temperature, | ||
// }); | ||
// }); | ||
|
||
test('should handle API errors gracefully', async () => { | ||
const prompt = 'Hello, how are you?'; | ||
const temperature = 0.7; | ||
|
||
mockGenerateContent.mockRejectedValue(new Error('Invalid request')); | ||
|
||
await expect(promptGemini(prompt, model, temperature)).rejects.toThrow( | ||
'Error prompting Gemini: Invalid request' | ||
); | ||
}); | ||
|
||
test('should use default temperature when not provided', async () => { | ||
const prompt = 'Hello'; | ||
const defaultTemperature = 0.5; | ||
|
||
mockGenerateContent.mockResolvedValue({ | ||
response: { | ||
text: () => 'Hi', | ||
usageMetadata: { | ||
promptTokenCount: 1, | ||
candidatesTokenCount: 1, | ||
totalTokenCount: 2, | ||
}, | ||
}, | ||
}); | ||
|
||
const result = await promptGemini(prompt, model); | ||
|
||
expect(result.responseText).toBe('Hi'); | ||
expect(mockGetGenerativeModel).toHaveBeenCalledWith({ | ||
model, | ||
temperature: defaultTemperature, | ||
}); | ||
}); | ||
|
||
test('should handle empty response from API', async () => { | ||
const prompt = 'Hello'; | ||
|
||
mockGenerateContent.mockResolvedValue({ | ||
response: { | ||
text: () => '', | ||
usageMetadata: { | ||
promptTokenCount: 1, | ||
candidatesTokenCount: 0, | ||
totalTokenCount: 1, | ||
}, | ||
}, | ||
}); | ||
|
||
const result = await promptGemini(prompt, model); | ||
expect(result.responseText).toBe(''); | ||
}); | ||
|
||
test('should handle network errors', async () => { | ||
const prompt = 'Hello'; | ||
|
||
mockGenerateContent.mockRejectedValue(new Error('Connection refused')); | ||
|
||
await expect(promptGemini(prompt, model)).rejects.toThrow( | ||
'Error prompting Gemini: Connection refused' | ||
); | ||
}); | ||
}); |
Oops, something went wrong.