detox-copilot
Advanced tools
Comparing version 0.0.11 to 0.0.13
@@ -60,3 +60,3 @@ "use strict"; | ||
catch (error) { | ||
console.error('Error loading cache from file:', error); | ||
console.warn('Error loading cache from file:', error); | ||
this.cache.clear(); // Clear cache on error to avoid stale data | ||
@@ -79,3 +79,3 @@ } | ||
this.loadCacheFromFile(); | ||
const snapshot = await this.snapshotManager.captureSnapshotImage(); | ||
const snapshot = this.promptHandler.isSnapshotImageSupported() ? await this.snapshotManager.captureSnapshotImage() : undefined; | ||
const viewHierarchy = await this.snapshotManager.captureViewHierarchyString(); | ||
@@ -82,0 +82,0 @@ const isSnapshotImageAttached = snapshot != null && this.promptHandler.isSnapshotImageSupported(); |
@@ -106,3 +106,3 @@ "use strict"; | ||
expect(mockPromptCreator.createPrompt).toHaveBeenCalledWith(intent, '<view></view>', false, []); | ||
expect(mockPromptHandler.runPrompt).toHaveBeenCalledWith('generated prompt', 'snapshot_data'); | ||
expect(mockPromptHandler.runPrompt).toHaveBeenCalledWith('generated prompt', undefined); | ||
expect(mockCodeEvaluator.evaluate).toHaveBeenCalledWith('generated code', mockContext); | ||
@@ -109,0 +109,0 @@ expect(fs.writeFileSync).toHaveBeenCalled(); |
@@ -8,8 +8,11 @@ "use strict"; | ||
const Copilot_1 = require("../Copilot"); | ||
jest.mock('fs', () => ({ | ||
readFileSync: jest.fn().mockReturnValue('{}') | ||
})); | ||
describe('Integration', () => { | ||
const fs_1 = __importDefault(require("fs")); | ||
const path_1 = __importDefault(require("path")); | ||
jest.mock('fs'); | ||
jest.mock('path'); | ||
describe('Copilot Integration Tests', () => { | ||
let mockFrameworkDriver; | ||
let mockPromptHandler; | ||
let mockFs; | ||
let mockPath; | ||
beforeEach(() => { | ||
@@ -29,13 +32,24 @@ jest.clearAllMocks(); | ||
}; | ||
mockFs = fs_1.default; | ||
mockPath = path_1.default; | ||
mockFs.existsSync.mockReturnValue(false); | ||
mockFs.readFileSync.mockReturnValue('{}'); | ||
mockFs.writeFileSync.mockImplementation(() => { }); | ||
mockPath.resolve.mockImplementation((...paths) => paths.join('/')); | ||
}); | ||
afterEach(() => { | ||
// Reset Copilot instance after each test to ensure a clean state | ||
Copilot_1.Copilot['instance'] = undefined; | ||
}); | ||
describe('Initialization', () => { | ||
it('should synchronously throw an error when perform is called before initialization', async () => { | ||
it('should throw an error when perform is called before initialization', async () => { | ||
await expect(() => index_1.default.perform('Some action')).rejects.toThrow(); | ||
}); | ||
it('should initialize successfully', () => { | ||
expect(() => index_1.default.init({ | ||
frameworkDriver: mockFrameworkDriver, | ||
promptHandler: mockPromptHandler | ||
})).not.toThrow(); | ||
}); | ||
}); | ||
describe('perform method', () => { | ||
describe('Single Step Operations', () => { | ||
beforeEach(() => { | ||
@@ -74,3 +88,3 @@ index_1.default.init({ | ||
}); | ||
describe('error handling', () => { | ||
describe('Multiple Step Operations', () => { | ||
beforeEach(() => { | ||
@@ -82,2 +96,32 @@ index_1.default.init({ | ||
}); | ||
it('should perform multiple steps using spread operator', async () => { | ||
mockPromptHandler.runPrompt | ||
.mockResolvedValueOnce('// Tap login button') | ||
.mockResolvedValueOnce('// Enter username') | ||
.mockResolvedValueOnce('// Enter password'); | ||
const results = await index_1.default.perform('Tap on the login button', 'Enter username "testuser"', 'Enter password "password123"'); | ||
expect(results).toHaveLength(3); | ||
expect(mockPromptHandler.runPrompt).toHaveBeenCalledTimes(3); | ||
expect(mockFrameworkDriver.captureSnapshotImage).toHaveBeenCalledTimes(3); | ||
expect(mockFrameworkDriver.captureViewHierarchyString).toHaveBeenCalledTimes(3); | ||
}); | ||
it('should handle errors in multiple steps and stop execution', async () => { | ||
mockPromptHandler.runPrompt | ||
.mockResolvedValueOnce('// Tap login button') | ||
.mockResolvedValueOnce('throw new Error("Username field not found");') | ||
.mockResolvedValueOnce('throw new Error("Username field not found - second");') | ||
.mockResolvedValueOnce('// Enter password'); | ||
await expect(index_1.default.perform('Tap on the login button', 'Enter username "testuser"', 'Enter password "password123"')).rejects.toThrow('Username field not found'); | ||
expect(mockPromptHandler.runPrompt).toHaveBeenCalledTimes(3); | ||
expect(mockFrameworkDriver.captureSnapshotImage).toHaveBeenCalledTimes(2); | ||
expect(mockFrameworkDriver.captureViewHierarchyString).toHaveBeenCalledTimes(2); | ||
}); | ||
}); | ||
describe('Error Handling', () => { | ||
beforeEach(() => { | ||
index_1.default.init({ | ||
frameworkDriver: mockFrameworkDriver, | ||
promptHandler: mockPromptHandler | ||
}); | ||
}); | ||
it('should throw error when PromptHandler fails', async () => { | ||
@@ -96,2 +140,92 @@ mockPromptHandler.runPrompt.mockRejectedValue(new Error('API error')); | ||
}); | ||
describe('Context Management', () => { | ||
beforeEach(() => { | ||
index_1.default.init({ | ||
frameworkDriver: mockFrameworkDriver, | ||
promptHandler: mockPromptHandler | ||
}); | ||
}); | ||
it('should reset context when reset is called', async () => { | ||
mockPromptHandler.runPrompt.mockResolvedValueOnce('// Login action'); | ||
await index_1.default.perform('Log in to the application'); | ||
index_1.default.reset(); | ||
mockPromptHandler.runPrompt.mockResolvedValueOnce('// New action after reset'); | ||
await index_1.default.perform('Perform action after reset'); | ||
expect(mockPromptHandler.runPrompt).toHaveBeenCalledTimes(2); | ||
expect(mockPromptHandler.runPrompt.mock.calls[1][0]).not.toContain('Log in to the application'); | ||
}); | ||
it('should clear conversation history on reset', async () => { | ||
mockPromptHandler.runPrompt | ||
.mockResolvedValueOnce('// Action 1') | ||
.mockResolvedValueOnce('// Action 2'); | ||
await index_1.default.perform('Action 1'); | ||
await index_1.default.perform('Action 2'); | ||
const lastCallArgsBeforeReset = mockPromptHandler.runPrompt.mock.calls[1][0]; | ||
expect(lastCallArgsBeforeReset).toContain('Action 1'); | ||
expect(lastCallArgsBeforeReset).toContain('Action 2'); | ||
index_1.default.reset(); | ||
mockPromptHandler.runPrompt.mockResolvedValueOnce('// New action'); | ||
await index_1.default.perform('New action after reset'); | ||
const lastCallArgsAfterReset = mockPromptHandler.runPrompt.mock.calls[2][0]; | ||
expect(lastCallArgsAfterReset).not.toContain('Action 1'); | ||
expect(lastCallArgsAfterReset).not.toContain('Action 2'); | ||
expect(lastCallArgsAfterReset).toContain('New action after reset'); | ||
}); | ||
}); | ||
describe('Caching Behavior', () => { | ||
beforeEach(() => { | ||
index_1.default.init({ | ||
frameworkDriver: mockFrameworkDriver, | ||
promptHandler: mockPromptHandler | ||
}); | ||
}); | ||
it('should create cache file if it does not exist', async () => { | ||
mockFs.existsSync.mockReturnValue(false); | ||
mockPromptHandler.runPrompt.mockResolvedValue('// Perform action'); | ||
await index_1.default.perform('Perform action'); | ||
expect(mockFs.writeFileSync).toHaveBeenCalled(); | ||
}); | ||
it('should read from existing cache file', async () => { | ||
mockFs.existsSync.mockReturnValue(true); | ||
mockFs.readFileSync.mockReturnValue(JSON.stringify({ | ||
'{"step":"Cached action","previous":[]}': '// Cached action code' | ||
})); | ||
await index_1.default.perform('Cached action'); | ||
expect(mockFs.readFileSync).toHaveBeenCalled(); | ||
expect(mockPromptHandler.runPrompt).not.toHaveBeenCalled(); | ||
}); | ||
it('should update cache file after performing new action', async () => { | ||
mockPromptHandler.runPrompt.mockResolvedValue('// New action code'); | ||
await index_1.default.perform('New action'); | ||
expect(mockFs.writeFileSync).toHaveBeenCalledWith(expect.any(String), expect.stringContaining('New action'), expect.any(Object)); | ||
}); | ||
it('should handle fs.readFileSync errors', async () => { | ||
mockFs.existsSync.mockReturnValue(true); | ||
mockFs.readFileSync.mockImplementation(() => { throw new Error('Read error'); }); | ||
mockPromptHandler.runPrompt.mockResolvedValue('// New action code'); | ||
await index_1.default.perform('Action with read error'); | ||
expect(mockPromptHandler.runPrompt).toHaveBeenCalled(); | ||
}); | ||
it('should handle fs.writeFileSync errors', async () => { | ||
mockFs.writeFileSync.mockImplementation(() => { throw new Error('Write error'); }); | ||
mockPromptHandler.runPrompt.mockResolvedValue('// Action code'); | ||
await expect(index_1.default.perform('Action with write error')).resolves.not.toThrow(); | ||
}); | ||
}); | ||
describe('Feature Support', () => { | ||
beforeEach(() => { | ||
index_1.default.init({ | ||
frameworkDriver: mockFrameworkDriver, | ||
promptHandler: mockPromptHandler | ||
}); | ||
}); | ||
it('should work without snapshot images when not supported', async () => { | ||
mockPromptHandler.isSnapshotImageSupported.mockReturnValue(false); | ||
mockPromptHandler.runPrompt.mockResolvedValue('// Perform action without snapshot'); | ||
await index_1.default.perform('Perform action without snapshot support'); | ||
expect(mockFrameworkDriver.captureSnapshotImage).not.toHaveBeenCalled(); | ||
expect(mockFrameworkDriver.captureViewHierarchyString).toHaveBeenCalled(); | ||
expect(mockPromptHandler.runPrompt).toHaveBeenCalledWith(expect.stringContaining('Perform action without snapshot support'), undefined); | ||
}); | ||
}); | ||
}); |
{ | ||
"name": "detox-copilot", | ||
"version": "0.0.11", | ||
"version": "0.0.13", | ||
"description": "A flexible plugin that drives your tests with human-written commands, enhanced by the power of large language models (LLMs)", | ||
@@ -5,0 +5,0 @@ "keywords": [ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
63340
1287
8
3