Skip to content

Commit d77fdae

Browse files
committed
bugfix-303-bugbot-first-message-bugs: Add comprehensive tests for AiRepository, IssueRepository, ProjectRepository, and PullRequestRepository. Implement new test cases for handling various response scenarios, including invalid JSON and label management. Improve test coverage for project details and user authentication methods.
1 parent 3461fce commit d77fdae

4 files changed

Lines changed: 1387 additions & 3 deletions

File tree

src/data/repository/__tests__/ai_repository.test.ts

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -375,6 +375,56 @@ describe('AiRepository', () => {
375375
expect(result).toBeUndefined();
376376
expect(mockFetch).toHaveBeenCalledTimes(OPENCODE_MAX_RETRIES * 2);
377377
});
378+
379+
it('returns undefined when expectJson is true but response has no JSON object (no curly brace)', async () => {
380+
const ai = createAi();
381+
const sessionOk = { ok: true, text: async () => JSON.stringify({ id: 's1' }) };
382+
const messageNoJson = {
383+
ok: true,
384+
status: 200,
385+
text: async () =>
386+
JSON.stringify({
387+
parts: [{ type: 'text', text: 'No JSON here, just plain text.' }],
388+
}),
389+
};
390+
for (let i = 0; i < OPENCODE_MAX_RETRIES; i++) {
391+
mockFetch.mockResolvedValueOnce(sessionOk).mockResolvedValueOnce(messageNoJson);
392+
}
393+
const promise = repo.askAgent(ai, 'plan', 'P', { expectJson: true, schema: {} });
394+
await jest.advanceTimersByTimeAsync((OPENCODE_MAX_RETRIES - 1) * OPENCODE_RETRY_DELAY_MS);
395+
const result = await promise;
396+
expect(result).toBeUndefined();
397+
});
398+
399+
it('returns undefined when session create returns invalid JSON (error with cause)', async () => {
400+
const ai = createAi();
401+
mockFetch.mockResolvedValue({ ok: true, text: async () => 'not valid json' });
402+
const promise = repo.askAgent(ai, 'plan', 'P', {});
403+
await jest.advanceTimersByTimeAsync((OPENCODE_MAX_RETRIES - 1) * OPENCODE_RETRY_DELAY_MS);
404+
const result = await promise;
405+
expect(result).toBeUndefined();
406+
expect(mockFetch).toHaveBeenCalledTimes(OPENCODE_MAX_RETRIES);
407+
});
408+
409+
it('hits single-quote path in extractor when response has single-quoted object (invalid JSON)', async () => {
410+
const ai = createAi();
411+
const sessionOk = { ok: true, text: async () => JSON.stringify({ id: 's1' }) };
412+
const messageSingleQuote = {
413+
ok: true,
414+
status: 200,
415+
text: async () =>
416+
JSON.stringify({
417+
parts: [{ type: 'text', text: "Note { 'a': 1 }" }],
418+
}),
419+
};
420+
for (let i = 0; i < OPENCODE_MAX_RETRIES; i++) {
421+
mockFetch.mockResolvedValueOnce(sessionOk).mockResolvedValueOnce(messageSingleQuote);
422+
}
423+
const promise = repo.askAgent(ai, 'plan', 'P', { expectJson: true, schema: {} });
424+
await jest.advanceTimersByTimeAsync((OPENCODE_MAX_RETRIES - 1) * OPENCODE_RETRY_DELAY_MS);
425+
const result = await promise;
426+
expect(result).toBeUndefined();
427+
});
378428
});
379429

380430
describe('copilotMessage', () => {

0 commit comments

Comments
 (0)