Adding test setup for import page and first form

Creating tests to check that correct action is proposed when user tries to add Github repos.
This commit is contained in:
Jussi Hallila
2021-01-13 14:21:50 +01:00
parent 19355928c0
commit 2b514d5323
6 changed files with 343 additions and 0 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-catalog-import': patch
---
Modifying import functionality to register existing catalog-info.yaml if one exists in given Github repository
@@ -0,0 +1,85 @@
/*
* Copyright 2021 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.
*/
import React from 'react';
import { renderInTestApp } from '@backstage/test-utils';
import { RegisterComponentForm } from './ImportComponentForm';
import {
ApiProvider,
ApiRegistry,
DiscoveryApi,
errorApiRef,
} from '@backstage/core';
import { catalogApiRef, CatalogClient } from '@backstage/plugin-catalog';
import { catalogImportApiRef, CatalogImportClient } from '../api';
import { fireEvent, waitFor, screen } from '@testing-library/react';
describe('<RegisterComponentForm />', () => {
let apis: ApiRegistry;
const mockErrorApi: jest.Mocked<typeof errorApiRef.T> = {
post: jest.fn(),
error$: jest.fn(),
};
beforeEach(() => {
apis = ApiRegistry.from([
[catalogApiRef, new CatalogClient({ discoveryApi: {} as DiscoveryApi })],
[
catalogImportApiRef,
new CatalogImportClient({
discoveryApi: { getBaseUrl: () => Promise.resolve('base') },
githubAuthApi: {
getAccessToken: (_, __) => Promise.resolve('token'),
},
configApi: {} as any,
}),
],
[errorApiRef, mockErrorApi],
]);
});
async function renderSUT(
nextStep: () => void = () => {},
saveConfig: () => void = () => {},
) {
return await renderInTestApp(
<ApiProvider apis={apis}>
<RegisterComponentForm nextStep={nextStep} saveConfig={saveConfig} />
</ApiProvider>,
);
}
it('Renders without exploding', async () => {
await renderSUT();
expect(
screen.getByPlaceholderText('https://github.com/backstage/backstage'),
).toBeInTheDocument();
});
it('Should have basic URL validation for input', async () => {
await renderSUT();
await waitFor(() => {
fireEvent.input(
screen.getByPlaceholderText('https://github.com/backstage/backstage'),
{ target: { value: 'not a url' } },
);
});
await waitFor(() => {
fireEvent.click(screen.getByText('Next'));
});
expect(screen.getByText('Must start with https://.')).toBeInTheDocument();
});
});
@@ -0,0 +1,189 @@
/*
* Copyright 2021 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.
*/
import React from 'react';
import { msw, renderInTestApp } from '@backstage/test-utils';
import { ImportComponentPage } from './ImportComponentPage';
import { ApiProvider, ApiRegistry, errorApiRef } from '@backstage/core';
import { catalogApiRef, CatalogClient } from '@backstage/plugin-catalog';
import { catalogImportApiRef, CatalogImportClient } from '../api';
import { fireEvent, screen, waitFor } from '@testing-library/react';
import { rest } from 'msw';
import { setupServer } from 'msw/node';
let codeSearchMockResponse: () => Promise<{
data: {
total_count: number;
items: Array<{ path: string }>;
};
}>;
jest.mock('@backstage/integration', () => ({
readGitHubIntegrationConfigs: () => ({
find: () => ({
host: 'test.localhost',
owner: 'someuser',
}),
}),
}));
jest.mock('@octokit/rest', () => ({
Octokit: jest.fn().mockImplementation(() => {
return {
repos: {
get: () =>
Promise.resolve({
data: {
default_branch: 'main',
},
}),
},
search: {
code: codeSearchMockResponse,
},
};
}),
}));
describe('<ImportComponentPage />', () => {
const server = setupServer();
msw.setupDefaultHandlers(server);
beforeEach(() => {
server.use(
rest.post('https://backend.localhost/locations', (_, res, ctx) => {
return res(
ctx.status(201),
ctx.json(require('../mocks/locations-POST-response.json')),
);
}),
rest.post('https://backend.localhost/analyze-location', (_, res, ctx) => {
return res(
ctx.json(require('../mocks/analyze-location-POST-response.json')),
);
}),
);
});
beforeAll(() => server.listen());
afterEach(() => server.resetHandlers());
afterAll(() => server.close());
let apis: ApiRegistry;
const mockErrorApi: jest.Mocked<typeof errorApiRef.T> = {
post: jest.fn(),
error$: jest.fn(),
};
beforeEach(() => {
const getBaseUrl = () => Promise.resolve('https://backend.localhost');
apis = ApiRegistry.from([
[
catalogApiRef,
new CatalogClient({
discoveryApi: { getBaseUrl },
}),
],
[
catalogImportApiRef,
new CatalogImportClient({
discoveryApi: { getBaseUrl },
githubAuthApi: {
getAccessToken: (_, __) => Promise.resolve('token'),
},
configApi: {} as any,
}),
],
[errorApiRef, mockErrorApi],
]);
});
async function renderSUT() {
return await renderInTestApp(
<ApiProvider apis={apis}>
<ImportComponentPage catalogRouteRef={{ path: 'path', title: 'ttl' }} />
</ApiProvider>,
);
}
it('Should use found yaml file directly and not create a pull request if GitHub api returns one', async () => {
codeSearchMockResponse = () =>
Promise.resolve({
data: {
total_count: 3,
items: [
{ path: 'simple/path/catalog-info.yaml' },
{ path: 'co/mple/x/path/catalog-info.yaml' },
{ path: 'catalog-info.yaml' },
],
},
});
await renderSUT();
await waitFor(() => {
fireEvent.input(
screen.getByPlaceholderText('https://github.com/backstage/backstage'),
{ target: { value: 'https://test.localhost/someuser/somerepo' } },
);
});
fireEvent.click(screen.getByText('Next'));
await waitFor(() => {
expect(
screen.getByText(
'https://test.localhost/someusername/somerepo/blob/master/src/catalog-info.yaml',
),
).toBeInTheDocument();
const pullReqText = screen.queryByText('pull request');
expect(pullReqText).not.toBeInTheDocument();
});
});
it('Should indicate a pull request creation when no yaml file found in the repo', async () => {
codeSearchMockResponse = () =>
Promise.resolve({
data: {
total_count: 0,
items: [],
},
});
const { container } = await renderSUT();
await waitFor(() => {
fireEvent.input(
screen.getByPlaceholderText('https://github.com/backstage/backstage'),
{ target: { value: 'https://test.localhost/someuser/somerepo' } },
);
});
fireEvent.click(screen.getByText('Next'));
await waitFor(() => {
expect(
screen.getByText('https://test.localhost/someuser/somerepo'),
).toBeInTheDocument();
});
const textNode = container
.querySelector('a[href="https://test.localhost/someuser/somerepo"]')
?.closest('p');
expect(textNode?.innerHTML).toContain(
'Following config object will be submitted in a pull request to the repository',
);
expect(
screen.queryByText(
'https://test.localhost/someusername/somerepo/blob/master/src/catalog-info.yaml',
),
).not.toBeInTheDocument();
});
});
@@ -0,0 +1,22 @@
{
"existingEntityFiles": [],
"generateEntities": [
{
"entity": {
"apiVersion": "backstage.io/v1alpha1",
"kind": "Component",
"metadata": {
"name": "somerepo",
"annotations": {
"github.com/project-slug": "someuser/somerepo"
}
},
"spec": {
"type": "other",
"lifecycle": "unknown"
}
},
"fields": []
}
]
}
@@ -0,0 +1,39 @@
{
"location": {
"id": "d4a64359-a709-4c91-a9de-0905a033bf22",
"type": "url",
"target": "https://test.localhost/someusername/somerepo/blob/master/src/catalog-info.yaml"
},
"entities": [
{
"metadata": {
"namespace": "default",
"annotations": {
"backstage.io/managed-by-location": "url:https://test.localhost/someusername/somerepo/blob/master/src/catalog-info.yaml",
"github.com/project-slug": "someusername/somerepo"
},
"name": "somerepo",
"uid": "e992d5ee-7c70-4316-90cf-325f1a0a5146",
"etag": "YWE2M2Q5MzgtNjdkNi00N2QwLWJkZjYtNDM0MTMzMDI4Y2I0",
"generation": 1
},
"apiVersion": "backstage.io/v1alpha1",
"kind": "Component",
"spec": {
"type": "other",
"lifecycle": "unknown",
"owner": "unknown"
},
"relations": [
{
"target": {
"kind": "group",
"namespace": "default",
"name": "unknown"
},
"type": "ownedBy"
}
]
}
]
}
+3
View File
@@ -15,3 +15,6 @@
*/
import '@testing-library/jest-dom';
import fetch from 'cross-fetch';
global.fetch = fetch;