diff --git a/plugins/scaffolder-backend-module-gitlab/src/actions/createGitlabIssueAction.test.ts b/plugins/scaffolder-backend-module-gitlab/src/actions/createGitlabIssueAction.test.ts index cd85454665..ce57fac9e5 100644 --- a/plugins/scaffolder-backend-module-gitlab/src/actions/createGitlabIssueAction.test.ts +++ b/plugins/scaffolder-backend-module-gitlab/src/actions/createGitlabIssueAction.test.ts @@ -65,9 +65,8 @@ describe('gitlab:issues:create', () => { repoUrl: 'gitlab.com?repo=repo&owner=owner', projectId: 123, title: 'Computer banks to rule the world', - // token: 'myAwesomeToken', }, - workspacePath: 'lol', + workspacePath: 'seen2much', logger: getVoidLogger(), logStream: new PassThrough(), output: jest.fn(), @@ -117,7 +116,7 @@ describe('gitlab:issues:create', () => { title: 'Computer banks to rule the world', token: 'myAwesomeToken', }, - workspacePath: 'lol', + workspacePath: 'seen2much', logger: getVoidLogger(), logStream: new PassThrough(), output: jest.fn(), @@ -158,55 +157,4 @@ describe('gitlab:issues:create', () => { 'https://gitlab.com/hangar18-/issues/42', ); }); - - it('should return a Gitlab issue when called with an epic id', async () => { - const mockContext = { - input: { - repoUrl: 'gitlab.com?repo=repo&owner=owner', - projectId: 123, - title: 'Instruments to sight the stars', - token: 'myAwesomeToken', - epicId: 1234, - }, - workspacePath: 'lol', - logger: getVoidLogger(), - logStream: new PassThrough(), - output: jest.fn(), - createTemporaryDirectory: jest.fn(), - }; - - mockGitlabClient.Issues.create.mockResolvedValue({ - id: 42, - web_url: 'https://gitlab.com/hangar18-/issues/42', - }); - - await action.handler({ - ...mockContext, - }); - - expect(mockGitlabClient.Issues.create).toHaveBeenCalledWith( - 123, - 'Computer banks to rule the world', - { - issueType: undefined, - description: '', - assigneeIds: [], - confidential: false, - epicId: 1234, - labels: '', - createdAt: new Date().toISOString(), - dueDate: undefined, - discussionToResolve: '', - mergeRequestToResolveDiscussionsOf: undefined, - milestoneId: undefined, - weight: undefined, - }, - ); - - expect(mockContext.output).toHaveBeenCalledWith('issueId', 42); - expect(mockContext.output).toHaveBeenCalledWith( - 'issueUrl', - 'https://gitlab.com/hangar18-/issues/42', - ); - }); }); diff --git a/plugins/scaffolder-backend-module-gitlab/src/util.test.ts b/plugins/scaffolder-backend-module-gitlab/src/util.test.ts index 0829d1321f..4de4eca786 100644 --- a/plugins/scaffolder-backend-module-gitlab/src/util.test.ts +++ b/plugins/scaffolder-backend-module-gitlab/src/util.test.ts @@ -16,6 +16,7 @@ import * as util from './util'; import { Gitlab, GroupSchema } from '@gitbeaker/rest'; +import { InputError } from '@backstage/errors'; // Mock the Gitlab client and its methods const setupGitlabMock = () => { @@ -25,11 +26,30 @@ const setupGitlabMock = () => { Groups: { show: jest.fn(), }, + Projects: { + show: jest.fn(), + }, + Epics: { + all: jest.fn(), + }, })), }; }); }; +const mockConfig = { + gitlab: [ + { + host: 'gitlab.com', + token: 'withToken', + apiBaseUrl: 'gitlab.com/api/v4', + }, + { + host: 'gitlab.com', + apiBaseUrl: 'gitlab.com/api/v4', + }, + ], +}; describe('getTopLevelParentGroup', () => { beforeEach(() => { setupGitlabMock(); @@ -37,96 +57,9 @@ describe('getTopLevelParentGroup', () => { afterEach(() => jest.resetAllMocks()); - const mockConfig = { - gitlab: [ - { - host: 'gitlab.com', - token: 'withToken', - apiBaseUrl: 'gitlab.com/api/v4', - }, - { - host: 'gitlab.com', - apiBaseUrl: 'gitlab.com/api/v4', - }, - ], - }; - - it('should return the top-level parent group', async () => { - // Instance with token - const mockGitlabClient = new Gitlab({ - host: mockConfig.gitlab[0].host, - token: mockConfig.gitlab[0].token!, - }); - - // Mocked nested groups - const mockGroups: GroupSchema[] = [ - { - id: 789, - parent_id: 0, - path: '', - description: '', - visibility: '', - share_with_group_lock: false, - require_two_factor_authentication: false, - two_factor_grace_period: 0, - project_creation_level: '', - subgroup_creation_level: '', - lfs_enabled: false, - default_branch_protection: 0, - request_access_enabled: false, - created_at: '', - avatar_url: '', - full_name: '', - full_path: '', - web_url: '', - name: '', - }, - { - id: 456, - parent_id: 789, - path: '', - description: '', - visibility: '', - share_with_group_lock: false, - require_two_factor_authentication: false, - two_factor_grace_period: 0, - project_creation_level: '', - subgroup_creation_level: '', - lfs_enabled: false, - default_branch_protection: 0, - request_access_enabled: false, - created_at: '', - avatar_url: '', - full_name: '', - full_path: '', - web_url: '', - name: '', - }, - { - id: 123, - parent_id: 456, - path: '', - description: '', - visibility: '', - share_with_group_lock: false, - require_two_factor_authentication: false, - two_factor_grace_period: 0, - project_creation_level: '', - subgroup_creation_level: '', - lfs_enabled: false, - default_branch_protection: 0, - request_access_enabled: false, - created_at: '', - avatar_url: '', - full_name: '', - full_path: '', - web_url: '', - name: '', - }, - ]; - - // Top level group - const mockTopParentGroup: GroupSchema = { + // Mocked nested groups + const mockGroups: GroupSchema[] = [ + { id: 789, parent_id: 0, path: '', @@ -146,7 +79,80 @@ describe('getTopLevelParentGroup', () => { full_path: '', web_url: '', name: '', - }; + }, + { + id: 456, + parent_id: 789, + path: '', + description: '', + visibility: '', + share_with_group_lock: false, + require_two_factor_authentication: false, + two_factor_grace_period: 0, + project_creation_level: '', + subgroup_creation_level: '', + lfs_enabled: false, + default_branch_protection: 0, + request_access_enabled: false, + created_at: '', + avatar_url: '', + full_name: '', + full_path: '', + web_url: '', + name: '', + }, + { + id: 123, + parent_id: 456, + path: '', + description: '', + visibility: '', + share_with_group_lock: false, + require_two_factor_authentication: false, + two_factor_grace_period: 0, + project_creation_level: '', + subgroup_creation_level: '', + lfs_enabled: false, + default_branch_protection: 0, + request_access_enabled: false, + created_at: '', + avatar_url: '', + full_name: '', + full_path: '', + web_url: '', + name: '', + }, + ]; + + // Top level group + const mockTopParentGroup: GroupSchema = { + id: 789, + parent_id: 0, + path: '', + description: '', + visibility: '', + share_with_group_lock: false, + require_two_factor_authentication: false, + two_factor_grace_period: 0, + project_creation_level: '', + subgroup_creation_level: '', + lfs_enabled: false, + default_branch_protection: 0, + request_access_enabled: false, + created_at: '', + avatar_url: '', + full_name: '', + full_path: '', + web_url: '', + name: '', + }; + + it('should return the top-level parent group if the input group has a parent in the hierarchy', async () => { + // Instance with token + const mockGitlabClient = new Gitlab({ + host: mockConfig.gitlab[0].host, + token: mockConfig.gitlab[0].token!, + }); const showSpy = jest.spyOn(mockGitlabClient.Groups, 'show'); @@ -165,4 +171,122 @@ describe('getTopLevelParentGroup', () => { const result = await action; expect(result).toEqual(mockTopParentGroup); }); + + it('should return the input group if it has no parents in the hierarchy', async () => { + // Instance with token + const mockGitlabClient = new Gitlab({ + host: mockConfig.gitlab[0].host, + token: mockConfig.gitlab[0].token!, + }); + + const showSpy = jest.spyOn(mockGitlabClient.Groups, 'show'); + + // Mock implementation of Groups.show + showSpy.mockImplementation( + async (groupId: string | number): Promise => { + const id = + typeof groupId === 'number' ? groupId : parseInt(groupId, 10); + const mockGroup = mockGroups.find(group => group.id === id) || null; + return mockGroup as GroupSchema; + }, + ); + + const action = util.getTopLevelParentGroup(mockGitlabClient, 789); + + const result = await action; + expect(result).toEqual(mockTopParentGroup); + }); +}); + +describe('checkEpicScope', () => { + afterEach(() => jest.resetAllMocks()); + + it('should return true if the project and epic are found', async () => { + const mockGitlabClient = new Gitlab({ + host: mockConfig.gitlab[0].host, + token: mockConfig.gitlab[0].token!, + }); + + const projectId = 123; + const epicId = 456; + + // Mock project and top-level parent group + const mockProject = { namespace: { id: 789 } }; + const mockTopParentGroup = { id: 789, name: 'MockGroup' }; + + mockGitlabClient.Projects.show.mockResolvedValue(mockProject); + mockGitlabClient.Groups.show.mockResolvedValue(mockTopParentGroup); + mockGitlabClient.Epics.all.mockResolvedValue([ + { id: epicId, group_id: 789 }, + ]); + + const result = await checkEpicScope(mockGitlabClient, projectId, epicId); + + expect(result).toBe(true); + expect(mockGitlabClient.Projects.show).toHaveBeenCalledWith(projectId); + expect(mockGitlabClient.Groups.show).toHaveBeenCalledWith( + mockProject.namespace.id, + ); + expect(mockGitlabClient.Epics.all).toHaveBeenCalledWith( + mockTopParentGroup.id, + ); + }); + + it('should throw InputError if the project is not found', async () => { + const mockClient = new Gitlab(); + const projectId = 123; + const epicId = 456; + + // Mocking the absence of the project + mockClient.Projects.show.mockResolvedValue(null); + + await expect(checkEpicScope(mockClient, projectId, epicId)).rejects.toThrow( + new InputError( + `Project with id ${projectId} not found. Check your GitLab instance.`, + ), + ); + + expect(mockClient.Projects.show).toHaveBeenCalledWith(projectId); + expect(mockClient.Groups.show).not.toHaveBeenCalled(); + expect(mockClient.Epics.all).not.toHaveBeenCalled(); + }); + + // Add more test cases as needed for different scenarios +}); + +describe('convertDate', () => { + it('should convert a valid input date with miliseconds to an ISO string', () => { + const inputDate = '1970-01-01T12:00:00.000Z'; + const defaultDate = '1978-10-09T12:00:00Z'; + + const result = util.convertDate(inputDate, defaultDate); + + expect(result).toEqual('1970-01-01T12:00:00.000Z'); + }); + + it('should convert a valid input date to an ISO string', () => { + const inputDate = '1970-01-01T12:00:00Z'; + const defaultDate = '1978-10-09T12:00:00Z'; + + const result = util.convertDate(inputDate, defaultDate); + + expect(result).toEqual('1970-01-01T12:00:00.000Z'); + }); + + it('should use default date if input date is undefined', () => { + const inputDate = undefined; + const defaultDate = '1970-01-01T12:00:00Z'; + + const result = util.convertDate(inputDate, defaultDate); + + expect(result).toEqual('1970-01-01T12:00:00.000Z'); + }); + + it('should throw an InputError if input date is invalid', () => { + const inputDate = 'invalidDate'; + const defaultDate = '2023-02-01T12:00:00Z'; + + // Expecting an InputError to be thrown + expect(() => util.convertDate(inputDate, defaultDate)).toThrow(InputError); + }); });