Add examples for publish:bitbucketServer:pull-request scaffolder action & improve related tests

Signed-off-by: parmar-abhinav <abhinavparmar147@gmail.com>
This commit is contained in:
parmar-abhinav
2024-04-18 09:04:14 +05:30
parent 16ef9e59e5
commit 24dd6559fe
4 changed files with 531 additions and 0 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-scaffolder-backend-module-bitbucket-server': patch
---
Add examples for `publish:bitbucketServer:pull-request` scaffolder action & improve related tests
@@ -0,0 +1,406 @@
/*
* Copyright 2023 The Backstage Authors
*
* 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('@backstage/plugin-scaffolder-node', () => {
return {
...jest.requireActual('@backstage/plugin-scaffolder-node'),
initRepoAndPush: jest.fn().mockResolvedValue({
commitHash: '220f19cc36b551763d157f1b5e4a4b446165dbd6',
}),
commitAndPushRepo: jest.fn().mockResolvedValue({
commitHash: '220f19cc36b551763d157f1b5e4a4b446165dbd6',
}),
};
});
import { createPublishBitbucketServerPullRequestAction } from './bitbucketServerPullRequest';
import { rest } from 'msw';
import { setupServer } from 'msw/node';
import { setupRequestMockHandlers } from '@backstage/backend-test-utils';
import { ScmIntegrations } from '@backstage/integration';
import { ConfigReader } from '@backstage/config';
import yaml from 'yaml';
import { examples } from './bitbucketServerPullRequest.examples';
import { createMockActionContext } from '@backstage/plugin-scaffolder-node-test-utils';
describe('publish:bitbucketServer:pull-request', () => {
const config = new ConfigReader({
integrations: {
bitbucketServer: [
{
host: 'hosted.bitbucket.com',
token: 'thing',
apiBaseUrl: 'https://hosted.bitbucket.com/rest/api/1.0',
},
{
host: 'basic-auth.bitbucket.com',
username: 'test-user',
password: 'test-password',
apiBaseUrl: 'https://basic-auth.bitbucket.com/rest/api/1.0',
},
{
host: 'no-credentials.bitbucket.com',
},
],
},
});
const integrations = ScmIntegrations.fromConfig(config);
const action = createPublishBitbucketServerPullRequestAction({
integrations,
config,
});
const mockContext = createMockActionContext({
input: {
repoUrl: 'hosted.bitbucket.com?project=project&repo=repo',
title: 'Add Scaffolder actions for Bitbucket Server',
description:
'I just made a Pull Request that Add Scaffolder actions for Bitbucket Server',
targetBranch: 'master',
sourceBranch: 'develop',
},
});
const responseOfBranches = {
size: 3,
limit: 25,
isLastPage: true,
values: [
{
id: 'refs/heads/master',
displayId: 'master',
type: 'BRANCH',
latestCommit: 'b1041e3f9b071b3d5cacd6826b7549cd624418f1',
latestChangeset: 'b1041e3f9b071b3d5cacd6826b7549cd624418f1',
isDefault: true,
},
{
id: 'refs/heads/my-feature-branch',
displayId: 'my-feature-branch',
type: 'BRANCH',
latestCommit: 'b1041e3f9b071b3d5cacd6826b7549cd624418f1',
latestChangeset: 'b1041e3f9b071b3d5cacd6826b7549cd624418f1',
isDefault: true,
},
{
id: 'refs/heads/develop',
displayId: 'develop',
type: 'BRANCH',
latestCommit: '98e21148205367aeb11c25a52eaca3c2945253fa',
latestChangeset: '98e21148205367aeb11c25a52eaca3c2945253fa',
isDefault: false,
},
{
id: 'refs/heads/development',
displayId: 'development',
type: 'BRANCH',
latestCommit: 'b1041e3f9b071b3d5cacd6826b7549cd624418f1',
latestChangeset: 'b1041e3f9b071b3d5cacd6826b7549cd624418f1',
isDefault: false,
},
],
start: 0,
};
const responseOfPullRequests = {
id: 19,
version: 0,
title: 'Test for bitbucket server pull-requests',
description: 'Test for bitbucket server pull-requests',
state: 'OPEN',
open: true,
closed: false,
createdDate: 1684200289521,
updatedDate: 1684200289521,
fromRef: {
id: 'refs/heads/develop',
displayId: 'develop',
latestCommit: '98e21148205367aeb11c25a52eaca3c2945253fa',
type: 'BRANCH',
repository: {
slug: 'repo',
id: 1812,
name: 'repo',
description: 'This is a test repo',
hierarchyId: '1da8822903a9b11a27b8',
scmId: 'git',
state: 'AVAILABLE',
statusMessage: 'Available',
forkable: true,
project: {},
public: false,
links: {},
},
},
toRef: {
id: 'refs/heads/master',
displayId: 'master',
latestCommit: 'b1041e3f9b071b3d5cacd6826b7549cd624418f1',
type: 'BRANCH',
repository: {
slug: 'repo',
id: 1812,
name: 'repo',
description: 'This is a test repo',
hierarchyId: '1da8822903a9b11a27b8',
scmId: 'git',
state: 'AVAILABLE',
statusMessage: 'Available',
forkable: true,
project: {},
public: false,
links: {},
},
},
locked: false,
author: {
user: {
name: 'test-user',
emailAddress: 'test-user@sample.com',
id: 2944,
displayName: 'test-user',
active: true,
slug: 'test-user',
type: 'NORMAL',
links: {},
},
role: 'AUTHOR',
approved: false,
status: 'UNAPPROVED',
},
reviewers: [],
participants: [],
links: {
self: [
{
href: 'https://hosted.bitbucket.com/projects/project/repos/repo/pull-requests/1',
},
],
},
};
const server = setupServer();
setupRequestMockHandlers(server);
beforeEach(() => {
jest.resetAllMocks();
});
it(`should ${examples[0].description}`, async () => {
expect.assertions(3);
server.use(
rest.get(
'https://hosted.bitbucket.com/rest/api/1.0/projects/project/repos/repo/branches',
(req, res, ctx) => {
expect(req.headers.get('Authorization')).toBe('Bearer thing');
return res(
ctx.status(200),
ctx.set('Content-Type', 'application/json'),
ctx.json(responseOfBranches),
);
},
),
rest.post(
'https://hosted.bitbucket.com/rest/api/1.0/projects/project/repos/repo/pull-requests',
(req, res, ctx) => {
expect(req.headers.get('Authorization')).toBe('Bearer thing');
return res(
ctx.status(201),
ctx.set('Content-Type', 'application/json'),
ctx.json(responseOfPullRequests),
);
},
),
);
await action.handler({
...mockContext,
input: {
...mockContext.input,
...yaml.parse(examples[0].example).steps[0].input,
},
});
});
it(`should ${examples[1].description}`, async () => {
expect.assertions(6);
server.use(
rest.get(
'https://hosted.bitbucket.com/rest/api/1.0/projects/project/repos/repo/branches',
(req, res, ctx) => {
expect(req.headers.get('Authorization')).toBe('Bearer thing');
return res(
ctx.status(200),
ctx.set('Content-Type', 'application/json'),
ctx.json(responseOfBranches),
);
},
),
rest.post(
'https://hosted.bitbucket.com/rest/api/1.0/projects/project/repos/repo/pull-requests',
(req, res, ctx) => {
const requestBody = req.body;
expect(requestBody.title).toBe('My pull request');
expect(requestBody.fromRef.displayId).toBe('my-feature-branch');
expect(requestBody.description).toBe(
'This is a detailed description of my pull request',
);
expect(req.headers.get('Authorization')).toBe('Bearer thing');
return res(
ctx.status(201),
ctx.set('Content-Type', 'application/json'),
ctx.json(responseOfPullRequests),
);
},
),
);
await action.handler({
...mockContext,
input: {
...mockContext.input,
...yaml.parse(examples[1].example).steps[0].input,
},
});
});
it(`should ${examples[2].description}`, async () => {
expect.assertions(6);
server.use(
rest.get(
'https://hosted.bitbucket.com/rest/api/1.0/projects/project/repos/repo/branches',
(req, res, ctx) => {
expect(req.headers.get('Authorization')).toBe('Bearer thing');
return res(
ctx.status(200),
ctx.set('Content-Type', 'application/json'),
ctx.json(responseOfBranches),
);
},
),
rest.post(
'https://hosted.bitbucket.com/rest/api/1.0/projects/project/repos/repo/pull-requests',
(req, res, ctx) => {
const requestBody = req.body;
expect(requestBody.title).toBe('My pull request');
expect(requestBody.toRef.displayId).toBe('development');
expect(requestBody.description).toBe(
'I just made a Pull Request that Add Scaffolder actions for Bitbucket Server',
);
expect(req.headers.get('Authorization')).toBe('Bearer thing');
return res(
ctx.status(201),
ctx.set('Content-Type', 'application/json'),
ctx.json(responseOfPullRequests),
);
},
),
);
await action.handler({
...mockContext,
input: {
...mockContext.input,
...yaml.parse(examples[2].example).steps[0].input,
},
});
});
it(`should ${examples[3].description}`, async () => {
expect.assertions(3);
server.use(
rest.get(
'https://no-credentials.bitbucket.com/rest/api/1.0/projects/project/repos/repo/branches',
(req, res, ctx) => {
expect(req.headers.get('Authorization')).toBe(
`Bearer ${yaml.parse(examples[3].example).steps[0].input.token}`,
);
return res(
ctx.status(200),
ctx.set('Content-Type', 'application/json'),
ctx.json(responseOfBranches),
);
},
),
rest.post(
'https://no-credentials.bitbucket.com/rest/api/1.0/projects/project/repos/repo/pull-requests',
(req, res, ctx) => {
expect(req.headers.get('Authorization')).toBe(
`Bearer ${yaml.parse(examples[3].example).steps[0].input.token}`,
);
return res(
ctx.status(201),
ctx.set('Content-Type', 'application/json'),
ctx.json(responseOfPullRequests),
);
},
),
);
await action.handler({
...mockContext,
input: {
...mockContext.input,
...yaml.parse(examples[3].example).steps[0].input,
},
});
});
it(`should ${examples[4].description}`, async () => {
expect.assertions(7);
server.use(
rest.get(
'https://no-credentials.bitbucket.com/rest/api/1.0/projects/project/repos/repo/branches',
(req, res, ctx) => {
expect(req.headers.get('Authorization')).toBe(
`Bearer ${yaml.parse(examples[4].example).steps[0].input.token}`,
);
return res(
ctx.status(200),
ctx.set('Content-Type', 'application/json'),
ctx.json(responseOfBranches),
);
},
),
rest.post(
'https://no-credentials.bitbucket.com/rest/api/1.0/projects/project/repos/repo/pull-requests',
(req, res, ctx) => {
const requestBody = req.body;
expect(requestBody.title).toBe('My pull request');
expect(requestBody.fromRef.displayId).toBe('my-feature-branch');
expect(requestBody.toRef.displayId).toBe('development');
expect(requestBody.description).toBe(
'This is a detailed description of my pull request',
);
expect(req.headers.get('Authorization')).toBe(
`Bearer ${yaml.parse(examples[4].example).steps[0].input.token}`,
);
return res(
ctx.status(201),
ctx.set('Content-Type', 'application/json'),
ctx.json(responseOfPullRequests),
);
},
),
);
await action.handler({
...mockContext,
input: {
...mockContext.input,
...yaml.parse(examples[4].example).steps[0].input,
},
});
});
});
@@ -0,0 +1,118 @@
/*
* Copyright 2023 The Backstage Authors
*
* 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.
*/
import { TemplateExample } from '@backstage/plugin-scaffolder-node';
import yaml from 'yaml';
export const examples: TemplateExample[] = [
{
description:
'Creating pull request on bitbucket server with required fields',
example: yaml.stringify({
steps: [
{
action: 'publish:bitbucketServer:pull-request',
id: 'publish-bitbucket-server-pull-request-minimal',
name: 'Creating pull request on bitbucket server',
input: {
repoUrl: 'hosted.bitbucket.com?project=project&repo=repo',
title: 'My pull request',
sourceBranch: 'my-feature-branch',
},
},
],
}),
},
{
description:
'Creating pull request on bitbucket server with custom descriptions',
example: yaml.stringify({
steps: [
{
action: 'publish:bitbucketServer:pull-request',
id: 'publish-bitbucket-server-pull-request-minimal',
name: 'Creating pull request on bitbucket server',
input: {
repoUrl: 'hosted.bitbucket.com?project=project&repo=repo',
title: 'My pull request',
sourceBranch: 'my-feature-branch',
description: 'This is a detailed description of my pull request',
},
},
],
}),
},
{
description:
'Creating pull request on bitbucket server with different target branch',
example: yaml.stringify({
steps: [
{
action: 'publish:bitbucketServer:pull-request',
id: 'publish-bitbucket-server-pull-request-target-branch',
name: 'Creating pull request on bitbucket server',
input: {
repoUrl: 'hosted.bitbucket.com?project=project&repo=repo',
title: 'My pull request',
sourceBranch: 'my-feature-branch',
targetBranch: 'development',
},
},
],
}),
},
{
description:
'Creating pull request on bitbucket server with authorization token',
example: yaml.stringify({
steps: [
{
action: 'publish:bitbucketServer:pull-request',
id: 'publish-bitbucket-server-pull-request-minimal',
name: 'Creating pull request on bitbucket server',
input: {
repoUrl: 'no-credentials.bitbucket.com?project=project&repo=repo',
title: 'My pull request',
sourceBranch: 'my-feature-branch',
token: 'my-auth-token',
},
},
],
}),
},
{
description: 'Creating pull request on bitbucket server with all fields',
example: yaml.stringify({
steps: [
{
action: 'publish:bitbucketServer:pull-request',
id: 'publish-bitbucket-server-pull-request-minimal',
name: 'Creating pull request on bitbucket server',
input: {
repoUrl: 'no-credentials.bitbucket.com?project=project&repo=repo',
title: 'My pull request',
sourceBranch: 'my-feature-branch',
targetBranch: 'development',
description: 'This is a detailed description of my pull request',
token: 'my-auth-token',
gitAuthorName: 'test-user',
gitAuthorEmail: 'test-user@sample.com',
},
},
],
}),
},
];
@@ -31,6 +31,7 @@ import {
import fetch, { RequestInit, Response } from 'node-fetch';
import { Config } from '@backstage/config';
import fs from 'fs-extra';
import { examples } from './bitbucketServerPullRequest.examples';
const createPullRequest = async (opts: {
project: string;
@@ -224,6 +225,7 @@ export function createPublishBitbucketServerPullRequestAction(options: {
gitAuthorEmail?: string;
}>({
id: 'publish:bitbucketServer:pull-request',
examples,
schema: {
input: {
type: 'object',