diff --git a/package.json b/package.json index ccac6bcdd89..42fab464612 100644 --- a/package.json +++ b/package.json @@ -183,7 +183,7 @@ "jest-matcher-utils": "29.7.0", "lerna": "7.4.1", "mini-css-extract-plugin": "2.8.0", - "msw": "1.3.2", + "msw": "2.2.0", "mutationobserver-shim": "0.3.7", "ngtemplate-loader": "2.1.0", "node-notifier": "10.0.1", diff --git a/public/app/core/components/NestedFolderPicker/NestedFolderPicker.test.tsx b/public/app/core/components/NestedFolderPicker/NestedFolderPicker.test.tsx index f5ed2595d83..73368d51752 100644 --- a/public/app/core/components/NestedFolderPicker/NestedFolderPicker.test.tsx +++ b/public/app/core/components/NestedFolderPicker/NestedFolderPicker.test.tsx @@ -1,7 +1,7 @@ import 'whatwg-fetch'; // fetch polyfill import { fireEvent, render as rtlRender, screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; -import { rest } from 'msw'; +import { HttpResponse, http } from 'msw'; import { SetupServer, setupServer } from 'msw/node'; import React from 'react'; import { TestProvider } from 'test/helpers/TestProvider'; @@ -47,14 +47,11 @@ describe('NestedFolderPicker', () => { beforeAll(() => { window.HTMLElement.prototype.scrollIntoView = function () {}; server = setupServer( - rest.get('/api/folders/:uid', (_, res, ctx) => { - return res( - ctx.status(200), - ctx.json({ - title: folderA.item.title, - uid: folderA.item.uid, - }) - ); + http.get('/api/folders/:uid', () => { + return HttpResponse.json({ + title: folderA.item.title, + uid: folderA.item.uid, + }); }) ); server.listen(); diff --git a/public/app/features/alerting/unified/CloneRuleEditor.test.tsx b/public/app/features/alerting/unified/CloneRuleEditor.test.tsx index b14798e4f35..747f66b4eb1 100644 --- a/public/app/features/alerting/unified/CloneRuleEditor.test.tsx +++ b/public/app/features/alerting/unified/CloneRuleEditor.test.tsx @@ -1,3 +1,4 @@ +import 'whatwg-fetch'; import { render, waitFor, waitForElementToBeRemoved, within } from '@testing-library/react'; import { setupServer } from 'msw/node'; import React from 'react'; @@ -11,7 +12,6 @@ import { backendSrv } from 'app/core/services/backend_srv'; import { DashboardSearchItem, DashboardSearchItemType } from 'app/features/search/types'; import { AlertManagerCortexConfig } from 'app/plugins/datasource/alertmanager/types'; import { RuleWithLocation } from 'app/types/unified-alerting'; -import 'whatwg-fetch'; import { RulerAlertingRuleDTO, diff --git a/public/app/features/alerting/unified/components/GrafanaAlertmanagerDeliveryWarning.test.tsx b/public/app/features/alerting/unified/components/GrafanaAlertmanagerDeliveryWarning.test.tsx index 31fe270eaff..92583016959 100644 --- a/public/app/features/alerting/unified/components/GrafanaAlertmanagerDeliveryWarning.test.tsx +++ b/public/app/features/alerting/unified/components/GrafanaAlertmanagerDeliveryWarning.test.tsx @@ -1,10 +1,9 @@ -import { render, screen } from '@testing-library/react'; +import 'whatwg-fetch'; +import { render, screen, waitFor } from '@testing-library/react'; import { setupServer } from 'msw/node'; import React from 'react'; import { Provider } from 'react-redux'; -import 'whatwg-fetch'; - import { setBackendSrv } from '@grafana/runtime'; import { backendSrv } from 'app/core/services/backend_srv'; import { configureStore } from 'app/store/configureStore'; @@ -76,7 +75,9 @@ describe('GrafanaAlertmanagerDeliveryWarning', () => { ); - expect(container).toBeEmptyDOMElement(); + await waitFor(() => { + expect(container).toBeEmptyDOMElement(); + }); }); it('Should render no warning when choice is All but no active AM instances', async () => { @@ -89,7 +90,9 @@ describe('GrafanaAlertmanagerDeliveryWarning', () => { ); - expect(container).toBeEmptyDOMElement(); + await waitFor(() => { + expect(container).toBeEmptyDOMElement(); + }); }); }); diff --git a/public/app/features/alerting/unified/components/PluginBridge.mock.ts b/public/app/features/alerting/unified/components/PluginBridge.mock.ts index 3644ce5779a..d71d70c313d 100644 --- a/public/app/features/alerting/unified/components/PluginBridge.mock.ts +++ b/public/app/features/alerting/unified/components/PluginBridge.mock.ts @@ -1,20 +1,25 @@ -import { rest } from 'msw'; -import { setupServer } from 'msw/node'; - // bit of setup to mock HTTP request responses import 'whatwg-fetch'; +import { http, HttpResponse } from 'msw'; +import { setupServer } from 'msw/node'; + import { SupportedPlugin } from '../types/pluginBridges'; export const NON_EXISTING_PLUGIN = '__does_not_exist__'; const server = setupServer( - rest.get(`/api/plugins/${NON_EXISTING_PLUGIN}/settings`, async (_req, res, ctx) => res(ctx.status(404))), - rest.get(`/api/plugins/${SupportedPlugin.Incident}/settings`, async (_req, res, ctx) => { - return res( - ctx.json({ - enabled: true, - }) - ); + http.get(`/api/plugins/${NON_EXISTING_PLUGIN}/settings`, async () => + HttpResponse.json( + {}, + { + status: 404, + } + ) + ), + http.get(`/api/plugins/${SupportedPlugin.Incident}/settings`, async () => { + return HttpResponse.json({ + enabled: true, + }); }) ); diff --git a/public/app/features/alerting/unified/components/contact-points/__mocks__/grafanaManagedServer.ts b/public/app/features/alerting/unified/components/contact-points/__mocks__/grafanaManagedServer.ts index a93b7b046c0..54666de1aa5 100644 --- a/public/app/features/alerting/unified/components/contact-points/__mocks__/grafanaManagedServer.ts +++ b/public/app/features/alerting/unified/components/contact-points/__mocks__/grafanaManagedServer.ts @@ -1,4 +1,5 @@ -import { rest } from 'msw'; +import 'whatwg-fetch'; +import { http, HttpResponse } from 'msw'; import { SetupServer } from 'msw/node'; import { AlertmanagerChoice, AlertManagerCortexConfig } from 'app/plugins/datasource/alertmanager/types'; @@ -14,15 +15,15 @@ import receiversMock from './receivers.mock.json'; export default (server: SetupServer) => { server.use( // this endpoint is a grafana built-in alertmanager - rest.get('/api/alertmanager/grafana/config/api/v1/alerts', (_req, res, ctx) => - res(ctx.json(alertmanagerMock)) + http.get('/api/alertmanager/grafana/config/api/v1/alerts', () => + HttpResponse.json(alertmanagerMock) ), // this endpoint is only available for the built-in alertmanager - rest.get('/api/alertmanager/grafana/config/api/v1/receivers', (_req, res, ctx) => - res(ctx.json(receiversMock)) + http.get('/api/alertmanager/grafana/config/api/v1/receivers', () => + HttpResponse.json(receiversMock) ), // this endpoint will respond if the OnCall plugin is installed - rest.get('/api/plugins/grafana-oncall-app/settings', (_req, res, ctx) => res(ctx.status(404))) + http.get('/api/plugins/grafana-oncall-app/settings', () => HttpResponse.json({}, { status: 404 })) ); // this endpoint is for rendering the "additional AMs to configure" warning @@ -41,12 +42,18 @@ export const setupTestEndpointMock = (server: SetupServer) => { const mock = jest.fn(); server.use( - rest.post('/api/alertmanager/grafana/config/api/v1/receivers/test', async (req, res, ctx) => { - const requestBody = await req.json(); - mock(requestBody); + http.post( + '/api/alertmanager/grafana/config/api/v1/receivers/test', + async ({ request }) => { + const requestBody = await request.json(); + mock(requestBody); - return res.once(ctx.status(200)); - }) + return HttpResponse.json({}); + }, + { + once: true, + } + ) ); return mock; @@ -56,12 +63,18 @@ export const setupSaveEndpointMock = (server: SetupServer) => { const mock = jest.fn(); server.use( - rest.post('/api/alertmanager/grafana/config/api/v1/alerts', async (req, res, ctx) => { - const requestBody = await req.json(); - mock(requestBody); + http.post( + '/api/alertmanager/grafana/config/api/v1/alerts', + async ({ request }) => { + const requestBody = await request.json(); + mock(requestBody); - return res.once(ctx.status(200)); - }) + return HttpResponse.json({}); + }, + { + once: true, + } + ) ); return mock; diff --git a/public/app/features/alerting/unified/components/contact-points/__mocks__/mimirFlavoredServer.ts b/public/app/features/alerting/unified/components/contact-points/__mocks__/mimirFlavoredServer.ts index 88ef97018e9..adbed73cb48 100644 --- a/public/app/features/alerting/unified/components/contact-points/__mocks__/mimirFlavoredServer.ts +++ b/public/app/features/alerting/unified/components/contact-points/__mocks__/mimirFlavoredServer.ts @@ -1,4 +1,5 @@ -import { rest } from 'msw'; +import 'whatwg-fetch'; +import { http, HttpResponse } from 'msw'; import { SetupServer } from 'msw/lib/node'; import { AlertManagerCortexConfig } from 'app/plugins/datasource/alertmanager/types'; @@ -10,14 +11,20 @@ export const MIMIR_DATASOURCE_UID = 'mimir'; export default (server: SetupServer) => { server.use( - rest.get(`/api/alertmanager/${MIMIR_DATASOURCE_UID}/config/api/v1/alerts`, (_req, res, ctx) => - res(ctx.json(mimirAlertmanagerMock)) + http.get(`/api/alertmanager/${MIMIR_DATASOURCE_UID}/config/api/v1/alerts`, () => + HttpResponse.json(mimirAlertmanagerMock) ), - rest.get(`/api/datasources/proxy/uid/${MIMIR_DATASOURCE_UID}/api/v1/status/buildinfo`, (_req, res, ctx) => - res(ctx.status(404)) + http.get(`/api/datasources/proxy/uid/${MIMIR_DATASOURCE_UID}/api/v1/status/buildinfo`, () => + HttpResponse.json( + { + template_files: {}, + alertmanager_config: {}, + }, + { status: 404 } + ) ), // this endpoint will respond if the OnCall plugin is installed - rest.get('/api/plugins/grafana-oncall-app/settings', (_req, res, ctx) => res(ctx.status(404))) + http.get('/api/plugins/grafana-oncall-app/settings', () => HttpResponse.json({}, { status: 404 })) ); return server; diff --git a/public/app/features/alerting/unified/components/contact-points/__mocks__/vanillaAlertmanagerServer.ts b/public/app/features/alerting/unified/components/contact-points/__mocks__/vanillaAlertmanagerServer.ts index b834a5a515f..6c4943e28a2 100644 --- a/public/app/features/alerting/unified/components/contact-points/__mocks__/vanillaAlertmanagerServer.ts +++ b/public/app/features/alerting/unified/components/contact-points/__mocks__/vanillaAlertmanagerServer.ts @@ -1,4 +1,5 @@ -import { rest } from 'msw'; +import 'whatwg-fetch'; +import { http, HttpResponse } from 'msw'; import { SetupServer } from 'msw/lib/node'; import { AlertmanagerStatus } from 'app/plugins/datasource/alertmanager/types'; @@ -10,11 +11,11 @@ export const VANILLA_ALERTMANAGER_DATASOURCE_UID = 'alertmanager'; export default (server: SetupServer) => { server.use( - rest.get(`/api/alertmanager/${VANILLA_ALERTMANAGER_DATASOURCE_UID}/api/v2/status`, (_req, res, ctx) => - res(ctx.json(vanillaAlertManagerConfig)) + http.get(`/api/alertmanager/${VANILLA_ALERTMANAGER_DATASOURCE_UID}/api/v2/status`, () => + HttpResponse.json(vanillaAlertManagerConfig) ), // this endpoint will respond if the OnCall plugin is installed - rest.get('/api/plugins/grafana-oncall-app/settings', (_req, res, ctx) => res(ctx.status(404))) + http.get('/api/plugins/grafana-oncall-app/settings', () => HttpResponse.json({}, { status: 404 })) ); return server; diff --git a/public/app/features/alerting/unified/components/rule-viewer/v2/__mocks__/server.ts b/public/app/features/alerting/unified/components/rule-viewer/v2/__mocks__/server.ts index a9ec31748fe..83584bb4155 100644 --- a/public/app/features/alerting/unified/components/rule-viewer/v2/__mocks__/server.ts +++ b/public/app/features/alerting/unified/components/rule-viewer/v2/__mocks__/server.ts @@ -1,7 +1,7 @@ -import { rest } from 'msw'; +import 'whatwg-fetch'; +import { http, HttpResponse } from 'msw'; import { SetupServer, setupServer } from 'msw/node'; -import 'whatwg-fetch'; import { AlertmanagersChoiceResponse } from 'app/features/alerting/unified/api/alertmanagerApi'; import { mockAlertmanagerChoiceResponse } from 'app/features/alerting/unified/mocks/alertmanagerApi'; import { AlertmanagerChoice } from 'app/plugins/datasource/alertmanager/types'; @@ -33,16 +33,15 @@ export function createMockGrafanaServer() { // a user must alsso have permissions for the folder (namespace) in which the alert rule is stored function mockFolderAccess(server: SetupServer, accessControl: Partial>) { server.use( - rest.get('/api/folders/:uid', (req, res, ctx) => { - const uid = req.params.uid; + http.get('/api/folders/:uid', ({ request }) => { + const url = new URL(request.url); + const uid = url.searchParams.get('uid'); - return res( - ctx.json({ - title: 'My Folder', - uid, - accessControl, - }) - ); + return HttpResponse.json({ + title: 'My Folder', + uid, + accessControl, + }); }) ); @@ -51,8 +50,8 @@ function mockFolderAccess(server: SetupServer, accessControl: Partial { - return res(ctx.status(200)); + http.get('/api/plugins/grafana-incident-app/settings', () => { + return HttpResponse.json({}); }) ); } diff --git a/public/app/features/alerting/unified/components/rules/RuleDetails.test.tsx b/public/app/features/alerting/unified/components/rules/RuleDetails.test.tsx index 9ee4496bd17..59e89009881 100644 --- a/public/app/features/alerting/unified/components/rules/RuleDetails.test.tsx +++ b/public/app/features/alerting/unified/components/rules/RuleDetails.test.tsx @@ -1,4 +1,6 @@ +import 'whatwg-fetch'; import { render, screen, waitFor } from '@testing-library/react'; +import { http, HttpResponse } from 'msw'; import { setupServer } from 'msw/node'; import React from 'react'; import { Provider } from 'react-redux'; @@ -18,6 +20,7 @@ import { AlertmanagersChoiceResponse } from '../../api/alertmanagerApi'; import { useIsRuleEditable } from '../../hooks/useIsRuleEditable'; import { getCloudRule, getGrafanaRule } from '../../mocks'; import { mockAlertmanagerChoiceResponse } from '../../mocks/alertmanagerApi'; +import { SupportedPlugin } from '../../types/pluginBridges'; import { RuleDetails } from './RuleDetails'; @@ -42,7 +45,13 @@ const ui = { }, }; -const server = setupServer(); +const server = setupServer( + http.get(`/api/plugins/${SupportedPlugin.Incident}/settings`, async () => { + return HttpResponse.json({ + enabled: false, + }); + }) +); const alertmanagerChoiceMockedResponse: AlertmanagersChoiceResponse = { alertmanagersChoice: AlertmanagerChoice.Internal, @@ -74,6 +83,7 @@ beforeEach(() => { ], }); server.resetHandlers(); + mockAlertmanagerChoiceResponse(server, alertmanagerChoiceMockedResponse); }); describe('RuleDetails RBAC', () => { @@ -107,7 +117,6 @@ describe('RuleDetails RBAC', () => { it('Should not render Silence button for users wihout the instance create permission', async () => { // Arrange jest.spyOn(contextSrv, 'hasPermission').mockReturnValue(false); - mockAlertmanagerChoiceResponse(server, alertmanagerChoiceMockedResponse); // Act renderRuleDetails(grafanaRule); @@ -118,8 +127,6 @@ describe('RuleDetails RBAC', () => { }); it('Should render Silence button for users with the instance create permissions', async () => { - mockAlertmanagerChoiceResponse(server, alertmanagerChoiceMockedResponse); - // Arrange jest .spyOn(contextSrv, 'hasPermission') diff --git a/public/app/features/alerting/unified/components/rules/RulesGroup.test.tsx b/public/app/features/alerting/unified/components/rules/RulesGroup.test.tsx index b224dd8db30..3093caf579c 100644 --- a/public/app/features/alerting/unified/components/rules/RulesGroup.test.tsx +++ b/public/app/features/alerting/unified/components/rules/RulesGroup.test.tsx @@ -108,10 +108,12 @@ describe('Rules group tests', () => { groups: [group], }; - it('Should hide delete and edit group buttons', () => { + it('Should hide delete and edit group buttons', async () => { // Act mockUseHasRuler(true, true); + mockFolderApi(server).folder('cpu-usage', mockFolder({ uid: 'cpu-usage', canSave: false })); renderRulesGroup(namespace, group); + expect(await screen.findByTestId('rule-group')).toBeInTheDocument(); // Assert expect(ui.deleteGroupButton.query()).not.toBeInTheDocument(); diff --git a/public/app/features/alerting/unified/components/rules/state-history/LokiStateHistory.test.tsx b/public/app/features/alerting/unified/components/rules/state-history/LokiStateHistory.test.tsx index 24380f45f3f..e9ba271cdec 100644 --- a/public/app/features/alerting/unified/components/rules/state-history/LokiStateHistory.test.tsx +++ b/public/app/features/alerting/unified/components/rules/state-history/LokiStateHistory.test.tsx @@ -1,9 +1,9 @@ +import 'whatwg-fetch'; import { render, waitFor } from '@testing-library/react'; -import { rest } from 'msw'; +import { http, HttpResponse } from 'msw'; import { setupServer } from 'msw/node'; import React from 'react'; import { byRole, byText } from 'testing-library-selector'; -import 'whatwg-fetch'; import { DataFrameJSON } from '@grafana/data'; import { setBackendSrv } from '@grafana/runtime'; @@ -20,53 +20,51 @@ beforeAll(() => { server.listen({ onUnhandledRequest: 'error' }); server.use( - rest.get('/api/v1/rules/history', (req, res, ctx) => - res( - ctx.json({ - data: { - values: [ - [1681739580000, 1681739580000, 1681739580000], - [ - { - previous: 'Normal', - current: 'Pending', - values: { - B: 0.010344684900897919, - C: 1, - }, - labels: { - handler: '/api/prometheus/grafana/api/v1/rules', - }, + http.get('/api/v1/rules/history', () => + HttpResponse.json({ + data: { + values: [ + [1681739580000, 1681739580000, 1681739580000], + [ + { + previous: 'Normal', + current: 'Pending', + values: { + B: 0.010344684900897919, + C: 1, }, - { - previous: 'Normal', - current: 'Pending', - values: { - B: 0.010344684900897919, - C: 1, - }, - dashboardUID: '', - panelID: 0, - labels: { - handler: '/api/live/ws', - }, + labels: { + handler: '/api/prometheus/grafana/api/v1/rules', }, - { - previous: 'Normal', - current: 'Pending', - values: { - B: 0.010344684900897919, - C: 1, - }, - labels: { - handler: '/api/folders/:uid/', - }, + }, + { + previous: 'Normal', + current: 'Pending', + values: { + B: 0.010344684900897919, + C: 1, }, - ], + dashboardUID: '', + panelID: 0, + labels: { + handler: '/api/live/ws', + }, + }, + { + previous: 'Normal', + current: 'Pending', + values: { + B: 0.010344684900897919, + C: 1, + }, + labels: { + handler: '/api/folders/:uid/', + }, + }, ], - }, - }) - ) + ], + }, + }) ) ); }); @@ -100,8 +98,8 @@ describe('LokiStateHistory', () => { it('should render no entries message when no records are returned', async () => { server.use( - rest.get('/api/v1/rules/history', (req, res, ctx) => - res(ctx.json({ data: { values: [] }, schema: { fields: [] } })) + http.get('/api/v1/rules/history', () => + HttpResponse.json({ data: { values: [] }, schema: { fields: [] } }) ) ); diff --git a/public/app/features/alerting/unified/hooks/useExternalAMSelector.test.tsx b/public/app/features/alerting/unified/hooks/useExternalAMSelector.test.tsx index 6feda94a91c..1e15071190b 100644 --- a/public/app/features/alerting/unified/hooks/useExternalAMSelector.test.tsx +++ b/public/app/features/alerting/unified/hooks/useExternalAMSelector.test.tsx @@ -1,10 +1,9 @@ +import 'whatwg-fetch'; import { renderHook, waitFor } from '@testing-library/react'; -import { rest } from 'msw'; +import { http, HttpResponse } from 'msw'; import { SetupServer, setupServer } from 'msw/node'; import { TestProvider } from 'test/helpers/TestProvider'; -import 'whatwg-fetch'; - import { DataSourceSettings } from '@grafana/data'; import { setBackendSrv } from '@grafana/runtime'; import { backendSrv } from 'app/core/services/backend_srv'; @@ -215,8 +214,8 @@ function setupAlertmanagerDataSource( }; server.use( - rest.get('/api/datasources', (_req, res, ctx) => { - return res(ctx.json([dsSettings])); + http.get('/api/datasources', () => { + return HttpResponse.json([dsSettings]); }) ); } diff --git a/public/app/features/alerting/unified/mockApi.ts b/public/app/features/alerting/unified/mockApi.ts index d603cbe42be..cd85c322815 100644 --- a/public/app/features/alerting/unified/mockApi.ts +++ b/public/app/features/alerting/unified/mockApi.ts @@ -1,7 +1,7 @@ -import { uniqueId } from 'lodash'; -import { rest } from 'msw'; -import { setupServer, SetupServer } from 'msw/node'; import 'whatwg-fetch'; +import { uniqueId } from 'lodash'; +import { http, HttpResponse } from 'msw'; +import { setupServer, SetupServer } from 'msw/node'; import { DataSourceInstanceSettings, PluginMeta } from '@grafana/data'; import { setBackendSrv } from '@grafana/runtime'; @@ -190,85 +190,74 @@ export function mockApi(server: SetupServer) { configure(builder); server.use( - rest.get(`api/alertmanager/${amName}/config/api/v1/alerts`, (req, res, ctx) => - res( - ctx.status(200), - ctx.json({ - alertmanager_config: builder.build(), - template_files: {}, - }) - ) + http.get(`api/alertmanager/${amName}/config/api/v1/alerts`, () => + HttpResponse.json({ + alertmanager_config: builder.build(), + template_files: {}, + }) ) ); }, eval: (response: AlertingQueryResponse) => { server.use( - rest.post('/api/v1/eval', (_, res, ctx) => { - return res(ctx.status(200), ctx.json(response)); + http.post('/api/v1/eval', () => { + return HttpResponse.json(response); }) ); }, grafanaNotifiers: (response: NotifierDTO[]) => { - server.use( - rest.get(`api/alert-notifiers`, (req, res, ctx) => res(ctx.status(200), ctx.json(response))) - ); + server.use(http.get(`api/alert-notifiers`, () => HttpResponse.json(response))); }, plugins: { getPluginSettings: (response: PluginMeta) => { - server.use( - rest.get(`api/plugins/${response.id}/settings`, (req, res, ctx) => - res(ctx.status(200), ctx.json(response)) - ) - ); + server.use(http.get(`api/plugins/${response.id}/settings`, () => HttpResponse.json(response))); }, }, oncall: { getOnCallIntegrations: (response: OnCallIntegrationDTO[]) => { server.use( - rest.get(`api/plugin-proxy/grafana-oncall-app/api/internal/v1/alert_receive_channels`, (_, res, ctx) => - res(ctx.status(200), ctx.json(response)) + http.get(`api/plugin-proxy/grafana-oncall-app/api/internal/v1/alert_receive_channels`, () => + HttpResponse.json(response) ) ); }, features: (response: string[]) => { server.use( - rest.get(`api/plugin-proxy/grafana-oncall-app/api/internal/v1/features`, (_, res, ctx) => - res(ctx.status(200), ctx.json(response)) - ) + http.get(`api/plugin-proxy/grafana-oncall-app/api/internal/v1/features`, () => HttpResponse.json(response)) ); }, validateIntegrationName: (invalidNames: string[]) => { server.use( - rest.get( + http.get( `api/plugin-proxy/grafana-oncall-app/api/internal/v1/alert_receive_channels/validate_name`, - (req, res, ctx) => { - const isValid = !invalidNames.includes(req.url.searchParams.get('verbal_name') ?? ''); - return res(ctx.status(isValid ? 200 : 409), ctx.json(isValid)); + ({ request }) => { + const url = new URL(request.url); + const isValid = !invalidNames.includes(url.searchParams.get('verbal_name') ?? ''); + return HttpResponse.json(isValid, { + status: isValid ? 200 : 409, + }); } ) ); }, createIntegraion: () => { server.use( - rest.post( + http.post<{}, CreateIntegrationDTO>( `api/plugin-proxy/grafana-oncall-app/api/internal/v1/alert_receive_channels`, - async (req, res, ctx) => { - const body = await req.json(); + async ({ request }) => { + const body = await request.json(); const integrationId = uniqueId('oncall-integration-'); - return res( - ctx.status(200), - ctx.json({ - id: integrationId, - integration: body.integration, - integration_url: `https://oncall-endpoint.example.com/${integrationId}`, - verbal_name: body.verbal_name, - connected_escalations_chains_count: 0, - }) - ); + return HttpResponse.json({ + id: integrationId, + integration: body.integration, + integration_url: `https://oncall-endpoint.example.com/${integrationId}`, + verbal_name: body.verbal_name, + connected_escalations_chains_count: 0, + }); } ) ); @@ -281,21 +270,15 @@ export function mockAlertRuleApi(server: SetupServer) { return { prometheusRuleNamespaces: (dsName: string, response: PromRulesResponse) => { server.use( - rest.get(`api/prometheus/${dsName}/api/v1/rules`, (req, res, ctx) => - res(ctx.status(200), ctx.json(response)) - ) + http.get(`api/prometheus/${dsName}/api/v1/rules`, () => HttpResponse.json(response)) ); }, rulerRules: (dsName: string, response: RulerRulesConfigDTO) => { - server.use( - rest.get(`/api/ruler/${dsName}/api/v1/rules`, (req, res, ctx) => res(ctx.status(200), ctx.json(response))) - ); + server.use(http.get(`/api/ruler/${dsName}/api/v1/rules`, () => HttpResponse.json(response))); }, rulerRuleGroup: (dsName: string, namespace: string, group: string, response: RulerRuleGroupDTO) => { server.use( - rest.get(`/api/ruler/${dsName}/api/v1/rules/${namespace}/${group}`, (req, res, ctx) => - res(ctx.status(200), ctx.json(response)) - ) + http.get(`/api/ruler/${dsName}/api/v1/rules/${namespace}/${group}`, () => HttpResponse.json(response)) ); }, }; @@ -312,9 +295,7 @@ export function mockFeatureDiscoveryApi(server: SetupServer) { * @param response Use `buildInfoResponse` to get a pre-defined response for Prometheus and Mimir */ discoverDsFeatures: (dsSettings: DataSourceInstanceSettings, response: PromBuildInfoResponse) => { - server.use( - rest.get(`${dsSettings.url}/api/v1/status/buildinfo`, (_, res, ctx) => res(ctx.status(200), ctx.json(response))) - ); + server.use(http.get(`${dsSettings.url}/api/v1/status/buildinfo`, () => HttpResponse.json(response))); }, }; } @@ -323,16 +304,20 @@ export function mockProvisioningApi(server: SetupServer) { return { exportRuleGroup: (folderUid: string, groupName: string, response: Record) => { server.use( - rest.get(`/api/v1/provisioning/folder/${folderUid}/rule-groups/${groupName}/export`, (req, res, ctx) => - res(ctx.status(200), ctx.text(response[req.url.searchParams.get('format') ?? 'yaml'])) - ) + http.get(`/api/v1/provisioning/folder/${folderUid}/rule-groups/${groupName}/export`, ({ request }) => { + const url = new URL(request.url); + const format = url.searchParams.get('format') ?? 'yaml'; + return HttpResponse.text(response[format]); + }) ); }, exportReceiver: (response: Record) => { server.use( - rest.get(`/api/v1/provisioning/contact-points/export/`, (req, res, ctx) => - res(ctx.status(200), ctx.text(response[req.url.searchParams.get('format') ?? 'yaml'])) - ) + http.get(`/api/v1/provisioning/contact-points/export/`, ({ request }) => { + const url = new URL(request.url); + const format = url.searchParams.get('format') ?? 'yaml'; + return HttpResponse.text(response[format]); + }) ); }, }; @@ -344,43 +329,51 @@ export function mockExportApi(server: SetupServer) { // exportRule requires ruleUid parameter and doesn't allow folderUid and group parameters exportRule: (ruleUid: string, response: Record) => { server.use( - rest.get('/api/ruler/grafana/api/v1/export/rules', (req, res, ctx) => { - if (req.url.searchParams.get('ruleUid') === ruleUid) { - return res(ctx.status(200), ctx.text(response[req.url.searchParams.get('format') ?? 'yaml'])); + http.get('/api/ruler/grafana/api/v1/export/rules', ({ request }) => { + const url = new URL(request.url); + if (url.searchParams.get('ruleUid') === ruleUid) { + const format = url.searchParams.get('format') ?? 'yaml'; + return HttpResponse.text(response[format]); } - return res(ctx.status(500)); + return HttpResponse.text('', { status: 500 }); }) ); }, // exportRulesGroup requires folderUid and group parameters and doesn't allow ruleUid parameter exportRulesGroup: (folderUid: string, group: string, response: Record) => { server.use( - rest.get('/api/ruler/grafana/api/v1/export/rules', (req, res, ctx) => { - if (req.url.searchParams.get('folderUid') === folderUid && req.url.searchParams.get('group') === group) { - return res(ctx.status(200), ctx.text(response[req.url.searchParams.get('format') ?? 'yaml'])); + http.get('/api/ruler/grafana/api/v1/export/rules', ({ request }) => { + const url = new URL(request.url); + if (url.searchParams.get('folderUid') === folderUid && url.searchParams.get('group') === group) { + const format = url.searchParams.get('format') ?? 'yaml'; + return HttpResponse.text(response[format]); } - return res(ctx.status(500)); + return HttpResponse.text('', { status: 500 }); }) ); }, // exportRulesFolder requires folderUid parameter exportRulesFolder: (folderUid: string, response: Record) => { server.use( - rest.get('/api/ruler/grafana/api/v1/export/rules', (req, res, ctx) => { - if (req.url.searchParams.get('folderUid') === folderUid) { - return res(ctx.status(200), ctx.text(response[req.url.searchParams.get('format') ?? 'yaml'])); + http.get('/api/ruler/grafana/api/v1/export/rules', ({ request }) => { + const url = new URL(request.url); + if (url.searchParams.get('folderUid') === folderUid) { + const format = url.searchParams.get('format') ?? 'yaml'; + return HttpResponse.text(response[format]); } - return res(ctx.status(500)); + return HttpResponse.text('', { status: 500 }); }) ); }, modifiedExport: (namespaceUID: string, response: Record) => { server.use( - rest.post(`/api/ruler/grafana/api/v1/rules/${namespaceUID}/export`, (req, res, ctx) => { - return res(ctx.status(200), ctx.text(response[req.url.searchParams.get('format') ?? 'yaml'])); + http.post(`/api/ruler/grafana/api/v1/rules/${namespaceUID}/export`, ({ request }) => { + const url = new URL(request.url); + const format = url.searchParams.get('format') ?? 'yaml'; + return HttpResponse.text(response[format]); }) ); }, @@ -390,7 +383,7 @@ export function mockExportApi(server: SetupServer) { export function mockFolderApi(server: SetupServer) { return { folder: (folderUid: string, response: FolderDTO) => { - server.use(rest.get(`/api/folders/${folderUid}`, (_, res, ctx) => res(ctx.status(200), ctx.json(response)))); + server.use(http.get(`/api/folders/${folderUid}`, () => HttpResponse.json(response))); }, }; } @@ -398,7 +391,7 @@ export function mockFolderApi(server: SetupServer) { export function mockSearchApi(server: SetupServer) { return { search: (results: DashboardSearchItem[]) => { - server.use(rest.get(`/api/search`, (_, res, ctx) => res(ctx.status(200), ctx.json(results)))); + server.use(http.get(`/api/search`, () => HttpResponse.json(results))); }, }; } @@ -406,14 +399,10 @@ export function mockSearchApi(server: SetupServer) { export function mockDashboardApi(server: SetupServer) { return { search: (results: DashboardSearchItem[]) => { - server.use(rest.get(`/api/search`, (_, res, ctx) => res(ctx.status(200), ctx.json(results)))); + server.use(http.get(`/api/search`, () => HttpResponse.json(results))); }, dashboard: (response: DashboardDTO) => { - server.use( - rest.get(`/api/dashboards/uid/${response.dashboard.uid}`, (_, res, ctx) => - res(ctx.status(200), ctx.json(response)) - ) - ); + server.use(http.get(`/api/dashboards/uid/${response.dashboard.uid}`, () => HttpResponse.json(response))); }, }; } diff --git a/public/app/features/alerting/unified/mocks/alertRuleApi.ts b/public/app/features/alerting/unified/mocks/alertRuleApi.ts index 7eb598b37fa..d748fb8973a 100644 --- a/public/app/features/alerting/unified/mocks/alertRuleApi.ts +++ b/public/app/features/alerting/unified/mocks/alertRuleApi.ts @@ -1,4 +1,5 @@ -import { rest } from 'msw'; +import 'whatwg-fetch'; +import { http, HttpResponse } from 'msw'; import { SetupServer } from 'msw/node'; import { PromRulesResponse } from 'app/types/unified-alerting-dto'; @@ -6,9 +7,9 @@ import { PromRulesResponse } from 'app/types/unified-alerting-dto'; import { PreviewResponse, PREVIEW_URL, PROM_RULES_URL } from '../api/alertRuleApi'; export function mockPreviewApiResponse(server: SetupServer, result: PreviewResponse) { - server.use(rest.post(PREVIEW_URL, (req, res, ctx) => res(ctx.json(result)))); + server.use(http.post(PREVIEW_URL, () => HttpResponse.json(result))); } export function mockPromRulesApiResponse(server: SetupServer, result: PromRulesResponse) { - server.use(rest.get(PROM_RULES_URL, (req, res, ctx) => res(ctx.json(result)))); + server.use(http.get(PROM_RULES_URL, () => HttpResponse.json(result))); } diff --git a/public/app/features/alerting/unified/mocks/alertmanagerApi.ts b/public/app/features/alerting/unified/mocks/alertmanagerApi.ts index 492e01e74a2..1b7e98806dc 100644 --- a/public/app/features/alerting/unified/mocks/alertmanagerApi.ts +++ b/public/app/features/alerting/unified/mocks/alertmanagerApi.ts @@ -1,4 +1,5 @@ -import { rest } from 'msw'; +import 'whatwg-fetch'; +import { http, HttpResponse } from 'msw'; import { SetupServer } from 'msw/node'; import { @@ -14,7 +15,7 @@ export const defaultAlertmanagerChoiceResponse: AlertmanagersChoiceResponse = { numExternalAlertmanagers: 0, }; export function mockAlertmanagerChoiceResponse(server: SetupServer, response: AlertmanagersChoiceResponse) { - server.use(rest.get('/api/v1/ngalert', (req, res, ctx) => res(ctx.status(200), ctx.json(response)))); + server.use(http.get('/api/v1/ngalert', () => HttpResponse.json(response))); } export const emptyExternalAlertmanagersResponse: ExternalAlertmanagersResponse = { @@ -24,7 +25,7 @@ export const emptyExternalAlertmanagersResponse: ExternalAlertmanagersResponse = }, }; export function mockAlertmanagersResponse(server: SetupServer, response: ExternalAlertmanagersResponse) { - server.use(rest.get('/api/v1/ngalert/alertmanagers', (req, res, ctx) => res(ctx.status(200), ctx.json(response)))); + server.use(http.get('/api/v1/ngalert/alertmanagers', () => HttpResponse.json(response))); } export function mockAlertmanagerConfigResponse( @@ -33,8 +34,8 @@ export function mockAlertmanagerConfigResponse( response: AlertManagerCortexConfig ) { server.use( - rest.get(`/api/alertmanager/${getDatasourceAPIUid(alertManagerSourceName)}/config/api/v1/alerts`, (req, res, ctx) => - res(ctx.status(200), ctx.json(response)) + http.get(`/api/alertmanager/${getDatasourceAPIUid(alertManagerSourceName)}/config/api/v1/alerts`, () => + HttpResponse.json(response) ) ); } diff --git a/public/app/features/alerting/unified/mocks/plugins.ts b/public/app/features/alerting/unified/mocks/plugins.ts index eb8a2b5eab7..df657222de9 100644 --- a/public/app/features/alerting/unified/mocks/plugins.ts +++ b/public/app/features/alerting/unified/mocks/plugins.ts @@ -1,4 +1,5 @@ -import { rest } from 'msw'; +import 'whatwg-fetch'; +import { http, HttpResponse } from 'msw'; import { SetupServer } from 'msw/lib/node'; import { PluginMeta } from '@grafana/data'; @@ -7,8 +8,11 @@ import { SupportedPlugin } from '../types/pluginBridges'; export function mockPluginSettings(server: SetupServer, plugin: SupportedPlugin, response?: PluginMeta) { server.use( - rest.get(`/api/plugins/${plugin}/settings`, (_req, res, ctx) => { - return response ? res(ctx.status(200), ctx.json(response)) : res(ctx.status(404)); + http.get(`/api/plugins/${plugin}/settings`, () => { + if (response) { + return HttpResponse.json(response); + } + return HttpResponse.json({}, { status: 404 }); }) ); } diff --git a/public/app/features/alerting/unified/mocks/rulerApi.ts b/public/app/features/alerting/unified/mocks/rulerApi.ts index 71339a4cf72..d689d02382f 100644 --- a/public/app/features/alerting/unified/mocks/rulerApi.ts +++ b/public/app/features/alerting/unified/mocks/rulerApi.ts @@ -1,14 +1,11 @@ -import { rest } from 'msw'; +import 'whatwg-fetch'; +import { http, HttpResponse } from 'msw'; import { SetupServer } from 'msw/node'; import { RulerRuleGroupDTO, RulerRulesConfigDTO } from '../../../../types/unified-alerting-dto'; export function mockRulerRulesApiResponse(server: SetupServer, rulesSourceName: string, response: RulerRulesConfigDTO) { - server.use( - rest.get(`/api/ruler/${rulesSourceName}/api/v1/rules`, (req, res, ctx) => - res(ctx.json(response)) - ) - ); + server.use(http.get(`/api/ruler/${rulesSourceName}/api/v1/rules`, () => HttpResponse.json(response))); } export function mockRulerRulesGroupApiResponse( @@ -19,8 +16,6 @@ export function mockRulerRulesGroupApiResponse( response: RulerRuleGroupDTO ) { server.use( - rest.get(`/api/ruler/${rulesSourceName}/api/v1/rules/${namespace}/${group}`, (req, res, ctx) => - res(ctx.json(response)) - ) + http.get(`/api/ruler/${rulesSourceName}/api/v1/rules/${namespace}/${group}`, () => HttpResponse.json(response)) ); } diff --git a/public/app/features/alerting/unified/mocks/templatesApi.ts b/public/app/features/alerting/unified/mocks/templatesApi.ts index cb6d18d4cf3..d0e591fb3c5 100644 --- a/public/app/features/alerting/unified/mocks/templatesApi.ts +++ b/public/app/features/alerting/unified/mocks/templatesApi.ts @@ -1,12 +1,13 @@ -import { rest } from 'msw'; +import 'whatwg-fetch'; +import { http, HttpResponse } from 'msw'; import { SetupServer } from 'msw/node'; import { previewTemplateUrl, TemplatePreviewResponse } from '../api/templateApi'; export function mockPreviewTemplateResponse(server: SetupServer, response: TemplatePreviewResponse) { - server.use(rest.post(previewTemplateUrl, (req, res, ctx) => res(ctx.status(200), ctx.json(response)))); + server.use(http.post(previewTemplateUrl, () => HttpResponse.json(response))); } export function mockPreviewTemplateResponseRejected(server: SetupServer) { - server.use(rest.post(previewTemplateUrl, (req, res, ctx) => res(ctx.status(500), ctx.json('error')))); + server.use(http.post(previewTemplateUrl, () => HttpResponse.json('error', { status: 500 }))); } diff --git a/public/app/features/browse-dashboards/BrowseDashboardsPage.test.tsx b/public/app/features/browse-dashboards/BrowseDashboardsPage.test.tsx index bb9f53b1afb..ab005ac3d48 100644 --- a/public/app/features/browse-dashboards/BrowseDashboardsPage.test.tsx +++ b/public/app/features/browse-dashboards/BrowseDashboardsPage.test.tsx @@ -1,7 +1,7 @@ -import 'whatwg-fetch'; // fetch polyfill +import 'whatwg-fetch'; import { render as rtlRender, screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; -import { rest } from 'msw'; +import { HttpResponse, http } from 'msw'; import { setupServer, SetupServer } from 'msw/node'; import React, { ComponentProps } from 'react'; import AutoSizer from 'react-virtualized-auto-sizer'; @@ -120,25 +120,19 @@ describe('browse-dashboards BrowseDashboardsPage', () => { beforeAll(() => { server = setupServer( - rest.get('/api/folders/:uid', (_, res, ctx) => { - return res( - ctx.status(200), - ctx.json({ - title: folderA.item.title, - uid: folderA.item.uid, - }) - ); + http.get('/api/folders/:uid', () => { + return HttpResponse.json({ + title: folderA.item.title, + uid: folderA.item.uid, + }); }), - rest.get('/api/search', (_, res, ctx) => { - return res(ctx.status(200), ctx.json({})); + http.get('/api/search', () => { + return HttpResponse.json({}); }), - rest.get('/api/search/sorting', (_, res, ctx) => { - return res( - ctx.status(200), - ctx.json({ - sortOptions: [], - }) - ); + http.get('/api/search/sorting', () => { + return HttpResponse.json({ + sortOptions: [], + }); }) ); server.listen(); diff --git a/public/app/features/browse-dashboards/BrowseFolderAlertingPage.test.tsx b/public/app/features/browse-dashboards/BrowseFolderAlertingPage.test.tsx index e7f01c2a7e1..9c101f9bb54 100644 --- a/public/app/features/browse-dashboards/BrowseFolderAlertingPage.test.tsx +++ b/public/app/features/browse-dashboards/BrowseFolderAlertingPage.test.tsx @@ -1,6 +1,6 @@ -import 'whatwg-fetch'; // fetch polyfill +import 'whatwg-fetch'; import { render as rtlRender, screen } from '@testing-library/react'; -import { rest } from 'msw'; +import { http, HttpResponse } from 'msw'; import { SetupServer, setupServer } from 'msw/node'; import React from 'react'; import { TestProvider } from 'test/helpers/TestProvider'; @@ -47,20 +47,17 @@ describe('browse-dashboards BrowseFolderAlertingPage', () => { beforeAll(() => { server = setupServer( - rest.get('/api/folders/:uid', (_, res, ctx) => { - return res( - ctx.status(200), - ctx.json({ - title: mockFolderName, - uid: mockFolderUid, - }) - ); + http.get('/api/folders/:uid', () => { + return HttpResponse.json({ + title: mockFolderName, + uid: mockFolderUid, + }); }), - rest.get('api/ruler/grafana/api/v1/rules', (_, res, ctx) => { - return res(ctx.status(200), ctx.json(mockRulerRulesResponse)); + http.get('api/ruler/grafana/api/v1/rules', () => { + return HttpResponse.json(mockRulerRulesResponse); }), - rest.get('api/prometheus/grafana/api/v1/rules', (_, res, ctx) => { - return res(ctx.status(200), ctx.json(mockPrometheusRulesResponse)); + http.get('api/prometheus/grafana/api/v1/rules', () => { + return HttpResponse.json(mockPrometheusRulesResponse); }) ); server.listen(); diff --git a/public/app/features/browse-dashboards/BrowseFolderLibraryPanelsPage.test.tsx b/public/app/features/browse-dashboards/BrowseFolderLibraryPanelsPage.test.tsx index b188fd20a93..1c6632d580b 100644 --- a/public/app/features/browse-dashboards/BrowseFolderLibraryPanelsPage.test.tsx +++ b/public/app/features/browse-dashboards/BrowseFolderLibraryPanelsPage.test.tsx @@ -1,6 +1,6 @@ -import 'whatwg-fetch'; // fetch polyfill +import 'whatwg-fetch'; import { render as rtlRender, screen } from '@testing-library/react'; -import { rest } from 'msw'; +import { http, HttpResponse } from 'msw'; import { SetupServer, setupServer } from 'msw/node'; import React from 'react'; import { TestProvider } from 'test/helpers/TestProvider'; @@ -47,25 +47,19 @@ describe('browse-dashboards BrowseFolderLibraryPanelsPage', () => { beforeAll(() => { server = setupServer( - rest.get('/api/folders/:uid', (_, res, ctx) => { - return res( - ctx.status(200), - ctx.json({ - title: mockFolderName, - uid: mockFolderUid, - }) - ); + http.get('/api/folders/:uid', () => { + return HttpResponse.json({ + title: mockFolderName, + uid: mockFolderUid, + }); }), - rest.get('/api/library-elements', (_, res, ctx) => { - return res( - ctx.status(200), - ctx.json({ - result: mockLibraryElementsResponse, - }) - ); + http.get('/api/library-elements', () => { + return HttpResponse.json({ + result: mockLibraryElementsResponse, + }); }), - rest.get('/api/search/sorting', (_, res, ctx) => { - return res(ctx.status(200), ctx.json({})); + http.get('/api/search/sorting', () => { + return HttpResponse.json({}); }) ); server.listen(); diff --git a/public/app/features/dashboard/components/ShareModal/SharePublicDashboard/SharePublicDashboard.test.tsx b/public/app/features/dashboard/components/ShareModal/SharePublicDashboard/SharePublicDashboard.test.tsx index e5d26f503a8..56970d1487f 100644 --- a/public/app/features/dashboard/components/ShareModal/SharePublicDashboard/SharePublicDashboard.test.tsx +++ b/public/app/features/dashboard/components/ShareModal/SharePublicDashboard/SharePublicDashboard.test.tsx @@ -1,9 +1,9 @@ +import 'whatwg-fetch'; import { screen, waitFor } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; -import { rest } from 'msw'; +import { http, HttpResponse } from 'msw'; import { setupServer } from 'msw/node'; -import 'whatwg-fetch'; import { BootData, DataQuery } from '@grafana/data/src'; import { selectors as e2eSelectors } from '@grafana/e2e-selectors/src'; import { reportInteraction, setEchoSrv } from '@grafana/runtime'; @@ -87,20 +87,27 @@ afterEach(() => { }); const getNonExistentPublicDashboardResponse = () => - rest.get('/api/dashboards/uid/:dashboardUid/public-dashboards', (req, res, ctx) => { - return res( - ctx.status(404), - ctx.json({ + http.get('/api/dashboards/uid/:dashboardUid/public-dashboards', () => { + return HttpResponse.json( + { message: 'Public dashboard not found', messageId: 'publicdashboards.notFound', statusCode: 404, traceID: '', - }) + }, + { + status: 404, + } ); }); const getErrorPublicDashboardResponse = () => - rest.get('/api/dashboards/uid/:dashboardUid/public-dashboards', (req, res, ctx) => { - return res(ctx.status(500)); + http.get('/api/dashboards/uid/:dashboardUid/public-dashboards', () => { + return HttpResponse.json( + {}, + { + status: 500, + } + ); }); const alertTests = () => { @@ -277,14 +284,11 @@ describe('SharePublic - Already persisted', () => { }); it('when modal is opened, then time range switch is enabled and not checked when its not checked in the db', async () => { server.use( - rest.get('/api/dashboards/uid/:dashboardUid/public-dashboards', (req, res, ctx) => { - return res( - ctx.status(200), - ctx.json({ - ...pubdashResponse, - timeSelectionEnabled: false, - }) - ); + http.get('/api/dashboards/uid/:dashboardUid/public-dashboards', () => { + return HttpResponse.json({ + ...pubdashResponse, + timeSelectionEnabled: false, + }); }) ); @@ -303,17 +307,16 @@ describe('SharePublic - Already persisted', () => { }); it('when pubdash is disabled in the db, then link url is not copyable and switch is checked', async () => { server.use( - rest.get('/api/dashboards/uid/:dashboardUid/public-dashboards', (req, res, ctx) => { - return res( - ctx.status(200), - ctx.json({ - isEnabled: false, - annotationsEnabled: false, - uid: 'a-uid', - dashboardUid: req.params.dashboardUid, - accessToken: 'an-access-token', - }) - ); + http.get('/api/dashboards/uid/:dashboardUid/public-dashboards', ({ request }) => { + const url = new URL(request.url); + const dashboardUid = url.searchParams.get('dashboardUid'); + return HttpResponse.json({ + isEnabled: false, + annotationsEnabled: false, + uid: 'a-uid', + dashboardUid, + accessToken: 'an-access-token', + }); }) ); @@ -339,15 +342,14 @@ describe('SharePublic - Report interactions', () => { jest.clearAllMocks(); server.use(getExistentPublicDashboardResponse()); server.use( - rest.patch('/api/dashboards/uid/:dashboardUid/public-dashboards/:uid', (req, res, ctx) => - res( - ctx.status(200), - ctx.json({ - ...pubdashResponse, - dashboardUid: req.params.dashboardUid, - }) - ) - ) + http.patch('/api/dashboards/uid/:dashboardUid/public-dashboards/:uid', ({ request }) => { + const url = new URL(request.url); + const dashboardUid = url.searchParams.get('dashboardUid'); + return HttpResponse.json({ + ...pubdashResponse, + dashboardUid, + }); + }) ); }); diff --git a/public/app/features/dashboard/components/ShareModal/SharePublicDashboard/utilsTest.tsx b/public/app/features/dashboard/components/ShareModal/SharePublicDashboard/utilsTest.tsx index 3d2bc135502..382c499e3a5 100644 --- a/public/app/features/dashboard/components/ShareModal/SharePublicDashboard/utilsTest.tsx +++ b/public/app/features/dashboard/components/ShareModal/SharePublicDashboard/utilsTest.tsx @@ -1,5 +1,6 @@ +import 'whatwg-fetch'; import { fireEvent, render, screen, waitFor, waitForElementToBeRemoved } from '@testing-library/react'; -import { rest } from 'msw'; +import { http, HttpResponse } from 'msw'; import React from 'react'; import { Provider } from 'react-redux'; @@ -32,15 +33,14 @@ export const pubdashResponse: sharePublicDashboardUtils.PublicDashboard = { }; export const getExistentPublicDashboardResponse = (publicDashboard?: Partial) => - rest.get('/api/dashboards/uid/:dashboardUid/public-dashboards', (req, res, ctx) => { - return res( - ctx.status(200), - ctx.json({ - ...pubdashResponse, - ...publicDashboard, - dashboardUid: req.params.dashboardUid, - }) - ); + http.get('/api/dashboards/uid/:dashboardUid/public-dashboards', ({ request }) => { + const url = new URL(request.url); + const dashboardUid = url.searchParams.get('dashboardUid'); + return HttpResponse.json({ + ...pubdashResponse, + ...publicDashboard, + dashboardUid, + }); }); export const renderSharePublicDashboard = async ( diff --git a/public/app/features/manage-dashboards/components/PublicDashboardListTable/PublicDashboardListTable.test.tsx b/public/app/features/manage-dashboards/components/PublicDashboardListTable/PublicDashboardListTable.test.tsx index 5c69c16bc2c..f98ecb38cda 100644 --- a/public/app/features/manage-dashboards/components/PublicDashboardListTable/PublicDashboardListTable.test.tsx +++ b/public/app/features/manage-dashboards/components/PublicDashboardListTable/PublicDashboardListTable.test.tsx @@ -1,8 +1,8 @@ +import 'whatwg-fetch'; import { render, screen, waitForElementToBeRemoved, within } from '@testing-library/react'; -import { rest } from 'msw'; +import { http, HttpResponse } from 'msw'; import { setupServer } from 'msw/node'; import React from 'react'; -import 'whatwg-fetch'; import { BrowserRouter } from 'react-router-dom'; import { TestProvider } from 'test/helpers/TestProvider'; import { getGrafanaContextMock } from 'test/mocks/getGrafanaContextMock'; @@ -60,10 +60,13 @@ const paginationResponse: Omit - res(ctx.status(200), ctx.json({ ...paginationResponse, publicDashboards: publicDashboardListResponse })) + http.get('/api/dashboards/public-dashboards', () => + HttpResponse.json({ + ...paginationResponse, + publicDashboards: publicDashboardListResponse, + }) ), - rest.delete('/api/dashboards/uid/:dashboardUid/public-dashboards/:uid', (_, res, ctx) => res(ctx.status(200))) + http.delete('/api/dashboards/uid/:dashboardUid/public-dashboards/:uid', () => HttpResponse.json({})) ); jest.mock('@grafana/runtime', () => ({ @@ -122,8 +125,8 @@ describe('Show table', () => { }; server.use( - rest.get('/api/dashboards/public-dashboards', (req, res, ctx) => { - return res(ctx.status(200), ctx.json(emptyListRS)); + http.get('/api/dashboards/public-dashboards', () => { + return HttpResponse.json(emptyListRS); }) ); @@ -171,8 +174,8 @@ describe('Orphaned public dashboard', () => { publicDashboards: [...publicDashboardListResponse, ...orphanedDashboardListResponse], }; server.use( - rest.get('/api/dashboards/public-dashboards', (req, res, ctx) => { - return res(ctx.status(200), ctx.json(response)); + http.get('/api/dashboards/public-dashboards', () => { + return HttpResponse.json(response); }) ); jest.spyOn(contextSrv, 'hasPermission').mockReturnValue(true); diff --git a/public/app/features/plugins/loader/pluginLoader.mock.ts b/public/app/features/plugins/loader/pluginLoader.mock.ts index 530b245a592..c683090ad6c 100644 --- a/public/app/features/plugins/loader/pluginLoader.mock.ts +++ b/public/app/features/plugins/loader/pluginLoader.mock.ts @@ -1,4 +1,5 @@ -import { rest } from 'msw'; +import 'whatwg-fetch'; +import { http, HttpResponse } from 'msw'; import { setupServer } from 'msw/node'; export const mockSystemModule = `System.register(['./dependencyA'], function (_export, _context) { @@ -85,38 +86,104 @@ export const mockModuleWithDefineMethod = `ace.define(function() { });`; const server = setupServer( - rest.get('/public/plugins/mockAmdModule/module.js', async (_req, res, ctx) => - res(ctx.status(200), ctx.set('Content-Type', 'text/javascript'), ctx.body(mockAmdModule)) + http.get( + '/public/plugins/mockAmdModule/module.js', + () => + new HttpResponse(mockAmdModule, { + headers: { + 'Content-Type': 'text/javascript', + }, + }) ), - rest.get('/public/plugins/mockSystemModule/module.js', async (_req, res, ctx) => - res(ctx.status(200), ctx.set('Content-Type', 'text/javascript'), ctx.body(mockSystemModule)) + http.get( + '/public/plugins/mockSystemModule/module.js', + () => + new HttpResponse(mockSystemModule, { + headers: { + 'Content-Type': 'text/javascript', + }, + }) ), - rest.get('http://my-cdn.com/plugins/my-plugin/v1.0.0/public/plugins/my-plugin/module.js', async (_req, res, ctx) => - res(ctx.status(200), ctx.set('Content-Type', 'text/javascript'), ctx.body(mockAmdModule)) + http.get( + 'http://my-cdn.com/plugins/my-plugin/v1.0.0/public/plugins/my-plugin/module.js', + () => + new HttpResponse(mockAmdModule, { + headers: { + 'Content-Type': 'text/javascript', + }, + }) ), - rest.get('/public/plugins/mockAmdModuleNamedNoDeps/module.js', async (_req, res, ctx) => - res(ctx.status(200), ctx.set('Content-Type', 'text/javascript'), ctx.body(mockAmdModuleNamedNoDeps)) + http.get( + '/public/plugins/mockAmdModuleNamedNoDeps/module.js', + () => + new HttpResponse(mockAmdModuleNamedNoDeps, { + headers: { + 'Content-Type': 'text/javascript', + }, + }) ), - rest.get('/public/plugins/mockAmdModuleNamedWithDeps/module.js', async (_req, res, ctx) => - res(ctx.status(200), ctx.set('Content-Type', 'text/javascript'), ctx.body(mockAmdModuleNamedWithDeps)) + http.get( + '/public/plugins/mockAmdModuleNamedWithDeps/module.js', + () => + new HttpResponse(mockAmdModuleNamedWithDeps, { + headers: { + 'Content-Type': 'text/javascript', + }, + }) ), - rest.get('/public/plugins/mockAmdModuleNamedWithDeps2/module.js', async (_req, res, ctx) => - res(ctx.status(200), ctx.set('Content-Type', 'text/javascript'), ctx.body(mockAmdModuleNamedWithDeps2)) + http.get( + '/public/plugins/mockAmdModuleNamedWithDeps2/module.js', + () => + new HttpResponse(mockAmdModuleNamedWithDeps2, { + headers: { + 'Content-Type': 'text/javascript', + }, + }) ), - rest.get('/public/plugins/mockAmdModuleNamedWithDeps3/module.js', async (_req, res, ctx) => - res(ctx.status(200), ctx.set('Content-Type', 'text/javascript'), ctx.body(mockAmdModuleNamedWithDeps3)) + http.get( + '/public/plugins/mockAmdModuleNamedWithDeps3/module.js', + () => + new HttpResponse(mockAmdModuleNamedWithDeps3, { + headers: { + 'Content-Type': 'text/javascript', + }, + }) ), - rest.get('/public/plugins/mockAmdModuleOnlyFunction/module.js', async (_req, res, ctx) => - res(ctx.status(200), ctx.set('Content-Type', 'text/javascript'), ctx.body(mockAmdModuleOnlyFunction)) + http.get( + '/public/plugins/mockAmdModuleOnlyFunction/module.js', + () => + new HttpResponse(mockAmdModuleOnlyFunction, { + headers: { + 'Content-Type': 'text/javascript', + }, + }) ), - rest.get('/public/plugins/mockAmdModuleWithComments/module.js', async (_req, res, ctx) => - res(ctx.status(200), ctx.set('Content-Type', 'text/javascript'), ctx.body(mockAmdModuleWithComments)) + http.get( + '/public/plugins/mockAmdModuleWithComments/module.js', + () => + new HttpResponse(mockAmdModuleWithComments, { + headers: { + 'Content-Type': 'text/javascript', + }, + }) ), - rest.get('/public/plugins/mockAmdModuleWithComments2/module.js', async (_req, res, ctx) => - res(ctx.status(200), ctx.set('Content-Type', 'text/javascript'), ctx.body(mockAmdModuleWithComments2)) + http.get( + '/public/plugins/mockAmdModuleWithComments2/module.js', + () => + new HttpResponse(mockAmdModuleWithComments2, { + headers: { + 'Content-Type': 'text/javascript', + }, + }) ), - rest.get('/public/plugins/mockModuleWithDefineMethod/module.js', async (_req, res, ctx) => - res(ctx.status(200), ctx.set('Content-Type', 'text/javascript'), ctx.body(mockModuleWithDefineMethod)) + http.get( + '/public/plugins/mockModuleWithDefineMethod/module.js', + () => + new HttpResponse(mockModuleWithDefineMethod, { + headers: { + 'Content-Type': 'text/javascript', + }, + }) ) ); diff --git a/public/app/features/plugins/loader/systemjsHooks.test.ts b/public/app/features/plugins/loader/systemjsHooks.test.ts index 08d33e2c644..9cd499b0c04 100644 --- a/public/app/features/plugins/loader/systemjsHooks.test.ts +++ b/public/app/features/plugins/loader/systemjsHooks.test.ts @@ -28,11 +28,13 @@ describe('SystemJS Loader Hooks', () => { const originalFetch = systemJSPrototype.fetch; const originalResolve = systemJSPrototype.resolve; - systemJSPrototype.resolve = (moduleId: string) => moduleId; - systemJSPrototype.shouldFetch = () => true; - beforeAll(() => { server.listen(); + systemJSPrototype.resolve = (moduleId: string) => moduleId; + systemJSPrototype.shouldFetch = () => true; + // because server.listen() patches fetch, we need to reassign this to the systemJSPrototype + // this is identical to what happens in the original code: https://github.com/systemjs/systemjs/blob/main/src/features/fetch-load.js#L12 + systemJSPrototype.fetch = window.fetch; }); afterEach(() => server.resetHandlers()); afterAll(() => { @@ -43,7 +45,11 @@ describe('SystemJS Loader Hooks', () => { describe('decorateSystemJSFetch', () => { it('wraps AMD modules in an AMD iife', async () => { - const basicResult = await decorateSystemJSFetch(originalFetch, '/public/plugins/mockAmdModule/module.js', {}); + const basicResult = await decorateSystemJSFetch( + systemJSPrototype.fetch, + '/public/plugins/mockAmdModule/module.js', + {} + ); const basicSource = await basicResult.text(); const basicExpected = `(function(define) { ${mockAmdModule} @@ -51,7 +57,7 @@ describe('SystemJS Loader Hooks', () => { expect(basicSource).toBe(basicExpected); const mockAmdModuleNamedNoDepsResult = await decorateSystemJSFetch( - originalFetch, + systemJSPrototype.fetch, '/public/plugins/mockAmdModuleNamedNoDeps/module.js', {} ); @@ -63,7 +69,7 @@ describe('SystemJS Loader Hooks', () => { expect(mockAmdModuleNamedNoDepsSource).toBe(mockAmdModuleNamedNoDepsExpected); const mockAmdModuleNamedWithDepsResult = await decorateSystemJSFetch( - originalFetch, + systemJSPrototype.fetch, '/public/plugins/mockAmdModuleNamedWithDeps/module.js', {} ); @@ -75,7 +81,7 @@ describe('SystemJS Loader Hooks', () => { expect(mockAmdModuleNamedWithDepsSource).toBe(mockAmdModuleNamedWithDepsExpected); const mockAmdModuleNamedWithDeps2Result = await decorateSystemJSFetch( - originalFetch, + systemJSPrototype.fetch, '/public/plugins/mockAmdModuleNamedWithDeps2/module.js', {} ); @@ -87,7 +93,7 @@ describe('SystemJS Loader Hooks', () => { expect(mockAmdModuleNamedWithDeps2Source).toBe(mockAmdModuleNamedWithDeps2Expected); const mockAmdModuleNamedWithDeps3Result = await decorateSystemJSFetch( - originalFetch, + systemJSPrototype.fetch, '/public/plugins/mockAmdModuleNamedWithDeps3/module.js', {} ); @@ -99,7 +105,7 @@ describe('SystemJS Loader Hooks', () => { expect(mockAmdModuleNamedWithDeps3Source).toBe(mockAmdModuleNamedWithDeps3Expected); const mockAmdModuleOnlyFunctionResult = await decorateSystemJSFetch( - originalFetch, + systemJSPrototype.fetch, '/public/plugins/mockAmdModuleOnlyFunction/module.js', {} ); @@ -111,7 +117,7 @@ describe('SystemJS Loader Hooks', () => { expect(mockAmdModuleOnlyFunctionSource).toBe(mockAmdModuleOnlyFunctionExpected); const mockAmdModuleWithCommentsResult = await decorateSystemJSFetch( - originalFetch, + systemJSPrototype.fetch, '/public/plugins/mockAmdModuleWithComments/module.js', {} ); @@ -123,7 +129,7 @@ describe('SystemJS Loader Hooks', () => { expect(mockAmdModuleWithCommentsSource).toBe(mockAmdModuleWithCommentsExpected); const mockAmdModuleWithComments2Result = await decorateSystemJSFetch( - originalFetch, + systemJSPrototype.fetch, '/public/plugins/mockAmdModuleWithComments2/module.js', {} ); @@ -136,14 +142,14 @@ describe('SystemJS Loader Hooks', () => { }); it("doesn't wrap system modules in an AMD iife", async () => { const url = '/public/plugins/mockSystemModule/module.js'; - const result = await decorateSystemJSFetch(originalFetch, url, {}); + const result = await decorateSystemJSFetch(systemJSPrototype.fetch, url, {}); const source = await result.text(); expect(source).toBe(mockSystemModule); }); it("doesn't wrap modules with a define method in an AMD iife", async () => { const url = '/public/plugins/mockModuleWithDefineMethod/module.js'; - const result = await decorateSystemJSFetch(originalFetch, url, {}); + const result = await decorateSystemJSFetch(systemJSPrototype.fetch, url, {}); const source = await result.text(); expect(source).toBe(mockModuleWithDefineMethod); @@ -151,13 +157,13 @@ describe('SystemJS Loader Hooks', () => { it('only transforms plugin source code hosted on cdn with cdn paths', async () => { config.pluginsCDNBaseURL = 'http://my-cdn.com/plugins'; const cdnUrl = 'http://my-cdn.com/plugins/my-plugin/v1.0.0/public/plugins/my-plugin/module.js'; - const cdnResult = await decorateSystemJSFetch(originalFetch, cdnUrl, {}); + const cdnResult = await decorateSystemJSFetch(systemJSPrototype.fetch, cdnUrl, {}); const cdnSource = await cdnResult.text(); expect(cdnSource).toContain('var pluginPath = "http://my-cdn.com/plugins/my-plugin/v1.0.0/public/plugins/";'); const url = '/public/plugins/mockAmdModule/module.js'; - const result = await decorateSystemJSFetch(originalFetch, url, {}); + const result = await decorateSystemJSFetch(systemJSPrototype.fetch, url, {}); const source = await result.text(); expect(source).toContain('var pluginPath = "/public/plugins/";'); }); diff --git a/public/test/jest-resolver.js b/public/test/jest-resolver.js index 75b29ad00dc..40046b872d5 100644 --- a/public/test/jest-resolver.js +++ b/public/test/jest-resolver.js @@ -27,6 +27,23 @@ module.exports = (path, options) => { delete pkg['exports']; delete pkg['module']; } + // Jest + jsdom acts like a browser (i.e., it looks for "browser" imports + // under pkg.exports), but msw knows that you're operating in a Node + // environment: + // + // https://github.com/mswjs/msw/issues/1786#issuecomment-1782559851 + // + // The MSW project's recommended workaround is to disable Jest's + // customExportConditions completely, so no packages use their browser's + // versions. We'll instead clear export conditions only for MSW. + // + // Taken from https://github.com/mswjs/msw/issues/1786#issuecomment-1787730599 + if (pkg.name === 'msw') { + delete pkg.exports['./node'].browser; + } + if (pkg.name === '@mswjs/interceptors') { + delete pkg.exports; + } return pkg; }, }); diff --git a/yarn.lock b/yarn.lock index a3bfcbd3626..01192c34e23 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1865,6 +1865,24 @@ __metadata: languageName: node linkType: hard +"@bundled-es-modules/cookie@npm:^2.0.0": + version: 2.0.0 + resolution: "@bundled-es-modules/cookie@npm:2.0.0" + dependencies: + cookie: "npm:^0.5.0" + checksum: 10/c8ef02aa5d3f6c786cfa407e1c93b4af29c600eb09990973f47a7a49e4771c1bec37c8f8e567638bb9cbc41f4e38d065ff1d8eaf9bf91f0c3613a6d60bc82c8c + languageName: node + linkType: hard + +"@bundled-es-modules/statuses@npm:^1.0.1": + version: 1.0.1 + resolution: "@bundled-es-modules/statuses@npm:1.0.1" + dependencies: + statuses: "npm:^2.0.1" + checksum: 10/9bf6a2bcf040a66fb805da0e1446041fd9def7468bb5da29c5ce02adf121a3f7cec123664308059a62a46fcaee666add83094b76df6dce72e5cafa8e6bebe60d + languageName: node + linkType: hard + "@colors/colors@npm:1.5.0": version: 1.5.0 resolution: "@colors/colors@npm:1.5.0" @@ -4298,6 +4316,45 @@ __metadata: languageName: node linkType: hard +"@inquirer/confirm@npm:^3.0.0": + version: 3.0.0 + resolution: "@inquirer/confirm@npm:3.0.0" + dependencies: + "@inquirer/core": "npm:^7.0.0" + "@inquirer/type": "npm:^1.2.0" + checksum: 10/ed16dc0e5b22115474853ca57dbe3dacdcd15bcb37cc50020e8e76ff8d0875d62d8b63b93b3092c653faeb6c83a139eac997ff05638b0f1f78ae919f29ee29d4 + languageName: node + linkType: hard + +"@inquirer/core@npm:^7.0.0": + version: 7.0.0 + resolution: "@inquirer/core@npm:7.0.0" + dependencies: + "@inquirer/type": "npm:^1.2.0" + "@types/mute-stream": "npm:^0.0.4" + "@types/node": "npm:^20.11.16" + "@types/wrap-ansi": "npm:^3.0.0" + ansi-escapes: "npm:^4.3.2" + chalk: "npm:^4.1.2" + cli-spinners: "npm:^2.9.2" + cli-width: "npm:^4.1.0" + figures: "npm:^3.2.0" + mute-stream: "npm:^1.0.0" + run-async: "npm:^3.0.0" + signal-exit: "npm:^4.1.0" + strip-ansi: "npm:^6.0.1" + wrap-ansi: "npm:^6.2.0" + checksum: 10/78c0ef4bb82cb7be23f16a80c9cff02839c77e378d272327f49878788a4c3b1cc00137387317053d242a87634954850a4d2546b3e48b1abd27130a21f598afef + languageName: node + linkType: hard + +"@inquirer/type@npm:^1.2.0": + version: 1.2.0 + resolution: "@inquirer/type@npm:1.2.0" + checksum: 10/12f68a16d8995efb409bd243d6ccc501b366e8009630a075071a9d9497cebd36bbd6c46d7d59b37435629e5e50236394679f414f7676b68b913ecc28a85cba0a + languageName: node + linkType: hard + "@internationalized/date@npm:^3.5.1": version: 3.5.1 resolution: "@internationalized/date@npm:3.5.1" @@ -5134,6 +5191,13 @@ __metadata: languageName: node linkType: hard +"@mswjs/cookies@npm:^1.1.0": + version: 1.1.0 + resolution: "@mswjs/cookies@npm:1.1.0" + checksum: 10/168ed1966e579a4f454e6d2af5a015150cca570ac4c660f5b656e7bc021afacbf0b3d4ed3d03e9293550f3965c28ce1e293fa7037c6cf46ed7e268e21a1053a4 + languageName: node + linkType: hard + "@mswjs/interceptors@npm:^0.17.10": version: 0.17.10 resolution: "@mswjs/interceptors@npm:0.17.10" @@ -5150,6 +5214,20 @@ __metadata: languageName: node linkType: hard +"@mswjs/interceptors@npm:^0.25.16": + version: 0.25.16 + resolution: "@mswjs/interceptors@npm:0.25.16" + dependencies: + "@open-draft/deferred-promise": "npm:^2.2.0" + "@open-draft/logger": "npm:^0.3.0" + "@open-draft/until": "npm:^2.0.0" + is-node-process: "npm:^1.2.0" + outvariant: "npm:^1.2.1" + strict-event-emitter: "npm:^0.5.1" + checksum: 10/d8fb74db45a63971e9da7367c8d120343c8f49fec7bcc3f0c77c04c3f628d307b70875f52e4a99df561547b92d0d53edacc421e42d69940d44999254b5d028b5 + languageName: node + linkType: hard + "@ndelangen/get-tarball@npm:^3.0.7": version: 3.0.7 resolution: "@ndelangen/get-tarball@npm:3.0.7" @@ -5588,6 +5666,23 @@ __metadata: languageName: node linkType: hard +"@open-draft/deferred-promise@npm:^2.2.0": + version: 2.2.0 + resolution: "@open-draft/deferred-promise@npm:2.2.0" + checksum: 10/bc3bb1668a555bb87b33383cafcf207d9561e17d2ca0d9e61b7ce88e82b66e36a333d3676c1d39eb5848022c03c8145331fcdc828ba297f88cb1de9c5cef6c19 + languageName: node + linkType: hard + +"@open-draft/logger@npm:^0.3.0": + version: 0.3.0 + resolution: "@open-draft/logger@npm:0.3.0" + dependencies: + is-node-process: "npm:^1.2.0" + outvariant: "npm:^1.4.0" + checksum: 10/7a280f170bcd4e91d3eedbefe628efd10c3bd06dd2461d06a7fdbced89ef457a38785847f88cc630fb4fd7dfa176d6f77aed17e5a9b08000baff647433b5ff78 + languageName: node + linkType: hard + "@open-draft/until@npm:^1.0.3": version: 1.0.3 resolution: "@open-draft/until@npm:1.0.3" @@ -5595,6 +5690,13 @@ __metadata: languageName: node linkType: hard +"@open-draft/until@npm:^2.0.0, @open-draft/until@npm:^2.1.0": + version: 2.1.0 + resolution: "@open-draft/until@npm:2.1.0" + checksum: 10/622be42950afc8e89715d0fd6d56cbdcd13e36625e23b174bd3d9f06f80e25f9adf75d6698af93bca1e1bf465b9ce00ec05214a12189b671fb9da0f58215b6f4 + languageName: node + linkType: hard + "@opentelemetry/api-logs@npm:0.45.1": version: 0.45.1 resolution: "@opentelemetry/api-logs@npm:0.45.1" @@ -8581,6 +8683,13 @@ __metadata: languageName: node linkType: hard +"@types/cookie@npm:^0.6.0": + version: 0.6.0 + resolution: "@types/cookie@npm:0.6.0" + checksum: 10/b883348d5bf88695fbc2c2276b1c49859267a55cae3cf11ea1dccc1b3be15b466e637ce3242109ba27d616c77c6aa4efe521e3d557110b4fdd9bc332a12445c2 + languageName: node + linkType: hard + "@types/cross-spawn@npm:^6.0.2": version: 6.0.3 resolution: "@types/cross-spawn@npm:6.0.3" @@ -9363,6 +9472,15 @@ __metadata: languageName: node linkType: hard +"@types/mute-stream@npm:^0.0.4": + version: 0.0.4 + resolution: "@types/mute-stream@npm:0.0.4" + dependencies: + "@types/node": "npm:*" + checksum: 10/af8d83ad7b68ea05d9357985daf81b6c9b73af4feacb2f5c2693c7fd3e13e5135ef1bd083ce8d5bdc8e97acd28563b61bb32dec4e4508a8067fcd31b8a098632 + languageName: node + linkType: hard + "@types/node-fetch@npm:^2.6.4": version: 2.6.4 resolution: "@types/node-fetch@npm:2.6.4" @@ -9382,7 +9500,7 @@ __metadata: languageName: node linkType: hard -"@types/node@npm:*, @types/node@npm:20.11.17, @types/node@npm:>=13.7.0": +"@types/node@npm:*, @types/node@npm:20.11.17, @types/node@npm:>=13.7.0, @types/node@npm:^20.11.16": version: 20.11.17 resolution: "@types/node@npm:20.11.17" dependencies: @@ -9808,6 +9926,13 @@ __metadata: languageName: node linkType: hard +"@types/statuses@npm:^2.0.4": + version: 2.0.4 + resolution: "@types/statuses@npm:2.0.4" + checksum: 10/3a806c3b96d1845e3e7441fbf0839037e95f717334760ddb7c29223c9a34a7206b68e2998631f89f1a1e3ef5b67b15652f6e8fa14987ebd7f6d38587c1bffd18 + languageName: node + linkType: hard + "@types/string-hash@npm:1.1.3": version: 1.1.3 resolution: "@types/string-hash@npm:1.1.3" @@ -9912,6 +10037,13 @@ __metadata: languageName: node linkType: hard +"@types/wrap-ansi@npm:^3.0.0": + version: 3.0.0 + resolution: "@types/wrap-ansi@npm:3.0.0" + checksum: 10/8aa644946ca4e859668c36b8e2bcf2ac4bdee59dac760414730ea57be8a93ae9166ebd40a088f2ab714843aaea2a2a67f0e6e6ec11cfc9c8701b2466ca1c4089 + languageName: node + linkType: hard + "@types/ws@npm:^8.5.5": version: 8.5.5 resolution: "@types/ws@npm:8.5.5" @@ -11114,7 +11246,7 @@ __metadata: languageName: node linkType: hard -"ansi-escapes@npm:^4.2.1, ansi-escapes@npm:^4.3.0": +"ansi-escapes@npm:^4.2.1, ansi-escapes@npm:^4.3.0, ansi-escapes@npm:^4.3.2": version: 4.3.2 resolution: "ansi-escapes@npm:4.3.2" dependencies: @@ -12814,6 +12946,13 @@ __metadata: languageName: node linkType: hard +"cli-spinners@npm:^2.9.2": + version: 2.9.2 + resolution: "cli-spinners@npm:2.9.2" + checksum: 10/a0a863f442df35ed7294424f5491fa1756bd8d2e4ff0c8736531d886cec0ece4d85e8663b77a5afaf1d296e3cbbebff92e2e99f52bbea89b667cbe789b994794 + languageName: node + linkType: hard + "cli-table3@npm:^0.6.1, cli-table3@npm:~0.6.1": version: 0.6.3 resolution: "cli-table3@npm:0.6.3" @@ -12844,6 +12983,13 @@ __metadata: languageName: node linkType: hard +"cli-width@npm:^4.1.0": + version: 4.1.0 + resolution: "cli-width@npm:4.1.0" + checksum: 10/b58876fbf0310a8a35c79b72ecfcf579b354e18ad04e6b20588724ea2b522799a758507a37dfe132fafaf93a9922cafd9514d9e1598e6b2cd46694853aed099f + languageName: node + linkType: hard + "cliui@npm:^7.0.2": version: 7.0.4 resolution: "cliui@npm:7.0.4" @@ -13421,6 +13567,13 @@ __metadata: languageName: node linkType: hard +"cookie@npm:^0.5.0": + version: 0.5.0 + resolution: "cookie@npm:0.5.0" + checksum: 10/aae7911ddc5f444a9025fbd979ad1b5d60191011339bce48e555cb83343d0f98b865ff5c4d71fecdfb8555a5cafdc65632f6fce172f32aaf6936830a883a0380 + languageName: node + linkType: hard + "copy-to-clipboard@npm:^3.3.1": version: 3.3.1 resolution: "copy-to-clipboard@npm:3.3.1" @@ -18231,7 +18384,7 @@ __metadata: mousetrap: "npm:1.6.5" mousetrap-global-bind: "npm:1.1.0" moveable: "npm:0.53.0" - msw: "npm:1.3.2" + msw: "npm:2.2.0" mutationobserver-shim: "npm:0.3.7" nanoid: "npm:^5.0.4" ngtemplate-loader: "npm:2.1.0" @@ -18564,6 +18717,13 @@ __metadata: languageName: node linkType: hard +"headers-polyfill@npm:^4.0.2": + version: 4.0.2 + resolution: "headers-polyfill@npm:4.0.2" + checksum: 10/70b53abf48a1d50760150624d6c7ca974a0d286ba102e411538f6dad6687ce51ce7cc60197e326df96f844548d6ff77d900e28c3cdbc0ba1fe09a05eae47156a + languageName: node + linkType: hard + "heimdalljs-logger@npm:^0.1.10, heimdalljs-logger@npm:^0.1.7": version: 0.1.10 resolution: "heimdalljs-logger@npm:0.1.10" @@ -22717,6 +22877,38 @@ __metadata: languageName: node linkType: hard +"msw@npm:2.2.0": + version: 2.2.0 + resolution: "msw@npm:2.2.0" + dependencies: + "@bundled-es-modules/cookie": "npm:^2.0.0" + "@bundled-es-modules/statuses": "npm:^1.0.1" + "@inquirer/confirm": "npm:^3.0.0" + "@mswjs/cookies": "npm:^1.1.0" + "@mswjs/interceptors": "npm:^0.25.16" + "@open-draft/until": "npm:^2.1.0" + "@types/cookie": "npm:^0.6.0" + "@types/statuses": "npm:^2.0.4" + chalk: "npm:^4.1.2" + graphql: "npm:^16.8.1" + headers-polyfill: "npm:^4.0.2" + is-node-process: "npm:^1.2.0" + outvariant: "npm:^1.4.2" + path-to-regexp: "npm:^6.2.0" + strict-event-emitter: "npm:^0.5.1" + type-fest: "npm:^4.9.0" + yargs: "npm:^17.7.2" + peerDependencies: + typescript: ">= 4.7.x <= 5.3.x" + peerDependenciesMeta: + typescript: + optional: true + bin: + msw: cli/index.js + checksum: 10/36e6a1f0bc89d1c84bf24c1cf7ca7c3fe5d5b032c825d52a832e9b815830976a86c17a8c3f1f506db720f44e99d04c9302e014cf569b51b2d2af62562a9fe62a + languageName: node + linkType: hard + "multicast-dns@npm:^7.2.4": version: 7.2.4 resolution: "multicast-dns@npm:7.2.4" @@ -22756,7 +22948,7 @@ __metadata: languageName: node linkType: hard -"mute-stream@npm:~1.0.0": +"mute-stream@npm:^1.0.0, mute-stream@npm:~1.0.0": version: 1.0.0 resolution: "mute-stream@npm:1.0.0" checksum: 10/36fc968b0e9c9c63029d4f9dc63911950a3bdf55c9a87f58d3a266289b67180201cade911e7699f8b2fa596b34c9db43dad37649e3f7fdd13c3bb9edb0017ee7 @@ -23607,10 +23799,10 @@ __metadata: languageName: node linkType: hard -"outvariant@npm:^1.2.1, outvariant@npm:^1.4.0": - version: 1.4.0 - resolution: "outvariant@npm:1.4.0" - checksum: 10/07b9bcb9b3a2ff1b3db02af6b07d70e663082b30ddc08ff475d7c85fc623fdcc4433a4ab5b88f6902b62dbb284eef1be386aa537e14cef0519fad887ec483054 +"outvariant@npm:^1.2.1, outvariant@npm:^1.4.0, outvariant@npm:^1.4.2": + version: 1.4.2 + resolution: "outvariant@npm:1.4.2" + checksum: 10/f16ba035fb65d1cbe7d2e06693dd42183c46bc8456713d9ddb5182d067defa7d78217edab0a2d3e173d3bacd627b2bd692195c7087c225b82548fbf52c677b38 languageName: node linkType: hard @@ -27278,6 +27470,13 @@ __metadata: languageName: node linkType: hard +"run-async@npm:^3.0.0": + version: 3.0.0 + resolution: "run-async@npm:3.0.0" + checksum: 10/97fb8747f7765b77ebcd311d3a33548099336f04c6434e0763039b98c1de0f1b4421000695aff8751f309c0b995d8dfd620c1f1e4c35572da38c101488165305 + languageName: node + linkType: hard + "run-parallel@npm:^1.1.9": version: 1.2.0 resolution: "run-parallel@npm:1.2.0" @@ -27732,6 +27931,13 @@ __metadata: languageName: node linkType: hard +"signal-exit@npm:^4.1.0": + version: 4.1.0 + resolution: "signal-exit@npm:4.1.0" + checksum: 10/c9fa63bbbd7431066174a48ba2dd9986dfd930c3a8b59de9c29d7b6854ec1c12a80d15310869ea5166d413b99f041bfa3dd80a7947bcd44ea8e6eb3ffeabfa1f + languageName: node + linkType: hard + "sigstore@npm:^1.3.0, sigstore@npm:^1.4.0": version: 1.9.0 resolution: "sigstore@npm:1.9.0" @@ -28376,6 +28582,13 @@ __metadata: languageName: node linkType: hard +"statuses@npm:^2.0.1": + version: 2.0.1 + resolution: "statuses@npm:2.0.1" + checksum: 10/18c7623fdb8f646fb213ca4051be4df7efb3484d4ab662937ca6fbef7ced9b9e12842709872eb3020cc3504b93bde88935c9f6417489627a7786f24f8031cbcb + languageName: node + linkType: hard + "stop-iteration-iterator@npm:^1.0.0": version: 1.0.0 resolution: "stop-iteration-iterator@npm:1.0.0" @@ -28518,6 +28731,13 @@ __metadata: languageName: node linkType: hard +"strict-event-emitter@npm:^0.5.1": + version: 0.5.1 + resolution: "strict-event-emitter@npm:0.5.1" + checksum: 10/25c84d88be85940d3547db665b871bfecea4ea0bedfeb22aae8db48126820cfb2b0bc2fba695392592a09b1aa36b686d6eede499e1ecd151593c03fe5a50d512 + languageName: node + linkType: hard + "string-hash@npm:^1.1.3": version: 1.1.3 resolution: "string-hash@npm:1.1.3" @@ -29819,6 +30039,13 @@ __metadata: languageName: node linkType: hard +"type-fest@npm:^4.9.0": + version: 4.10.2 + resolution: "type-fest@npm:4.10.2" + checksum: 10/2b1ad1270d9fabeeb506ba831d513caeb05bfc852e5e012511d785ce9dc68d773fe0a42bddf857a362c7f3406244809c5b8a698b743bb7617d4a8c470672087f + languageName: node + linkType: hard + "type-is@npm:~1.6.18": version: 1.6.18 resolution: "type-is@npm:1.6.18" @@ -31485,7 +31712,7 @@ __metadata: languageName: node linkType: hard -"yargs@npm:^17.3.1, yargs@npm:^17.5.1, yargs@npm:^17.6.2": +"yargs@npm:^17.3.1, yargs@npm:^17.5.1, yargs@npm:^17.6.2, yargs@npm:^17.7.2": version: 17.7.2 resolution: "yargs@npm:17.7.2" dependencies: