Convert tests to use msw instead of mocking fetch
Signed-off-by: Robert Bunning <rbunning@webstaurantstore.com>
This commit is contained in:
@@ -49,6 +49,7 @@
|
||||
"react-router-dom": "6.0.0-beta.0 || ^6.3.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@backstage/backend-test-utils": "workspace:^",
|
||||
"@backstage/cli": "workspace:^",
|
||||
"@backstage/core-app-api": "workspace:^",
|
||||
"@backstage/dev-utils": "workspace:^",
|
||||
@@ -60,7 +61,7 @@
|
||||
"@types/node": "^16.11.26",
|
||||
"@types/react": "^16.13.1 || ^17.0.0",
|
||||
"cross-fetch": "^3.1.5",
|
||||
"msw": "^1.0.0"
|
||||
"msw": "^1.2.3"
|
||||
},
|
||||
"files": [
|
||||
"dist"
|
||||
|
||||
@@ -14,15 +14,24 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { NewRelicClient } from '.';
|
||||
import { FetchApi } from '@backstage/core-plugin-api';
|
||||
import { NewRelicApplication, NewRelicClient } from '.';
|
||||
import { DiscoveryApi } from '@backstage/core-plugin-api';
|
||||
import { rest } from 'msw';
|
||||
import { setupServer } from 'msw/node';
|
||||
import { MockFetchApi, setupRequestMockHandlers } from '@backstage/test-utils';
|
||||
|
||||
beforeEach(() => {
|
||||
jest.resetAllMocks();
|
||||
});
|
||||
|
||||
describe('NewRelicClient', () => {
|
||||
const server = setupServer();
|
||||
setupRequestMockHandlers(server);
|
||||
|
||||
beforeEach(() => {
|
||||
server.resetHandlers();
|
||||
});
|
||||
|
||||
test.each([
|
||||
['https://test.test/BASEPATH/apm/api/applications.json', '/BASEPATH'],
|
||||
['https://test.test/BASEPATH2/apm/api/applications.json', '/BASEPATH2'],
|
||||
@@ -31,17 +40,18 @@ describe('NewRelicClient', () => {
|
||||
])(
|
||||
'It correctly forms the request url (%p) when proxyPathBase is %p',
|
||||
async (expectedUrl, basePathOverride) => {
|
||||
server.use(
|
||||
rest.get(expectedUrl, (_, res, ctx) =>
|
||||
res(ctx.status(200), ctx.json({ applications: [] })),
|
||||
),
|
||||
);
|
||||
|
||||
const mockedDiscoveryApi: DiscoveryApi = {
|
||||
getBaseUrl: jest.fn().mockResolvedValueOnce('https://test.test'),
|
||||
};
|
||||
|
||||
const mockedFetchApi: FetchApi = {
|
||||
fetch: jest.fn().mockResolvedValueOnce({
|
||||
ok: true,
|
||||
json: async () => [],
|
||||
headers: new Map<string, string | null>(),
|
||||
}),
|
||||
};
|
||||
const mockedFetchApi = new MockFetchApi();
|
||||
const fetchSpy = jest.spyOn(mockedFetchApi, 'fetch');
|
||||
|
||||
const client = new NewRelicClient({
|
||||
discoveryApi: mockedDiscoveryApi,
|
||||
@@ -50,7 +60,7 @@ describe('NewRelicClient', () => {
|
||||
});
|
||||
await client.getApplications();
|
||||
|
||||
expect(mockedFetchApi.fetch).toHaveBeenCalledWith(expectedUrl);
|
||||
expect(fetchSpy).toHaveBeenCalledWith(expectedUrl);
|
||||
},
|
||||
);
|
||||
|
||||
@@ -59,7 +69,7 @@ describe('NewRelicClient', () => {
|
||||
getBaseUrl: jest.fn().mockResolvedValueOnce('https://test.test'),
|
||||
};
|
||||
|
||||
const mockedApplicationOne = {
|
||||
const mockedApplicationOne: NewRelicApplication = {
|
||||
id: 1,
|
||||
application_summary: {
|
||||
apdex_score: 0,
|
||||
@@ -81,8 +91,16 @@ describe('NewRelicClient', () => {
|
||||
},
|
||||
};
|
||||
|
||||
const mockedApplicationTwo = {
|
||||
const mockedApplicationTwo: NewRelicApplication = {
|
||||
id: 2,
|
||||
application_summary: {
|
||||
apdex_score: -900,
|
||||
error_rate: 0,
|
||||
host_count: 0,
|
||||
instance_count: 0,
|
||||
response_time: 0,
|
||||
throughput: 0,
|
||||
},
|
||||
name: 'Testing Application #2',
|
||||
language: 'en-us',
|
||||
health_status: 'Working',
|
||||
@@ -95,7 +113,7 @@ describe('NewRelicClient', () => {
|
||||
},
|
||||
};
|
||||
|
||||
const mockedApplicationThree = {
|
||||
const mockedApplicationThree: NewRelicApplication = {
|
||||
id: 3,
|
||||
application_summary: {
|
||||
apdex_score: -900,
|
||||
@@ -117,45 +135,65 @@ describe('NewRelicClient', () => {
|
||||
},
|
||||
};
|
||||
|
||||
const mockedFetchApi: FetchApi = {
|
||||
fetch: jest
|
||||
.fn()
|
||||
.mockResolvedValueOnce({
|
||||
ok: true,
|
||||
json: async () => ({ applications: [mockedApplicationOne] }),
|
||||
headers: new Map<string, string | null>([
|
||||
[
|
||||
'link',
|
||||
'<https://next.page/page2?page=2>; rel="next", <https://badsite.dontgohere>; rel="first"',
|
||||
],
|
||||
['otherheader', 'otherValue'],
|
||||
]),
|
||||
})
|
||||
.mockResolvedValueOnce({
|
||||
ok: true,
|
||||
json: async () => ({ applications: [] }),
|
||||
headers: new Map<string, string | null>([
|
||||
['link', '<https://next.page/page3?page=3>; rel="next",'],
|
||||
]),
|
||||
})
|
||||
.mockResolvedValueOnce({
|
||||
ok: true,
|
||||
json: async () => ({
|
||||
applications: [mockedApplicationTwo, mockedApplicationThree],
|
||||
}),
|
||||
headers: new Map<string, string | null>([
|
||||
[
|
||||
'link',
|
||||
'<https://first.page/page1>; rel="first", <https://next.page/page2>; rel="next"',
|
||||
],
|
||||
]),
|
||||
}),
|
||||
};
|
||||
const queryToRequestData = new Map<
|
||||
string | null,
|
||||
{ link?: string | string[]; apps: NewRelicApplication[] }
|
||||
>([
|
||||
[
|
||||
null,
|
||||
{
|
||||
link: [
|
||||
'<https://next.page/page2?page=2>; rel="next"',
|
||||
'<https://badsite.dontgohere>; rel="bad"',
|
||||
],
|
||||
apps: [mockedApplicationOne],
|
||||
},
|
||||
],
|
||||
[
|
||||
'2',
|
||||
{
|
||||
link: '<https://next.page/page3?page=3>; rel="next",',
|
||||
apps: [],
|
||||
},
|
||||
],
|
||||
[
|
||||
'3',
|
||||
{
|
||||
apps: [mockedApplicationTwo, mockedApplicationThree],
|
||||
},
|
||||
],
|
||||
]);
|
||||
|
||||
const mockedFetchApi = new MockFetchApi();
|
||||
const fetchSpy = jest.spyOn(mockedFetchApi, 'fetch');
|
||||
|
||||
server.use(
|
||||
rest.get(
|
||||
'https://test.test/newrelic/apm/api/applications.json',
|
||||
(req, res, ctx) => {
|
||||
const nextPageNumber = req.url.searchParams.get('page');
|
||||
const requestData = queryToRequestData.get(nextPageNumber) ?? {
|
||||
apps: [],
|
||||
};
|
||||
|
||||
const { link, apps: applications } = requestData;
|
||||
const statusTransform = ctx.status(200);
|
||||
const responseBody = ctx.json({ applications });
|
||||
|
||||
if (!!link) {
|
||||
return res(statusTransform, ctx.set({ link }), responseBody);
|
||||
}
|
||||
|
||||
return res(statusTransform, responseBody);
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
const client = new NewRelicClient({
|
||||
discoveryApi: mockedDiscoveryApi,
|
||||
fetchApi: mockedFetchApi,
|
||||
});
|
||||
|
||||
const actual = await client.getApplications();
|
||||
const expected = {
|
||||
applications: [
|
||||
@@ -165,14 +203,14 @@ describe('NewRelicClient', () => {
|
||||
],
|
||||
};
|
||||
|
||||
expect(mockedFetchApi.fetch).toHaveBeenCalledTimes(3);
|
||||
expect(mockedFetchApi.fetch).toHaveBeenCalledWith(
|
||||
expect(fetchSpy).toHaveBeenCalledTimes(3);
|
||||
expect(fetchSpy).toHaveBeenCalledWith(
|
||||
'https://test.test/newrelic/apm/api/applications.json',
|
||||
);
|
||||
expect(mockedFetchApi.fetch).toHaveBeenCalledWith(
|
||||
expect(fetchSpy).toHaveBeenCalledWith(
|
||||
'https://test.test/newrelic/apm/api/applications.json?page=2',
|
||||
);
|
||||
expect(mockedFetchApi.fetch).toHaveBeenCalledWith(
|
||||
expect(fetchSpy).toHaveBeenCalledWith(
|
||||
'https://test.test/newrelic/apm/api/applications.json?page=3',
|
||||
);
|
||||
expect(actual).toStrictEqual(expected);
|
||||
@@ -185,19 +223,28 @@ describe('NewRelicClient', () => {
|
||||
getBaseUrl: jest.fn().mockResolvedValueOnce('https://test.test'),
|
||||
};
|
||||
|
||||
const mockedFetchApi: FetchApi = {
|
||||
fetch: jest.fn().mockResolvedValueOnce({
|
||||
ok: true,
|
||||
json: async () => ({ applications: [] }),
|
||||
headers: new Map<string, string | null>([
|
||||
[
|
||||
linkHeaderName,
|
||||
'<https://next.page/page2>; rel="next", <https://badsite.dontgohere>; rel="next"',
|
||||
],
|
||||
['otherheader', 'otherValue'],
|
||||
]),
|
||||
const mockedFetchApi = new MockFetchApi();
|
||||
const fetchSpy = jest.spyOn(mockedFetchApi, 'fetch');
|
||||
|
||||
server.use(
|
||||
rest.get(
|
||||
'https://test.test/newrelic/apm/api/applications.json',
|
||||
(_, res, ctx) =>
|
||||
res(
|
||||
ctx.status(200),
|
||||
ctx.set(
|
||||
linkHeaderName,
|
||||
'<https://test.test/badroute>; rel="next"',
|
||||
),
|
||||
ctx.json({ applications: [] }),
|
||||
),
|
||||
),
|
||||
rest.get('https://test.test/badroute', () => {
|
||||
throw new Error(
|
||||
'NewRelicClient attempted to paginate when it should not have',
|
||||
);
|
||||
}),
|
||||
};
|
||||
);
|
||||
|
||||
const client = new NewRelicClient({
|
||||
discoveryApi: mockedDiscoveryApi,
|
||||
@@ -205,8 +252,8 @@ describe('NewRelicClient', () => {
|
||||
});
|
||||
await client.getApplications();
|
||||
|
||||
expect(mockedFetchApi.fetch).toHaveBeenCalledTimes(1);
|
||||
expect(mockedFetchApi.fetch).toHaveBeenCalledWith(
|
||||
expect(fetchSpy).toHaveBeenCalledTimes(1);
|
||||
expect(fetchSpy).toHaveBeenCalledWith(
|
||||
'https://test.test/newrelic/apm/api/applications.json',
|
||||
);
|
||||
},
|
||||
@@ -228,16 +275,25 @@ describe('NewRelicClient', () => {
|
||||
getBaseUrl: jest.fn().mockResolvedValueOnce('https://test.test'),
|
||||
};
|
||||
|
||||
const mockedFetchApi: FetchApi = {
|
||||
fetch: jest.fn().mockResolvedValueOnce({
|
||||
ok: true,
|
||||
json: async () => ({ applications: [] }),
|
||||
headers: new Map<string, string | null>([
|
||||
['Link', linkHeaderValue],
|
||||
['otherheader', 'otherValue'],
|
||||
]),
|
||||
const mockedFetchApi = new MockFetchApi();
|
||||
const fetchSpy = jest.spyOn(mockedFetchApi, 'fetch');
|
||||
|
||||
server.use(
|
||||
rest.get(
|
||||
'https://test.test/newrelic/apm/api/applications.json',
|
||||
(_, res, ctx) =>
|
||||
res(
|
||||
ctx.status(200),
|
||||
ctx.set('link', linkHeaderValue),
|
||||
ctx.json({ applications: [] }),
|
||||
),
|
||||
),
|
||||
rest.get('https://test.test/badroute', () => {
|
||||
throw new Error(
|
||||
'NewRelicClient attempted to paginate when it should not have',
|
||||
);
|
||||
}),
|
||||
};
|
||||
);
|
||||
|
||||
const client = new NewRelicClient({
|
||||
discoveryApi: mockedDiscoveryApi,
|
||||
@@ -245,45 +301,33 @@ describe('NewRelicClient', () => {
|
||||
});
|
||||
await client.getApplications();
|
||||
|
||||
expect(mockedFetchApi.fetch).toHaveBeenCalledTimes(1);
|
||||
expect(mockedFetchApi.fetch).toHaveBeenCalledWith(
|
||||
expect(fetchSpy).toHaveBeenCalledTimes(1);
|
||||
expect(fetchSpy).toHaveBeenCalledWith(
|
||||
'https://test.test/newrelic/apm/api/applications.json',
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
test.each([
|
||||
[
|
||||
{
|
||||
ok: false,
|
||||
statusText: 'statusText',
|
||||
json: async () => ({ error: { title: 'TESTING' } }),
|
||||
},
|
||||
],
|
||||
[
|
||||
{
|
||||
ok: false,
|
||||
statusText: 'statusText',
|
||||
json: async () => ({}),
|
||||
},
|
||||
],
|
||||
[404, { error: { title: 'TESTING' } }],
|
||||
[500, {}],
|
||||
])(
|
||||
'It returns an empty array of applications when the fetch is not okay',
|
||||
async fetchResult => {
|
||||
async (statusCode, jsonBody) => {
|
||||
const mockedDiscoveryApi: DiscoveryApi = {
|
||||
getBaseUrl: jest.fn().mockResolvedValueOnce('https://test.test'),
|
||||
};
|
||||
|
||||
const mockedFetchApi: FetchApi = {
|
||||
fetch: jest.fn().mockResolvedValueOnce({
|
||||
ok: true,
|
||||
json: async () => fetchResult,
|
||||
}),
|
||||
};
|
||||
server.use(
|
||||
rest.get(
|
||||
'https://test.test/newrelic/apm/api/applications.json',
|
||||
(_, res, ctx) => res(ctx.status(statusCode), ctx.json(jsonBody)),
|
||||
),
|
||||
);
|
||||
|
||||
const client = new NewRelicClient({
|
||||
discoveryApi: mockedDiscoveryApi,
|
||||
fetchApi: mockedFetchApi,
|
||||
fetchApi: new MockFetchApi(),
|
||||
});
|
||||
const actual = await client.getApplications();
|
||||
|
||||
@@ -296,15 +340,15 @@ describe('NewRelicClient', () => {
|
||||
getBaseUrl: jest.fn().mockResolvedValueOnce('https://test.test'),
|
||||
};
|
||||
|
||||
const mockedFetchApi: FetchApi = {
|
||||
fetch: () => {
|
||||
throw new Error('TESTING');
|
||||
},
|
||||
};
|
||||
server.use(
|
||||
rest.get('https://test.test/newrelic/apm/api/applications.json', () => {
|
||||
throw new Error('Network Error');
|
||||
}),
|
||||
);
|
||||
|
||||
const client = new NewRelicClient({
|
||||
discoveryApi: mockedDiscoveryApi,
|
||||
fetchApi: mockedFetchApi,
|
||||
fetchApi: new MockFetchApi(),
|
||||
});
|
||||
const actual = await client.getApplications();
|
||||
|
||||
@@ -316,16 +360,16 @@ describe('NewRelicClient', () => {
|
||||
getBaseUrl: jest.fn().mockResolvedValueOnce('https://test.test'),
|
||||
};
|
||||
|
||||
const mockedFetchApi: FetchApi = {
|
||||
fetch: jest.fn().mockResolvedValue({
|
||||
ok: true,
|
||||
json: async () => ({ applications: [] }),
|
||||
}),
|
||||
};
|
||||
server.use(
|
||||
rest.get(
|
||||
'https://test.test/newrelic/apm/api/applications.json',
|
||||
(_, res, ctx) => res(ctx.status(200), ctx.json({ applications: [] })),
|
||||
),
|
||||
);
|
||||
|
||||
const client = new NewRelicClient({
|
||||
discoveryApi: mockedDiscoveryApi,
|
||||
fetchApi: mockedFetchApi,
|
||||
fetchApi: new MockFetchApi(),
|
||||
});
|
||||
|
||||
await client.getApplications();
|
||||
|
||||
@@ -7590,6 +7590,7 @@ __metadata:
|
||||
version: 0.0.0-use.local
|
||||
resolution: "@backstage/plugin-newrelic@workspace:plugins/newrelic"
|
||||
dependencies:
|
||||
"@backstage/backend-test-utils": "workspace:^"
|
||||
"@backstage/cli": "workspace:^"
|
||||
"@backstage/core-app-api": "workspace:^"
|
||||
"@backstage/core-components": "workspace:^"
|
||||
@@ -7608,7 +7609,7 @@ __metadata:
|
||||
"@types/parse-link-header": ^2.0.1
|
||||
"@types/react": ^16.13.1 || ^17.0.0
|
||||
cross-fetch: ^3.1.5
|
||||
msw: ^1.0.0
|
||||
msw: ^1.2.3
|
||||
parse-link-header: ^2.0.0
|
||||
react-use: ^17.2.4
|
||||
peerDependencies:
|
||||
@@ -32846,9 +32847,9 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"msw@npm:^1.0.0, msw@npm:^1.0.1, msw@npm:^1.2.1":
|
||||
version: 1.2.2
|
||||
resolution: "msw@npm:1.2.2"
|
||||
"msw@npm:^1.0.0, msw@npm:^1.0.1, msw@npm:^1.2.1, msw@npm:^1.2.3":
|
||||
version: 1.2.3
|
||||
resolution: "msw@npm:1.2.3"
|
||||
dependencies:
|
||||
"@mswjs/cookies": ^0.2.2
|
||||
"@mswjs/interceptors": ^0.17.5
|
||||
@@ -32876,7 +32877,7 @@ __metadata:
|
||||
optional: true
|
||||
bin:
|
||||
msw: cli/index.js
|
||||
checksum: e42cec8f5523663020bdecf6a7977a10aa86a4718d1920def3fbde0ff3734391873668cc6e3996d6790add3c74dac95a952f8560ce2543697280125eb55138e8
|
||||
checksum: 832a6fc3973726a97e03ce2690c3b6e1774b5156d064a478657a1b33f9933e4834af833cc8a859e1b717fa9b71f1271b3e66a1ec6eed7f76bfe79406e9ec3986
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
|
||||
Reference in New Issue
Block a user