tests: added test suite for gitlab publisher action

Signed-off-by: Johan Haals <johan.haals@gmail.com>
This commit is contained in:
blam
2021-02-26 09:22:02 +01:00
committed by Johan Haals
parent c630401572
commit e787b088b8
3 changed files with 221 additions and 4 deletions
@@ -0,0 +1,165 @@
/*
* Copyright 2020 Spotify AB
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
jest.mock('../../../stages/publish/helpers');
jest.mock('@gitbeaker/node');
import { createPublishGitlabAction } from './gitlab';
import { ScmIntegrations } from '@backstage/integration';
import { ConfigReader } from '@backstage/config';
import { getVoidLogger } from '@backstage/backend-common';
import { PassThrough } from 'stream';
import { initRepoAndPush } from '../../../stages/publish/helpers';
describe('Gitlab Publish Action', () => {
const integrations = ScmIntegrations.fromConfig(
new ConfigReader({
integrations: {
gitlab: [
{
host: 'gitlab.com',
token: 'tokenlols',
apiBaseUrl: 'https://api.gitlab.com',
},
{
host: 'hosted.gitlab.com',
apiBaseUrl: 'https://api.hosted.gitlab.com',
},
],
},
}),
);
const action = createPublishGitlabAction({ integrations });
const mockContext = {
input: {
repoUrl: 'gitlab.com?repo=repo&owner=owner',
repoVisibility: 'private',
},
workspacePath: 'lol',
logger: getVoidLogger(),
logStream: new PassThrough(),
output: jest.fn(),
createTemporaryDirectory: jest.fn(),
};
const { mockGitlabClient } = require('@gitbeaker/node');
beforeEach(() => {
jest.resetAllMocks();
});
it('should throw an error when the repoUrl is not well formed', async () => {
await expect(
action.handler({
...mockContext,
input: { repoUrl: 'gitlab.com?repo=bob' },
}),
).rejects.toThrow(/missing owner/);
await expect(
action.handler({
...mockContext,
input: { repoUrl: 'gitlab.com?owner=owner' },
}),
).rejects.toThrow(/missing repo/);
});
it('should throw if there is no integration config provided', async () => {
await expect(
action.handler({
...mockContext,
input: { repoUrl: 'missing.com?repo=bob&owner=owner' },
}),
).rejects.toThrow(/No matching integration configuration/);
});
it('should throw if there is no token in the integration config that is returned', async () => {
await expect(
action.handler({
...mockContext,
input: {
repoUrl: 'hosted.gitlab.com?repo=bob&owner=owner',
},
}),
).rejects.toThrow(/No token available for host/);
});
it('should call the correct Gitlab APIs when the owner is an organization', async () => {
mockGitlabClient.Namespaces.show.mockResolvedValue({ id: 1234 });
mockGitlabClient.Projects.create.mockResolvedValue({
http_url_to_repo: 'http://mockurl.git',
});
await action.handler(mockContext);
expect(mockGitlabClient.Namespaces.show).toHaveBeenCalledWith('owner');
expect(mockGitlabClient.Projects.create).toHaveBeenCalledWith({
namespace_id: 1234,
name: 'repo',
visibility: 'private',
});
});
it('should call the correct Gitlab APIs when the owner is not an organization', async () => {
mockGitlabClient.Namespaces.show.mockResolvedValue({ id: null });
mockGitlabClient.Users.current.mockResolvedValue({ id: 12345 });
mockGitlabClient.Projects.create.mockResolvedValue({
http_url_to_repo: 'http://mockurl.git',
});
await action.handler(mockContext);
expect(mockGitlabClient.Namespaces.show).toHaveBeenCalledWith('owner');
expect(mockGitlabClient.Projects.create).toHaveBeenCalledWith({
namespace_id: 12345,
name: 'repo',
visibility: 'private',
});
});
it('should call initRepoAndPush with the correct values', async () => {
mockGitlabClient.Namespaces.show.mockResolvedValue({ id: 1234 });
mockGitlabClient.Projects.create.mockResolvedValue({
http_url_to_repo: 'http://mockurl.git',
});
await action.handler(mockContext);
expect(initRepoAndPush).toHaveBeenCalledWith({
dir: mockContext.workspacePath,
remoteUrl: 'http://mockurl.git',
auth: { username: 'oauth2', password: 'tokenlols' },
logger: mockContext.logger,
});
});
it('should call output with the remoteUrl and repoContentsUrl', async () => {
mockGitlabClient.Namespaces.show.mockResolvedValue({ id: 1234 });
mockGitlabClient.Projects.create.mockResolvedValue({
http_url_to_repo: 'http://mockurl.git',
});
await action.handler(mockContext);
expect(mockContext.output).toHaveBeenCalledWith(
'remoteUrl',
'http://mockurl',
);
expect(mockContext.output).toHaveBeenCalledWith(
'repoContentsUrl',
'http://mockurl/-/blob/master',
);
});
});
@@ -40,6 +40,7 @@ describe('Github Publish Action', () => {
repoUrl: 'github.com?repo=repo&owner=owner',
description: 'description',
repoVisibility: 'private',
access: 'owner/blam',
},
workspacePath: 'lol',
logger: getVoidLogger(),
@@ -51,7 +52,7 @@ describe('Github Publish Action', () => {
const { mockGithubClient } = require('@octokit/rest');
beforeEach(() => {
jest.restoreAllMocks();
jest.resetAllMocks();
});
it('should throw an error when the repoUrl is not well formed', async () => {
@@ -178,6 +179,59 @@ describe('Github Publish Action', () => {
});
});
it('should add access for the team when it starts with the owner', async () => {
mockGithubClient.users.getByUsername.mockResolvedValue({
data: { type: 'User' },
});
mockGithubClient.repos.createForAuthenticatedUser.mockResolvedValue({
data: {
clone_url: 'https://github.com/clone/url.git',
html_url: 'https://github.com/html/url',
},
});
await action.handler(mockContext);
expect(
mockGithubClient.teams.addOrUpdateRepoPermissionsInOrg,
).toHaveBeenCalledWith({
org: 'owner',
team_slug: 'blam',
owner: 'owner',
repo: 'repo',
permission: 'admin',
});
});
it('should add outside collaborators when provided', async () => {
mockGithubClient.users.getByUsername.mockResolvedValue({
data: { type: 'User' },
});
mockGithubClient.repos.createForAuthenticatedUser.mockResolvedValue({
data: {
clone_url: 'https://github.com/clone/url.git',
html_url: 'https://github.com/html/url',
},
});
await action.handler({
...mockContext,
input: {
...mockContext.input,
access: 'outsidecollaborator',
},
});
expect(mockGithubClient.repos.addCollaborator).toHaveBeenCalledWith({
username: 'outsidecollaborator',
owner: 'owner',
repo: 'repo',
permission: 'admin',
});
});
it('should call output with the remoteUrl and the repoContentsUrl', async () => {
mockGithubClient.users.getByUsername.mockResolvedValue({
data: { type: 'User' },
@@ -75,9 +75,7 @@ export function createPublishGitlabAction(options: {
}
if (!integrationConfig.config.token) {
throw new InputError(
`No token provided for GitLab Integration ${host}`,
);
throw new InputError(`No token available for host ${host}`);
}
const client = new Gitlab({