backstage

Форк
0
388 строк · 10.9 Кб
1
/*
2
 * Copyright 2022 The Backstage Authors
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 *
8
 *     http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16

17
import * as util from './util';
18
import { Gitlab, GroupSchema } from '@gitbeaker/rest';
19
import { InputError } from '@backstage/errors';
20

21
// Mock the Gitlab client and its methods
22
const mockGitlabClient = {
23
  Groups: {
24
    show: jest.fn(),
25
  },
26
  Projects: {
27
    show: jest.fn(),
28
  },
29
  Epics: {
30
    all: jest.fn(),
31
  },
32
};
33

34
jest.mock('@gitbeaker/rest', () => ({
35
  Gitlab: class {
36
    constructor() {
37
      return mockGitlabClient;
38
    }
39
  },
40
}));
41

42
const mockConfig = {
43
  gitlab: [
44
    {
45
      host: 'gitlab.com',
46
      token: 'withToken',
47
      apiBaseUrl: 'gitlab.com/api/v4',
48
    },
49
    {
50
      host: 'gitlab.com',
51
      apiBaseUrl: 'gitlab.com/api/v4',
52
    },
53
  ],
54
};
55
describe('getTopLevelParentGroup', () => {
56
  afterEach(() => jest.resetAllMocks());
57

58
  // Mocked nested groups
59
  const mockGroups: GroupSchema[] = [
60
    {
61
      id: 789,
62
      parent_id: 0,
63
      path: '',
64
      description: '',
65
      visibility: '',
66
      share_with_group_lock: false,
67
      require_two_factor_authentication: false,
68
      two_factor_grace_period: 0,
69
      project_creation_level: '',
70
      subgroup_creation_level: '',
71
      lfs_enabled: false,
72
      default_branch_protection: 0,
73
      request_access_enabled: false,
74
      created_at: '',
75
      avatar_url: '',
76
      full_name: '',
77
      full_path: '',
78
      web_url: '',
79
      name: '',
80
    },
81
    {
82
      id: 456,
83
      parent_id: 789,
84
      path: '',
85
      description: '',
86
      visibility: '',
87
      share_with_group_lock: false,
88
      require_two_factor_authentication: false,
89
      two_factor_grace_period: 0,
90
      project_creation_level: '',
91
      subgroup_creation_level: '',
92
      lfs_enabled: false,
93
      default_branch_protection: 0,
94
      request_access_enabled: false,
95
      created_at: '',
96
      avatar_url: '',
97
      full_name: '',
98
      full_path: '',
99
      web_url: '',
100
      name: '',
101
    },
102
    {
103
      id: 123,
104
      parent_id: 456,
105
      path: '',
106
      description: '',
107
      visibility: '',
108
      share_with_group_lock: false,
109
      require_two_factor_authentication: false,
110
      two_factor_grace_period: 0,
111
      project_creation_level: '',
112
      subgroup_creation_level: '',
113
      lfs_enabled: false,
114
      default_branch_protection: 0,
115
      request_access_enabled: false,
116
      created_at: '',
117
      avatar_url: '',
118
      full_name: '',
119
      full_path: '',
120
      web_url: '',
121
      name: '',
122
    },
123
  ];
124

125
  // Top level group
126
  const mockTopParentGroup: GroupSchema = {
127
    id: 789,
128
    parent_id: 0,
129
    path: '',
130
    description: '',
131
    visibility: '',
132
    share_with_group_lock: false,
133
    require_two_factor_authentication: false,
134
    two_factor_grace_period: 0,
135
    project_creation_level: '',
136
    subgroup_creation_level: '',
137
    lfs_enabled: false,
138
    default_branch_protection: 0,
139
    request_access_enabled: false,
140
    created_at: '',
141
    avatar_url: '',
142
    full_name: '',
143
    full_path: '',
144
    web_url: '',
145
    name: '',
146
  };
147

148
  it('should return the top-level parent group if the input group has a parent in the hierarchy', async () => {
149
    // Instance with token
150
    const apiClient = new Gitlab({
151
      host: mockConfig.gitlab[0].host,
152
      token: mockConfig.gitlab[0].token!,
153
    });
154

155
    const showSpy = jest.spyOn(mockGitlabClient.Groups, 'show');
156

157
    // Mock implementation of Groups.show
158
    showSpy.mockImplementation(
159
      async (groupId: string | number): Promise<any> => {
160
        const id =
161
          typeof groupId === 'number' ? groupId : parseInt(groupId, 10);
162
        const mockGroup = mockGroups.find(group => group.id === id) || null;
163
        return mockGroup as GroupSchema;
164
      },
165
    );
166

167
    const action = util.getTopLevelParentGroup(apiClient, 123);
168

169
    const result = await action;
170
    expect(result).toEqual(mockTopParentGroup);
171
  });
172

173
  it('should return the input group if it has no parents in the hierarchy', async () => {
174
    // Instance with token
175
    const apiClient = new Gitlab({
176
      host: mockConfig.gitlab[0].host,
177
      token: mockConfig.gitlab[0].token!,
178
    });
179

180
    const showSpy = jest.spyOn(mockGitlabClient.Groups, 'show');
181

182
    // Mock implementation of Groups.show
183
    showSpy.mockImplementation(
184
      async (groupId: string | number): Promise<any> => {
185
        const id =
186
          typeof groupId === 'number' ? groupId : parseInt(groupId, 10);
187
        const mockGroup = mockGroups.find(group => group.id === id) || null;
188
        return mockGroup as GroupSchema;
189
      },
190
    );
191

192
    const action = util.getTopLevelParentGroup(apiClient, 789);
193

194
    const result = await action;
195
    expect(result).toEqual(mockTopParentGroup);
196
  });
197
});
198

199
describe('checkEpicScope', () => {
200
  afterEach(() => jest.resetAllMocks());
201

202
  it('should return true if the project is inside the epic scope', async () => {
203
    const apiClient = new Gitlab({
204
      host: mockConfig.gitlab[0].host,
205
      token: mockConfig.gitlab[0].token!,
206
    });
207

208
    const projectId = 123;
209
    const epicId = 456;
210

211
    // Mock project, top-level parent group, and epic
212
    const mockProject = {
213
      id: 123,
214
      name: 'You learn',
215
      namespace: { id: 789 },
216
      path_with_namespace: 'at-once/you-learn',
217
    };
218
    const mockTopParentGroup = {
219
      id: 789,
220
      name: 'LivingTwice',
221
      full_path: 'at-once/you-learn',
222
    };
223
    const mockEpic = { id: epicId, group_id: 789 };
224

225
    mockGitlabClient.Projects.show.mockResolvedValue(mockProject);
226
    mockGitlabClient.Groups.show.mockResolvedValue(mockTopParentGroup);
227
    mockGitlabClient.Epics.all.mockResolvedValue([mockEpic]);
228

229
    const result = await util.checkEpicScope(apiClient, projectId, epicId);
230

231
    expect(result).toBe(true);
232
    expect(mockGitlabClient.Projects.show).toHaveBeenCalledWith(projectId);
233
    expect(mockGitlabClient.Groups.show).toHaveBeenCalledWith(
234
      mockProject.namespace.id,
235
    );
236
    expect(mockGitlabClient.Epics.all).toHaveBeenCalledWith(
237
      mockTopParentGroup.id,
238
    );
239
  });
240

241
  it('should return false if the project is not inside the epic scope', async () => {
242
    const apiClient = new Gitlab({
243
      host: mockConfig.gitlab[0].host,
244
      token: mockConfig.gitlab[0].token!,
245
    });
246

247
    const projectId = 123;
248
    const epicId = 45;
249

250
    // Mock project, top-level parent group, and epic
251
    const mockProject = {
252
      id: 123,
253
      name: 'You learn',
254
      namespace: { id: 32 },
255
      path_with_namespace: 'at-once/you-learn',
256
    };
257
    const mockTopParentGroup = {
258
      id: 32,
259
      name: 'TheWalls',
260
      full_path: 'you-built/within',
261
    };
262

263
    const mockEpic = { id: epicId, group_id: 32 };
264

265
    mockGitlabClient.Projects.show.mockResolvedValue(mockProject);
266
    mockGitlabClient.Groups.show.mockResolvedValue(mockTopParentGroup);
267
    mockGitlabClient.Epics.all.mockResolvedValue([mockEpic]);
268

269
    const result = await util.checkEpicScope(apiClient, projectId, epicId);
270

271
    expect(result).toBe(false);
272
    expect(mockGitlabClient.Projects.show).toHaveBeenCalledWith(projectId);
273
    expect(mockGitlabClient.Groups.show).toHaveBeenCalledWith(
274
      mockProject.namespace.id,
275
    );
276
    expect(mockGitlabClient.Epics.all).toHaveBeenCalledWith(
277
      mockTopParentGroup.id,
278
    );
279
  });
280

281
  it('should throw an InputError if the project is not found', async () => {
282
    const apiClient = new Gitlab({
283
      host: mockConfig.gitlab[0].host,
284
      token: mockConfig.gitlab[0].token!,
285
    });
286

287
    const projectId = 123;
288
    const epicId = 456;
289

290
    mockGitlabClient.Projects.show.mockResolvedValue(null);
291

292
    await expect(
293
      util.checkEpicScope(apiClient, projectId, epicId),
294
    ).rejects.toThrow(InputError);
295
    expect(mockGitlabClient.Projects.show).toHaveBeenCalledWith(projectId);
296
  });
297

298
  it('should throw an InputError if the top-level parent group is not found', async () => {
299
    const apiClient = new Gitlab({
300
      host: mockConfig.gitlab[0].host,
301
      token: mockConfig.gitlab[0].token!,
302
    });
303

304
    const projectId = 123;
305
    const epicId = 456;
306

307
    mockGitlabClient.Projects.show.mockResolvedValue({
308
      id: 123,
309
      name: 'You learn',
310
      namespace: { id: 789 },
311
      path_with_namespace: 'at-once/you-learn',
312
    });
313
    mockGitlabClient.Groups.show.mockResolvedValue(null);
314

315
    await expect(
316
      util.checkEpicScope(apiClient, projectId, epicId),
317
    ).rejects.toThrow(InputError);
318
    expect(mockGitlabClient.Projects.show).toHaveBeenCalledWith(projectId);
319
    expect(mockGitlabClient.Groups.show).toHaveBeenCalledWith(789);
320
  });
321

322
  it('should throw an InputError if the epic is not found', async () => {
323
    const apiClient = new Gitlab({
324
      host: mockConfig.gitlab[0].host,
325
      token: mockConfig.gitlab[0].token!,
326
    });
327

328
    const projectId = 123;
329
    const epicId = 456;
330

331
    mockGitlabClient.Projects.show.mockResolvedValue({
332
      id: 123,
333
      name: 'You learn',
334
      namespace: { id: 789 },
335
      path_with_namespace: 'at-once/you-learn',
336
    });
337
    mockGitlabClient.Groups.show.mockResolvedValue({
338
      id: 789,
339
      name: 'LivingTwice',
340
      full_path: 'at-once/you-learn',
341
    });
342
    mockGitlabClient.Epics.all.mockResolvedValue([]);
343

344
    await expect(
345
      util.checkEpicScope(apiClient, projectId, epicId),
346
    ).rejects.toThrow(InputError);
347
    expect(mockGitlabClient.Projects.show).toHaveBeenCalledWith(projectId);
348
    expect(mockGitlabClient.Groups.show).toHaveBeenCalledWith(789);
349
    expect(mockGitlabClient.Epics.all).toHaveBeenCalledWith(789);
350
  });
351
});
352

353
describe('convertDate', () => {
354
  it('should convert a valid input date with miliseconds to an ISO string', () => {
355
    const inputDate = '1970-01-01T12:00:00.000Z';
356
    const defaultDate = '1978-10-09T12:00:00Z';
357

358
    const result = util.convertDate(inputDate, defaultDate);
359

360
    expect(result).toEqual('1970-01-01T12:00:00.000Z');
361
  });
362

363
  it('should convert a valid input date to an ISO string', () => {
364
    const inputDate = '1970-01-01T12:00:00Z';
365
    const defaultDate = '1978-10-09T12:00:00Z';
366

367
    const result = util.convertDate(inputDate, defaultDate);
368

369
    expect(result).toEqual('1970-01-01T12:00:00.000Z');
370
  });
371

372
  it('should use default date if input date is undefined', () => {
373
    const inputDate = undefined;
374
    const defaultDate = '1970-01-01T12:00:00Z';
375

376
    const result = util.convertDate(inputDate, defaultDate);
377

378
    expect(result).toEqual('1970-01-01T12:00:00.000Z');
379
  });
380

381
  it('should throw an InputError if  input date is invalid', () => {
382
    const inputDate = 'invalidDate';
383
    const defaultDate = '2023-02-01T12:00:00Z';
384

385
    // Expecting an InputError to be thrown
386
    expect(() => util.convertDate(inputDate, defaultDate)).toThrow(InputError);
387
  });
388
});
389

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.