Skip to content

Commit 89b267b

Browse files
committed
bugfix-319-setup-crash-on-repository-with-no-issues: Improve error handling and test coverage for label and issue type related operations.
1 parent 10dda94 commit 89b267b

2 files changed

Lines changed: 71 additions & 1 deletion

File tree

src/data/model/__tests__/execution.test.ts

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ jest.mock('../../../usecase/steps/common/get_hotfix_version_use_case', () => ({
6767
})),
6868
}));
6969

70-
import { INPUT_KEYS } from '../../../utils/constants';
70+
import { ACTIONS, INPUT_KEYS } from '../../../utils/constants';
7171
import { Ai } from '../ai';
7272
import { Branches } from '../branches';
7373
import { Emoji } from '../emoji';
@@ -750,5 +750,20 @@ describe('Execution', () => {
750750
expect(e.hotfix.baseVersion).toBeUndefined();
751751
expect(e.hotfix.version).toBeUndefined();
752752
});
753+
it('setup skips internal label fetch error when ACTION is INITIAL_SETUP', async () => {
754+
const singleAction = new SingleAction(ACTIONS.INITIAL_SETUP, '1', '', '', '');
755+
const issue = makeIssue({ eventName: 'issues', issue: { number: 1 } } as never);
756+
const e = buildExecution({ eventName: 'issues', issue: { number: 1 } } as never, { singleAction, issue });
757+
mockGetLabels.mockRejectedValue(new Error('Label error'));
758+
await e.setup();
759+
expect(e.labels.currentIssueLabels).toEqual([]);
760+
});
761+
762+
it('setup throws when getLabels fails and not INITIAL_SETUP', async () => {
763+
const issue = makeIssue({ eventName: 'issues', issue: { number: 1 } } as never);
764+
const e = buildExecution({ eventName: 'issues', issue: { number: 1 } } as never, { issue });
765+
mockGetLabels.mockRejectedValue(new Error('Fatal label error'));
766+
await expect(e.setup()).rejects.toThrow('Fatal label error');
767+
});
753768
});
754769
});

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

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,20 @@ function makeLabels(overrides: { currentIssueLabels?: string[] } = {}): Labels {
8585
return labels;
8686
}
8787

88+
function makeIssueTypes(): IssueTypes {
89+
return new IssueTypes(
90+
'Task', 'Task desc', 'BLUE',
91+
'Bug', 'Bug desc', 'RED',
92+
'Feature', 'Feature desc', 'GREEN',
93+
'Docs', 'Docs desc', 'GREY',
94+
'Maintenance', 'Maint desc', 'GREY',
95+
'Hotfix', 'Hotfix desc', 'RED',
96+
'Release', 'Release desc', 'BLUE',
97+
'Question', 'Q desc', 'PURPLE',
98+
'Help', 'Help desc', 'PURPLE'
99+
);
100+
}
101+
88102
describe('IssueRepository', () => {
89103
const repo = new IssueRepository();
90104

@@ -470,6 +484,12 @@ describe('IssueRepository', () => {
470484
expect(result).toEqual([]);
471485
expect(mockRest.issues.listLabelsOnIssue).toHaveBeenCalled();
472486
});
487+
488+
it('returns empty array when listLabelsOnIssue returns non-404 error', async () => {
489+
mockRest.issues.listLabelsOnIssue.mockRejectedValue(new Error('Some other error'));
490+
const result = await repo.getLabels('owner', 'repo', 1, 'token');
491+
expect(result).toEqual([]);
492+
});
473493
});
474494

475495
describe('setLabels', () => {
@@ -1147,6 +1167,41 @@ describe('IssueRepository', () => {
11471167
expect(result.errors.length).toBeGreaterThan(0);
11481168
expect(result.errors.some((e) => e.includes('Create failed'))).toBe(true);
11491169
});
1170+
1171+
it('setIssueType catches error and continues (re-throws in IssueRepository)', async () => {
1172+
const labels = makeLabels({ currentIssueLabels: ['bug'] });
1173+
const issueTypes = makeIssueTypes();
1174+
mockGraphql.mockRejectedValue(new Error('Global error'));
1175+
await expect(repo.setIssueType('o', 'r', 1, labels, issueTypes, 't')).rejects.toThrow('Global error');
1176+
});
1177+
1178+
it('createIssueType throws when organization is null', async () => {
1179+
mockGraphql.mockResolvedValueOnce({ organization: null });
1180+
await expect(repo.createIssueType('o', 'n', 'd', 'c', 't')).rejects.toThrow('No se pudo obtener la organización o');
1181+
});
1182+
1183+
it('listIssueTypes throws when organization is null', async () => {
1184+
mockGraphql.mockResolvedValueOnce({ organization: null });
1185+
await expect(repo.listIssueTypes('o', 't')).rejects.toThrow('No se pudo obtener la organización o');
1186+
});
1187+
1188+
it('createIssueType throws when organization is missing (GraphQL error scenario)', async () => {
1189+
mockGraphql.mockResolvedValueOnce({ organization: null });
1190+
await expect(repo.createIssueType('o', 'n', 'd', 'c', 't')).rejects.toThrow('No se pudo obtener la organización o');
1191+
});
1192+
1193+
it('ensureLabel handles 422 error "already exists"', async () => {
1194+
mockRest.issues.listLabelsForRepo.mockResolvedValue({ data: [] });
1195+
mockRest.issues.createLabel.mockRejectedValue({ status: 422, message: 'already exists' });
1196+
const result = await repo.ensureLabel('o', 'r', 'new', 'c', 'd', 't');
1197+
expect(result).toEqual({ created: false, existed: true });
1198+
});
1199+
1200+
it('ensureLabel re-throws other errors', async () => {
1201+
mockRest.issues.listLabelsForRepo.mockResolvedValue({ data: [] });
1202+
mockRest.issues.createLabel.mockRejectedValue(new Error('Fatal'));
1203+
await expect(repo.ensureLabel('o', 'r', 'new', 'c', 'd', 't')).rejects.toThrow('Fatal');
1204+
});
11501205
});
11511206
});
11521207

0 commit comments

Comments
 (0)