Merge pull request #31933 from backstage/upgrade-jsdom
chore: upgrade jsdom to v27 and Jest to v30
This commit is contained in:
+1
-1
@@ -1,4 +1,4 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
|
||||
|
||||
exports[`GkeEntityProvider should return clusters as Resources 1`] = `
|
||||
[MockFunction] {
|
||||
|
||||
@@ -1577,10 +1577,11 @@ describe('DefaultEntitiesCatalog', () => {
|
||||
totalItems: 0,
|
||||
items: {
|
||||
type: 'raw',
|
||||
entities: expect.objectContaining({ length: 10 }),
|
||||
entities: expect.any(Array),
|
||||
},
|
||||
pageInfo: { nextCursor: expect.anything() },
|
||||
});
|
||||
expect(response.items.entities).toHaveLength(10);
|
||||
response = await catalog.queryEntities({
|
||||
...request,
|
||||
cursor: response.pageInfo.nextCursor!,
|
||||
@@ -1589,10 +1590,11 @@ describe('DefaultEntitiesCatalog', () => {
|
||||
totalItems: 0,
|
||||
items: {
|
||||
type: 'raw',
|
||||
entities: expect.objectContaining({ length: 5 }),
|
||||
entities: expect.any(Array),
|
||||
},
|
||||
pageInfo: { prevCursor: expect.anything() },
|
||||
});
|
||||
expect(response.items.entities).toHaveLength(5);
|
||||
},
|
||||
);
|
||||
|
||||
|
||||
@@ -327,9 +327,10 @@ describe('writeEntitiesResponse', () => {
|
||||
expect(res.header['content-length']).not.toBeDefined();
|
||||
expect(res.body).toEqual({
|
||||
page: 1,
|
||||
items: expect.objectContaining({ length: 300 }),
|
||||
items: expect.any(Array),
|
||||
totalItems: 1337,
|
||||
});
|
||||
expect(res.body.items).toHaveLength(300);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -438,9 +439,10 @@ describe('writeEntitiesResponse', () => {
|
||||
expect(res.header['content-length']).toBeDefined();
|
||||
expect(res.body).toEqual({
|
||||
page: 1,
|
||||
items: expect.objectContaining({ length: 300 }),
|
||||
items: expect.any(Array),
|
||||
totalItems: 1337,
|
||||
});
|
||||
expect(res.body.items).toHaveLength(300);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -68,15 +68,15 @@ describe('useAllEntitiesCount', () => {
|
||||
),
|
||||
});
|
||||
|
||||
await waitFor(() =>
|
||||
await waitFor(() => {
|
||||
expect(mockCatalogApi.queryEntities).toHaveBeenCalledWith({
|
||||
filter: {
|
||||
'relations.ownedBy': ['user:default/owner'],
|
||||
},
|
||||
limit: 0,
|
||||
}),
|
||||
);
|
||||
expect(result.current).toEqual({ count: 10, loading: false });
|
||||
});
|
||||
expect(result.current).toEqual({ count: 10, loading: false });
|
||||
});
|
||||
});
|
||||
|
||||
it(`shouldn't invoke the endpoint at startup, when filters are missing`, async () => {
|
||||
|
||||
@@ -721,18 +721,27 @@ describe('Entity page', () => {
|
||||
);
|
||||
|
||||
const { disabled } = params.useProps();
|
||||
await waitFor(async () => {
|
||||
await userEvent.click(screen.getByTestId('menu-button'));
|
||||
expect(screen.getByText('Test Title')).toBeInTheDocument();
|
||||
expect(screen.getByText('Test Icon')).toBeInTheDocument();
|
||||
const listItem = screen.getByText('Test Title').closest('li');
|
||||
expect(listItem).toHaveAttribute('aria-disabled', disabled.toString());
|
||||
if (!disabled) {
|
||||
await userEvent.click(screen.getByText('Test Title'));
|
||||
}
|
||||
|
||||
expect(onClickMock).toHaveBeenCalledTimes(disabled ? 0 : 1);
|
||||
});
|
||||
// Wait for entity to load first
|
||||
await waitFor(() =>
|
||||
expect(screen.getByText(/artist-lookup/)).toBeInTheDocument(),
|
||||
);
|
||||
|
||||
await userEvent.click(screen.getByTestId('menu-button'));
|
||||
|
||||
// Wait for menu to open
|
||||
await waitFor(() =>
|
||||
expect(screen.getByText('Test Title')).toBeInTheDocument(),
|
||||
);
|
||||
|
||||
expect(screen.getByText('Test Icon')).toBeInTheDocument();
|
||||
const listItem = screen.getByText('Test Title').closest('li');
|
||||
expect(listItem).toHaveAttribute('aria-disabled', disabled.toString());
|
||||
if (!disabled) {
|
||||
await userEvent.click(screen.getByText('Test Title'));
|
||||
}
|
||||
|
||||
expect(onClickMock).toHaveBeenCalledTimes(disabled ? 0 : 1);
|
||||
});
|
||||
|
||||
it.each([
|
||||
|
||||
@@ -65,7 +65,7 @@
|
||||
"devDependencies": {
|
||||
"@backstage/backend-test-utils": "workspace:^",
|
||||
"@backstage/cli": "workspace:^",
|
||||
"msw": "^1.0.0"
|
||||
"msw": "^2.0.0"
|
||||
},
|
||||
"configSchema": "config.d.ts"
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
import { DefaultEventsService } from './DefaultEventsService';
|
||||
import { EventParams } from './EventParams';
|
||||
import { EVENTS_NOTIFY_TIMEOUT_HEADER } from './EventsService';
|
||||
import { rest } from 'msw';
|
||||
import { http, HttpResponse } from 'msw';
|
||||
import { setupServer } from 'msw/node';
|
||||
import {
|
||||
mockServices,
|
||||
@@ -129,18 +129,18 @@ describe('DefaultEventsService', () => {
|
||||
});
|
||||
|
||||
mswServer.use(
|
||||
rest.put(
|
||||
http.put(
|
||||
'http://localhost:0/api/events/bus/v1/subscriptions/a.tester',
|
||||
(_req, res, ctx) => res(ctx.status(200)),
|
||||
() => new HttpResponse(null, { status: 200 }),
|
||||
),
|
||||
rest.get(
|
||||
http.get(
|
||||
'http://localhost:0/api/events/bus/v1/subscriptions/a.tester/events',
|
||||
(_req, res, ctx) =>
|
||||
res(
|
||||
ctx.status(200),
|
||||
ctx.json({
|
||||
() =>
|
||||
HttpResponse.json(
|
||||
{
|
||||
events: [{ topic: 'test', payload: { foo: 'bar' } }],
|
||||
}),
|
||||
},
|
||||
{ status: 200 },
|
||||
),
|
||||
),
|
||||
);
|
||||
@@ -180,38 +180,36 @@ describe('DefaultEventsService', () => {
|
||||
});
|
||||
|
||||
mswServer.use(
|
||||
rest.put(
|
||||
http.put(
|
||||
'http://localhost:0/api/events/bus/v1/subscriptions/a.tester',
|
||||
(_req, res, ctx) => res(ctx.status(200)),
|
||||
() => new HttpResponse(null, { status: 200 }),
|
||||
),
|
||||
// The first and third calls result in a blocking 202 that is resolved after 100ms
|
||||
// The second and fourth calls result in a 200 with an event
|
||||
// The fifth call blocks until the end of the test
|
||||
// No more than 5 calls should be made
|
||||
rest.get(
|
||||
http.get(
|
||||
'http://localhost:0/api/events/bus/v1/subscriptions/a.tester/events',
|
||||
(_req, res, ctx) => {
|
||||
() => {
|
||||
callCount += 1;
|
||||
if (callCount === 1 || callCount === 3) {
|
||||
return res(
|
||||
ctx.status(202),
|
||||
ctx.body(
|
||||
new ReadableStream({
|
||||
start(controller) {
|
||||
setTimeout(() => controller.close(), 100);
|
||||
},
|
||||
}),
|
||||
),
|
||||
return new HttpResponse(
|
||||
new ReadableStream({
|
||||
start(controller) {
|
||||
setTimeout(() => controller.close(), 100);
|
||||
},
|
||||
}),
|
||||
{ status: 202 },
|
||||
);
|
||||
} else if (callCount === 2 || callCount === 4) {
|
||||
return res(
|
||||
ctx.status(200),
|
||||
ctx.json({
|
||||
return HttpResponse.json(
|
||||
{
|
||||
events: [{ topic: 'test', payload: { callCount } }],
|
||||
}),
|
||||
},
|
||||
{ status: 200 },
|
||||
);
|
||||
} else if (callCount === 5) {
|
||||
return res(ctx.status(202), ctx.body(blockingStream));
|
||||
return new HttpResponse(blockingStream, { status: 202 });
|
||||
}
|
||||
throw new Error(`events endpoint called too many times`);
|
||||
},
|
||||
@@ -268,45 +266,42 @@ describe('DefaultEventsService', () => {
|
||||
});
|
||||
|
||||
mswServer.use(
|
||||
rest.put(
|
||||
http.put(
|
||||
'http://localhost:0/api/events/bus/v1/subscriptions/a.tester',
|
||||
(_req, res, ctx) => res(ctx.status(200)),
|
||||
() => new HttpResponse(null, { status: 200 }),
|
||||
),
|
||||
// The first and third calls result in a blocking 202 that is resolved after 100ms
|
||||
// The second and fourth calls result in a 200 with an event
|
||||
// The fifth call blocks until the end of the test
|
||||
// No more than 5 calls should be made
|
||||
rest.get(
|
||||
http.get(
|
||||
'http://localhost:0/api/events/bus/v1/subscriptions/a.tester/events',
|
||||
(_req, res, ctx) => {
|
||||
() => {
|
||||
callCount += 1;
|
||||
if (callCount === 1 || callCount === 3) {
|
||||
return res(
|
||||
ctx.status(202),
|
||||
ctx.body(
|
||||
new ReadableStream({
|
||||
start(controller) {
|
||||
setTimeout(() => controller.close(), 100);
|
||||
},
|
||||
}),
|
||||
),
|
||||
return new HttpResponse(
|
||||
new ReadableStream({
|
||||
start(controller) {
|
||||
setTimeout(() => controller.close(), 100);
|
||||
},
|
||||
}),
|
||||
{ status: 202 },
|
||||
);
|
||||
} else if (callCount === 2 || callCount === 4) {
|
||||
return res(
|
||||
ctx.status(200),
|
||||
ctx.json({
|
||||
return HttpResponse.json(
|
||||
{
|
||||
events: [{ topic: 'test', payload: { callCount } }],
|
||||
}),
|
||||
},
|
||||
{ status: 200 },
|
||||
);
|
||||
} else if (callCount === 5) {
|
||||
// 5th call has a timeout header so polling should proceed to the next call
|
||||
return res(
|
||||
ctx.set(EVENTS_NOTIFY_TIMEOUT_HEADER, '100'),
|
||||
ctx.status(202),
|
||||
ctx.body(blockingStream),
|
||||
);
|
||||
return new HttpResponse(blockingStream, {
|
||||
status: 202,
|
||||
headers: { [EVENTS_NOTIFY_TIMEOUT_HEADER]: '100' },
|
||||
});
|
||||
} else if (callCount === 6) {
|
||||
return res(ctx.status(202), ctx.body(blockingStream));
|
||||
return new HttpResponse(blockingStream, { status: 202 });
|
||||
}
|
||||
throw new Error(`events endpoint called too many times`);
|
||||
},
|
||||
@@ -358,11 +353,11 @@ describe('DefaultEventsService', () => {
|
||||
|
||||
let calledApi = false;
|
||||
mswServer.use(
|
||||
rest.put(
|
||||
http.put(
|
||||
'http://localhost:0/api/events/bus/v1/subscriptions/a.tester',
|
||||
(_req, res, ctx) => {
|
||||
() => {
|
||||
calledApi = true;
|
||||
res(ctx.status(200));
|
||||
return new HttpResponse(null, { status: 200 });
|
||||
},
|
||||
),
|
||||
);
|
||||
@@ -393,9 +388,9 @@ describe('DefaultEventsService', () => {
|
||||
});
|
||||
|
||||
mswServer.use(
|
||||
rest.put(
|
||||
http.put(
|
||||
'http://localhost:0/api/events/bus/v1/subscriptions/a.tester',
|
||||
(_req, res, ctx) => res(ctx.status(404)),
|
||||
() => new HttpResponse(null, { status: 404 }),
|
||||
),
|
||||
);
|
||||
|
||||
@@ -432,9 +427,9 @@ describe('DefaultEventsService', () => {
|
||||
});
|
||||
|
||||
mswServer.use(
|
||||
rest.put(
|
||||
http.put(
|
||||
'http://localhost:0/api/events/bus/v1/subscriptions/a.tester',
|
||||
(_req, res, ctx) => res(ctx.status(404)),
|
||||
() => new HttpResponse(null, { status: 404 }),
|
||||
),
|
||||
);
|
||||
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
|
||||
|
||||
exports[`CatalogClusterLocator returns the aws cluster details provided by annotations 1`] = `
|
||||
{
|
||||
|
||||
@@ -84,7 +84,7 @@
|
||||
"@testing-library/react": "^16.0.0",
|
||||
"@types/react": "^18.0.0",
|
||||
"jest-websocket-mock": "^2.5.0",
|
||||
"msw": "^1.3.1",
|
||||
"msw": "^2.0.0",
|
||||
"react": "^18.0.2",
|
||||
"react-dom": "^18.0.2",
|
||||
"react-router-dom": "^6.3.0"
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
import { KubernetesAuthProvidersApi } from '../kubernetes-auth-provider';
|
||||
import { KubernetesBackendClient } from './KubernetesBackendClient';
|
||||
import { rest } from 'msw';
|
||||
import { http, HttpResponse } from 'msw';
|
||||
import { UrlPatternDiscovery } from '@backstage/core-app-api';
|
||||
import { setupServer } from 'msw/node';
|
||||
import { MockFetchApi, registerMswTestHooks } from '@backstage/test-utils';
|
||||
@@ -89,23 +89,24 @@ describe('KubernetesBackendClient', () => {
|
||||
it('hits the /clusters API', async () => {
|
||||
identityApi.getCredentials.mockResolvedValue({ token: 'idToken' });
|
||||
worker.use(
|
||||
rest.get('http://localhost:1234/api/kubernetes/clusters', (_, res, ctx) =>
|
||||
res(ctx.json({ items: [{ name: 'cluster-a', authProvider: 'aws' }] })),
|
||||
http.get('http://localhost:1234/api/kubernetes/clusters', () =>
|
||||
HttpResponse.json({
|
||||
items: [{ name: 'cluster-a', authProvider: 'aws' }],
|
||||
}),
|
||||
),
|
||||
);
|
||||
|
||||
const clusters = await backendClient.getClusters();
|
||||
|
||||
expect(clusters).toStrictEqual([
|
||||
{ name: 'cluster-a', authProvider: 'aws' },
|
||||
]);
|
||||
expect(clusters).toEqual([{ name: 'cluster-a', authProvider: 'aws' }]);
|
||||
});
|
||||
|
||||
it('/clusters API throws a 404 Error', async () => {
|
||||
identityApi.getCredentials.mockResolvedValue({ token: 'idToken' });
|
||||
worker.use(
|
||||
rest.get('http://localhost:1234/api/kubernetes/clusters', (_, res, ctx) =>
|
||||
res(ctx.status(404)),
|
||||
http.get(
|
||||
'http://localhost:1234/api/kubernetes/clusters',
|
||||
() => new HttpResponse(null, { status: 404 }),
|
||||
),
|
||||
);
|
||||
|
||||
@@ -117,8 +118,9 @@ describe('KubernetesBackendClient', () => {
|
||||
it('/clusters API throws a 500 Error', async () => {
|
||||
identityApi.getCredentials.mockResolvedValue({ token: 'idToken' });
|
||||
worker.use(
|
||||
rest.get('http://localhost:1234/api/kubernetes/clusters', (_, res, ctx) =>
|
||||
res(ctx.status(500)),
|
||||
http.get(
|
||||
'http://localhost:1234/api/kubernetes/clusters',
|
||||
() => new HttpResponse(null, { status: 500 }),
|
||||
),
|
||||
);
|
||||
|
||||
@@ -130,9 +132,9 @@ describe('KubernetesBackendClient', () => {
|
||||
it('hits the /resources/custom/query API', async () => {
|
||||
identityApi.getCredentials.mockResolvedValue({ token: 'idToken' });
|
||||
worker.use(
|
||||
rest.post(
|
||||
http.post(
|
||||
'http://localhost:1234/api/kubernetes/resources/custom/query',
|
||||
(_, res, ctx) => res(ctx.json(mockResponse)),
|
||||
() => HttpResponse.json(mockResponse),
|
||||
),
|
||||
);
|
||||
|
||||
@@ -157,15 +159,15 @@ describe('KubernetesBackendClient', () => {
|
||||
const customObject: ObjectsByEntityResponse =
|
||||
await backendClient.getCustomObjectsByEntity(request);
|
||||
|
||||
expect(customObject).toStrictEqual(mockResponse);
|
||||
expect(customObject).toEqual(mockResponse);
|
||||
});
|
||||
|
||||
it('/resources/custom/query API throws a 404 error', async () => {
|
||||
identityApi.getCredentials.mockResolvedValue({ token: 'idToken' });
|
||||
worker.use(
|
||||
rest.post(
|
||||
http.post(
|
||||
'http://localhost:1234/api/kubernetes/resources/custom/query',
|
||||
(_, res, ctx) => res(ctx.status(404)),
|
||||
() => new HttpResponse(null, { status: 404 }),
|
||||
),
|
||||
);
|
||||
|
||||
@@ -197,9 +199,9 @@ describe('KubernetesBackendClient', () => {
|
||||
it('/resources/custom/query API throws a 500 error', async () => {
|
||||
identityApi.getCredentials.mockResolvedValue({ token: 'idToken' });
|
||||
worker.use(
|
||||
rest.post(
|
||||
http.post(
|
||||
'http://localhost:1234/api/kubernetes/resources/custom/query',
|
||||
(_, res, ctx) => res(ctx.status(500)),
|
||||
() => new HttpResponse(null, { status: 500 }),
|
||||
),
|
||||
);
|
||||
|
||||
@@ -231,9 +233,8 @@ describe('KubernetesBackendClient', () => {
|
||||
it('hits the /services/{entityName} API', async () => {
|
||||
identityApi.getCredentials.mockResolvedValue({ token: 'idToken' });
|
||||
worker.use(
|
||||
rest.post(
|
||||
'http://localhost:1234/api/kubernetes/services/test-name',
|
||||
(_, res, ctx) => res(ctx.json(mockResponse)),
|
||||
http.post('http://localhost:1234/api/kubernetes/services/test-name', () =>
|
||||
HttpResponse.json(mockResponse),
|
||||
),
|
||||
);
|
||||
|
||||
@@ -250,15 +251,15 @@ describe('KubernetesBackendClient', () => {
|
||||
const entityObject: ObjectsByEntityResponse =
|
||||
await backendClient.getObjectsByEntity(request);
|
||||
|
||||
expect(entityObject).toStrictEqual(mockResponse);
|
||||
expect(entityObject).toEqual(mockResponse);
|
||||
});
|
||||
|
||||
it('services/{entityName} API throws a 404 error', async () => {
|
||||
identityApi.getCredentials.mockResolvedValue({ token: 'idToken' });
|
||||
worker.use(
|
||||
rest.post(
|
||||
http.post(
|
||||
'http://localhost:1234/api/kubernetes/services/test-name',
|
||||
(_, res, ctx) => res(ctx.status(404)),
|
||||
() => new HttpResponse(null, { status: 404 }),
|
||||
),
|
||||
);
|
||||
|
||||
@@ -282,9 +283,9 @@ describe('KubernetesBackendClient', () => {
|
||||
it('services/{entityName} API throws a 500 error', async () => {
|
||||
identityApi.getCredentials.mockResolvedValue({ token: 'idToken' });
|
||||
worker.use(
|
||||
rest.post(
|
||||
http.post(
|
||||
'http://localhost:1234/api/kubernetes/services/test-name',
|
||||
(_, res, ctx) => res(ctx.status(500)),
|
||||
() => new HttpResponse(null, { status: 500 }),
|
||||
),
|
||||
);
|
||||
|
||||
@@ -308,9 +309,9 @@ describe('KubernetesBackendClient', () => {
|
||||
it('hits the /resources/workloads/query API', async () => {
|
||||
identityApi.getCredentials.mockResolvedValue({ token: 'idToken' });
|
||||
worker.use(
|
||||
rest.post(
|
||||
http.post(
|
||||
'http://localhost:1234/api/kubernetes/resources/workloads/query',
|
||||
(_, res, ctx) => res(ctx.json(mockResponse)),
|
||||
() => HttpResponse.json(mockResponse),
|
||||
),
|
||||
);
|
||||
|
||||
@@ -328,15 +329,15 @@ describe('KubernetesBackendClient', () => {
|
||||
const response: ObjectsByEntityResponse =
|
||||
await backendClient.getWorkloadsByEntity(request);
|
||||
|
||||
expect(response).toStrictEqual(mockResponse);
|
||||
expect(response).toEqual(mockResponse);
|
||||
});
|
||||
|
||||
it('/resources/workloads/query API throws a 404 error', async () => {
|
||||
identityApi.getCredentials.mockResolvedValue({ token: 'idToken' });
|
||||
worker.use(
|
||||
rest.post(
|
||||
http.post(
|
||||
'http://localhost:1234/api/kubernetes/resources/workloads/query',
|
||||
(_, res, ctx) => res(ctx.status(404)),
|
||||
() => new HttpResponse(null, { status: 404 }),
|
||||
),
|
||||
);
|
||||
|
||||
@@ -361,9 +362,9 @@ describe('KubernetesBackendClient', () => {
|
||||
it('/resources/workloads/query API throws a 500 error', async () => {
|
||||
identityApi.getCredentials.mockResolvedValue({ token: 'idToken' });
|
||||
worker.use(
|
||||
rest.post(
|
||||
http.post(
|
||||
'http://localhost:1234/api/kubernetes/resources/workloads/query',
|
||||
(_, res, ctx) => res(ctx.status(500)),
|
||||
() => new HttpResponse(null, { status: 500 }),
|
||||
),
|
||||
);
|
||||
|
||||
@@ -388,12 +389,10 @@ describe('KubernetesBackendClient', () => {
|
||||
describe('proxy', () => {
|
||||
beforeEach(() => {
|
||||
worker.use(
|
||||
rest.get(
|
||||
'http://localhost:1234/api/kubernetes/clusters',
|
||||
(_, res, ctx) =>
|
||||
res(
|
||||
ctx.json({ items: [{ name: 'cluster-a', authProvider: 'aws' }] }),
|
||||
),
|
||||
http.get('http://localhost:1234/api/kubernetes/clusters', () =>
|
||||
HttpResponse.json({
|
||||
items: [{ name: 'cluster-a', authProvider: 'aws' }],
|
||||
}),
|
||||
),
|
||||
);
|
||||
identityApi.getCredentials.mockResolvedValue({ token: 'idToken' });
|
||||
@@ -401,20 +400,16 @@ describe('KubernetesBackendClient', () => {
|
||||
|
||||
it('hits the /proxy API with oidc as protocol and okta as auth provider', async () => {
|
||||
worker.use(
|
||||
rest.get(
|
||||
'http://localhost:1234/api/kubernetes/clusters',
|
||||
(_, res, ctx) =>
|
||||
res(
|
||||
ctx.json({
|
||||
items: [
|
||||
{
|
||||
name: 'cluster-a',
|
||||
authProvider: 'oidc',
|
||||
oidcTokenProvider: 'okta',
|
||||
},
|
||||
],
|
||||
}),
|
||||
),
|
||||
http.get('http://localhost:1234/api/kubernetes/clusters', () =>
|
||||
HttpResponse.json({
|
||||
items: [
|
||||
{
|
||||
name: 'cluster-a',
|
||||
authProvider: 'oidc',
|
||||
oidcTokenProvider: 'okta',
|
||||
},
|
||||
],
|
||||
}),
|
||||
),
|
||||
);
|
||||
kubernetesAuthProvidersApi.getCredentials.mockResolvedValue({
|
||||
@@ -428,16 +423,14 @@ describe('KubernetesBackendClient', () => {
|
||||
},
|
||||
};
|
||||
worker.use(
|
||||
rest.get(
|
||||
http.get(
|
||||
'http://localhost:1234/api/kubernetes/proxy/api/v1/namespaces',
|
||||
(req, res, ctx) =>
|
||||
res(
|
||||
req.headers.get(
|
||||
'Backstage-Kubernetes-Authorization-oidc-okta',
|
||||
) === 'k8-token3'
|
||||
? ctx.json(nsResponse)
|
||||
: ctx.status(403),
|
||||
),
|
||||
({ request }) =>
|
||||
request.headers.get(
|
||||
'Backstage-Kubernetes-Authorization-oidc-okta',
|
||||
) === 'k8-token3'
|
||||
? HttpResponse.json(nsResponse)
|
||||
: new HttpResponse(null, { status: 403 }),
|
||||
),
|
||||
);
|
||||
|
||||
@@ -448,7 +441,7 @@ describe('KubernetesBackendClient', () => {
|
||||
|
||||
const response = await backendClient.proxy(request);
|
||||
|
||||
await expect(response.json()).resolves.toStrictEqual(nsResponse);
|
||||
await expect(response.json()).resolves.toEqual(nsResponse);
|
||||
expect(kubernetesAuthProvidersApi.getCredentials).toHaveBeenCalledWith(
|
||||
'oidc.okta',
|
||||
);
|
||||
@@ -457,19 +450,15 @@ describe('KubernetesBackendClient', () => {
|
||||
it('hits the /proxy API with serviceAccount as auth provider', async () => {
|
||||
identityApi.getCredentials.mockResolvedValue({ token: 'idToken' });
|
||||
worker.use(
|
||||
rest.get(
|
||||
'http://localhost:1234/api/kubernetes/clusters',
|
||||
(_, res, ctx) =>
|
||||
res(
|
||||
ctx.json({
|
||||
items: [
|
||||
{
|
||||
name: 'cluster-a',
|
||||
authProvider: 'serviceAccount',
|
||||
},
|
||||
],
|
||||
}),
|
||||
),
|
||||
http.get('http://localhost:1234/api/kubernetes/clusters', () =>
|
||||
HttpResponse.json({
|
||||
items: [
|
||||
{
|
||||
name: 'cluster-a',
|
||||
authProvider: 'serviceAccount',
|
||||
},
|
||||
],
|
||||
}),
|
||||
),
|
||||
);
|
||||
|
||||
@@ -481,14 +470,12 @@ describe('KubernetesBackendClient', () => {
|
||||
},
|
||||
};
|
||||
worker.use(
|
||||
rest.get(
|
||||
http.get(
|
||||
'http://localhost:1234/api/kubernetes/proxy/api/v1/namespaces',
|
||||
(req, res, ctx) =>
|
||||
res(
|
||||
req.headers.get('Authorization') === 'Bearer idToken'
|
||||
? ctx.json(nsResponse)
|
||||
: ctx.status(403),
|
||||
),
|
||||
({ request }) =>
|
||||
request.headers.get('Authorization') === 'Bearer idToken'
|
||||
? HttpResponse.json(nsResponse)
|
||||
: new HttpResponse(null, { status: 403 }),
|
||||
),
|
||||
);
|
||||
|
||||
@@ -499,7 +486,7 @@ describe('KubernetesBackendClient', () => {
|
||||
|
||||
const response = await backendClient.proxy(request);
|
||||
|
||||
await expect(response.json()).resolves.toStrictEqual(nsResponse);
|
||||
await expect(response.json()).resolves.toEqual(nsResponse);
|
||||
expect(kubernetesAuthProvidersApi.getCredentials).toHaveBeenCalledWith(
|
||||
'serviceAccount',
|
||||
);
|
||||
@@ -507,24 +494,20 @@ describe('KubernetesBackendClient', () => {
|
||||
|
||||
it('ignores oidcTokenProvider for non-oidc auth provider', async () => {
|
||||
worker.use(
|
||||
rest.get(
|
||||
'http://localhost:1234/api/kubernetes/clusters',
|
||||
(_, res, ctx) =>
|
||||
res(
|
||||
ctx.json({
|
||||
items: [
|
||||
{
|
||||
name: 'cluster-a',
|
||||
authProvider: 'not oidc',
|
||||
oidcTokenProvider: 'should be ignored',
|
||||
},
|
||||
],
|
||||
}),
|
||||
),
|
||||
http.get('http://localhost:1234/api/kubernetes/clusters', () =>
|
||||
HttpResponse.json({
|
||||
items: [
|
||||
{
|
||||
name: 'cluster-a',
|
||||
authProvider: 'not oidc',
|
||||
oidcTokenProvider: 'should be ignored',
|
||||
},
|
||||
],
|
||||
}),
|
||||
),
|
||||
rest.get(
|
||||
http.get(
|
||||
'http://localhost:1234/api/kubernetes/proxy/api/v1/namespaces',
|
||||
(_, res, ctx) => res(ctx.json([])),
|
||||
() => HttpResponse.json([]),
|
||||
),
|
||||
);
|
||||
|
||||
@@ -552,15 +535,13 @@ describe('KubernetesBackendClient', () => {
|
||||
},
|
||||
};
|
||||
worker.use(
|
||||
rest.get(
|
||||
http.get(
|
||||
'http://localhost:1234/api/kubernetes/proxy/api/v1/namespaces',
|
||||
(req, res, ctx) =>
|
||||
res(
|
||||
req.headers.get('Backstage-Kubernetes-Authorization-aws') ===
|
||||
'k8-token'
|
||||
? ctx.json(nsResponse)
|
||||
: ctx.status(403),
|
||||
),
|
||||
({ request }) =>
|
||||
request.headers.get('Backstage-Kubernetes-Authorization-aws') ===
|
||||
'k8-token'
|
||||
? HttpResponse.json(nsResponse)
|
||||
: new HttpResponse(null, { status: 403 }),
|
||||
),
|
||||
);
|
||||
|
||||
@@ -570,7 +551,7 @@ describe('KubernetesBackendClient', () => {
|
||||
};
|
||||
|
||||
const response = await backendClient.proxy(request);
|
||||
await expect(response.json()).resolves.toStrictEqual(nsResponse);
|
||||
await expect(response.json()).resolves.toEqual(nsResponse);
|
||||
});
|
||||
|
||||
it('/proxy API throws a 404 error', async () => {
|
||||
@@ -578,9 +559,9 @@ describe('KubernetesBackendClient', () => {
|
||||
token: 'k8-token',
|
||||
});
|
||||
worker.use(
|
||||
rest.get(
|
||||
http.get(
|
||||
'http://localhost:1234/api/kubernetes/proxy/api/v1/namespaces',
|
||||
(_, res, ctx) => res(ctx.status(404)),
|
||||
() => new HttpResponse(null, { status: 404 }),
|
||||
),
|
||||
);
|
||||
|
||||
@@ -616,15 +597,13 @@ describe('KubernetesBackendClient', () => {
|
||||
},
|
||||
};
|
||||
worker.use(
|
||||
rest.get(
|
||||
http.get(
|
||||
'http://localhost:1234/api/kubernetes/proxy/api/v1/namespaces',
|
||||
(req, res, ctx) =>
|
||||
res(
|
||||
req.headers.get('Backstage-Kubernetes-Authorization') ===
|
||||
'Bearer k8-token'
|
||||
? ctx.json(nsResponse)
|
||||
: ctx.status(403),
|
||||
),
|
||||
({ request }) =>
|
||||
request.headers.get('Backstage-Kubernetes-Authorization') ===
|
||||
'Bearer k8-token'
|
||||
? HttpResponse.json(nsResponse)
|
||||
: new HttpResponse(null, { status: 403 }),
|
||||
),
|
||||
);
|
||||
|
||||
@@ -646,14 +625,12 @@ describe('KubernetesBackendClient', () => {
|
||||
},
|
||||
};
|
||||
worker.use(
|
||||
rest.get(
|
||||
http.get(
|
||||
'http://localhost:1234/api/kubernetes/proxy/api/v1/namespaces/new-ns',
|
||||
(req, res, ctx) =>
|
||||
res(
|
||||
req.headers.get('Backstage-Kubernetes-Authorization')
|
||||
? ctx.status(403)
|
||||
: ctx.json(nsResponse),
|
||||
),
|
||||
({ request }) =>
|
||||
request.headers.get('Backstage-Kubernetes-Authorization')
|
||||
? new HttpResponse(null, { status: 403 })
|
||||
: HttpResponse.json(nsResponse),
|
||||
),
|
||||
);
|
||||
kubernetesAuthProvidersApi.getCredentials.mockResolvedValue({});
|
||||
@@ -663,7 +640,7 @@ describe('KubernetesBackendClient', () => {
|
||||
path: '/api/v1/namespaces/new-ns',
|
||||
});
|
||||
|
||||
await expect(response.json()).resolves.toStrictEqual(nsResponse);
|
||||
await expect(response.json()).resolves.toEqual(nsResponse);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -21,11 +21,6 @@ describe('HeadlampClusterLinksFormatter', () => {
|
||||
|
||||
beforeEach(() => {
|
||||
formatter = new HeadlampClusterLinksFormatter();
|
||||
// Mock window.location.origin
|
||||
Object.defineProperty(window, 'location', {
|
||||
value: { origin: 'http://localhost:3000' },
|
||||
writable: true,
|
||||
});
|
||||
});
|
||||
|
||||
it('formats internal dashboard link correctly', async () => {
|
||||
@@ -41,7 +36,7 @@ describe('HeadlampClusterLinksFormatter', () => {
|
||||
|
||||
const result = await formatter.formatClusterLink(options);
|
||||
expect(result.toString()).toBe(
|
||||
'http://localhost:3000/headlamp?to=%2Fc%2Ftest-cluster%2Fpods%2Fdefault%2Ftest-pod',
|
||||
'http://localhost/headlamp?to=%2Fc%2Ftest-cluster%2Fpods%2Fdefault%2Ftest-pod',
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
@@ -148,9 +148,7 @@ describe('PermissionIntegrationClient', () => {
|
||||
],
|
||||
);
|
||||
|
||||
expect(response).toEqual(
|
||||
expect.objectContaining([{ id: '123', result: AuthorizeResult.ALLOW }]),
|
||||
);
|
||||
expect(response).toEqual([{ id: '123', result: AuthorizeResult.ALLOW }]);
|
||||
});
|
||||
|
||||
it('should not include authorization headers if no token is supplied', async () => {
|
||||
|
||||
@@ -514,11 +514,12 @@ describe('Stepper', () => {
|
||||
|
||||
const mockFormData = { firstName: 'John' };
|
||||
|
||||
Object.defineProperty(window, 'location', {
|
||||
value: {
|
||||
search: `?formData=${JSON.stringify(mockFormData)}`,
|
||||
},
|
||||
});
|
||||
// Use history.replaceState to set the query string (jsdom 27 doesn't allow redefining window.location)
|
||||
window.history.replaceState(
|
||||
{},
|
||||
'',
|
||||
`?formData=${JSON.stringify(mockFormData)}`,
|
||||
);
|
||||
|
||||
const { getByRole } = await renderInTestApp(
|
||||
<SecretsContextProvider>
|
||||
|
||||
-8
@@ -20,14 +20,6 @@ import { MockFileSystemAccess } from '../../../lib/filesystem/MockFileSystemAcce
|
||||
import { DirectoryEditorProvider } from './DirectoryEditorContext';
|
||||
import { TemplateEditorBrowser } from './TemplateEditorBrowser';
|
||||
|
||||
Blob.prototype.text = async function text() {
|
||||
return new Promise(resolve => {
|
||||
const reader = new FileReader();
|
||||
reader.onload = () => resolve(reader.result as string);
|
||||
reader.readAsText(this);
|
||||
});
|
||||
};
|
||||
|
||||
describe('TemplateEditorBrowser', () => {
|
||||
it('should render files and expand dirs without exploding', async () => {
|
||||
await renderInTestApp(
|
||||
|
||||
@@ -33,7 +33,7 @@ describe('<VirtualizedListbox />', () => {
|
||||
aria-expanded="true"
|
||||
class="MuiAutocomplete-root MuiAutocomplete-hasClearIcon MuiAutocomplete-hasPopupIcon"
|
||||
role="combobox"
|
||||
style="position: relative; height: 18px; width: 100%; overflow: auto; will-change: transform; direction: ltr;"
|
||||
style="position: relative; height: 18px; width: 100%; overflow: auto; -webkit-overflow-scrolling: touch; will-change: transform; direction: ltr;"
|
||||
>
|
||||
<div
|
||||
style="height: 0px; width: 100%;"
|
||||
@@ -50,7 +50,7 @@ describe('<VirtualizedListbox />', () => {
|
||||
<div>
|
||||
<div>
|
||||
<div
|
||||
style="position: relative; height: 18px; width: 100%; overflow: auto; will-change: transform; direction: ltr;"
|
||||
style="position: relative; height: 18px; width: 100%; overflow: auto; -webkit-overflow-scrolling: touch; will-change: transform; direction: ltr;"
|
||||
>
|
||||
<div
|
||||
style="height: 0px; width: 100%;"
|
||||
@@ -71,7 +71,7 @@ describe('<VirtualizedListbox />', () => {
|
||||
<div>
|
||||
<div>
|
||||
<div
|
||||
style="position: relative; height: 54px; width: 100%; overflow: auto; will-change: transform; direction: ltr;"
|
||||
style="position: relative; height: 54px; width: 100%; overflow: auto; -webkit-overflow-scrolling: touch; will-change: transform; direction: ltr;"
|
||||
>
|
||||
<div
|
||||
style="height: 36px; width: 100%;"
|
||||
@@ -100,7 +100,7 @@ describe('<VirtualizedListbox />', () => {
|
||||
<div>
|
||||
<div>
|
||||
<div
|
||||
style="position: relative; height: 378px; width: 100%; overflow: auto; will-change: transform; direction: ltr;"
|
||||
style="position: relative; height: 378px; width: 100%; overflow: auto; -webkit-overflow-scrolling: touch; will-change: transform; direction: ltr;"
|
||||
>
|
||||
<div
|
||||
style="height: 360px; width: 100%;"
|
||||
@@ -184,7 +184,7 @@ describe('<VirtualizedListbox />', () => {
|
||||
<div>
|
||||
<div>
|
||||
<div
|
||||
style="position: relative; height: 378px; width: 100%; overflow: auto; will-change: transform; direction: ltr;"
|
||||
style="position: relative; height: 378px; width: 100%; overflow: auto; -webkit-overflow-scrolling: touch; will-change: transform; direction: ltr;"
|
||||
>
|
||||
<div
|
||||
style="height: 3600px; width: 100%;"
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { screen, waitFor } from '@testing-library/react';
|
||||
import { screen, waitFor, fireEvent } from '@testing-library/react';
|
||||
import userEvent from '@testing-library/user-event';
|
||||
|
||||
import MenuItem from '@material-ui/core/MenuItem';
|
||||
@@ -312,10 +312,10 @@ describe('SearchResultGroup', () => {
|
||||
|
||||
await userEvent.click(screen.getByText('owner'));
|
||||
|
||||
await userEvent.type(
|
||||
screen.getByRole('textbox'),
|
||||
'{backspace}{backspace}{backspace}{backspace}techdocs-core',
|
||||
);
|
||||
// Use fireEvent.blur for contentEditable elements since userEvent.type with
|
||||
// backspace doesn't work properly in jsdom (jsdom limitation, not a bug)
|
||||
const textbox = screen.getByRole('textbox');
|
||||
fireEvent.blur(textbox, { target: { textContent: 'techdocs-core' } });
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.getByText('techdocs-core')).toBeInTheDocument();
|
||||
|
||||
@@ -21,21 +21,13 @@ import { screen } from '@testing-library/react';
|
||||
describe('handleMetaRedirects', () => {
|
||||
const navigate = jest.fn();
|
||||
|
||||
const setUpNewTestShadowDom = async (
|
||||
html: string,
|
||||
rootHref: string,
|
||||
rootPath: string,
|
||||
) => {
|
||||
const setUpNewTestShadowDom = async (html: string, rootHref: string) => {
|
||||
const entityName = 'testEntity';
|
||||
// Mock window.location.href for each test
|
||||
Object.defineProperty(window, 'location', {
|
||||
value: {
|
||||
href: rootHref,
|
||||
pathname: rootPath,
|
||||
hostname: 'localhost',
|
||||
},
|
||||
writable: true,
|
||||
});
|
||||
// Use history.replaceState to change location (jsdom 27+ doesn't allow redefining location)
|
||||
// Jest's jsdom starts at http://localhost/, so replaceState updates the pathname while
|
||||
// keeping hostname and origin as 'localhost'.
|
||||
const url = new URL(rootHref);
|
||||
history.replaceState(null, '', `${url.pathname}${url.search}${url.hash}`);
|
||||
return await createTestShadowDom(html, {
|
||||
preTransformers: [],
|
||||
postTransformers: [handleMetaRedirects(navigate, entityName)],
|
||||
@@ -55,7 +47,6 @@ describe('handleMetaRedirects', () => {
|
||||
await setUpNewTestShadowDom(
|
||||
`<meta http-equiv="refresh" content="0; url=../anotherPage">`,
|
||||
'http://localhost/docs/default/component/testEntity/subpath',
|
||||
'/docs/default/component/testEntity/subpath',
|
||||
);
|
||||
|
||||
expect(
|
||||
@@ -73,7 +64,6 @@ describe('handleMetaRedirects', () => {
|
||||
await setUpNewTestShadowDom(
|
||||
`<meta http-equiv="refresh" content="0; url=http://external.com/test">`,
|
||||
'http://localhost/docs/default/component/testEntity/subpath',
|
||||
'/docs/default/component/testEntity/subpath',
|
||||
);
|
||||
|
||||
expect(
|
||||
@@ -91,7 +81,6 @@ describe('handleMetaRedirects', () => {
|
||||
await setUpNewTestShadowDom(
|
||||
`<meta http-equiv="refresh" content="0; url=http://localhost/test">`,
|
||||
'http://localhost/docs/default/component/testEntity/subpath',
|
||||
'/docs/default/component/testEntity/subpath',
|
||||
);
|
||||
|
||||
expect(
|
||||
@@ -107,7 +96,6 @@ describe('handleMetaRedirects', () => {
|
||||
await setUpNewTestShadowDom(
|
||||
`<meta name="keywords" content="TechDocs, Example">`,
|
||||
'http://localhost/docs/default/component/testEntity/subpath',
|
||||
'/docs/default/component/testEntity/subpath',
|
||||
);
|
||||
|
||||
jest.runAllTimers();
|
||||
|
||||
Reference in New Issue
Block a user