From 4d4bf391846492911cc0ecc22c0c6fda146846d6 Mon Sep 17 00:00:00 2001 From: Tom Ratcliffe Date: Fri, 26 Apr 2024 11:20:08 +0100 Subject: [PATCH] Check for server received body This is not ideal! Preference would be to have a more robust mock server that responds to the received silence and appends it to a stateful list for the test and then resets afterwards --- .../alerting/unified/Silences.test.tsx | 28 +++++++++++++++++++ .../alerting/unified/mocks/server/events.ts | 23 +++++++++++++++ 2 files changed, 51 insertions(+) create mode 100644 public/app/features/alerting/unified/mocks/server/events.ts diff --git a/public/app/features/alerting/unified/Silences.test.tsx b/public/app/features/alerting/unified/Silences.test.tsx index 92c50bf446e..0ac440359d5 100644 --- a/public/app/features/alerting/unified/Silences.test.tsx +++ b/public/app/features/alerting/unified/Silences.test.tsx @@ -6,6 +6,8 @@ import { dateTime } from '@grafana/data'; import { selectors } from '@grafana/e2e-selectors'; import { config, locationService, setDataSourceSrv } from '@grafana/runtime'; import { setupMswServer } from 'app/features/alerting/unified/mockApi'; +import { waitForServerRequest } from 'app/features/alerting/unified/mocks/server/events'; +import { silenceCreateHandler } from 'app/features/alerting/unified/mocks/silences'; import { MatcherOperator } from 'app/plugins/datasource/alertmanager/types'; import { AccessControlAction } from 'app/types'; @@ -239,6 +241,8 @@ describe('Silence create/edit', () => { renderSilences(baseUrlPath); expect(await ui.editor.durationField.find()).toBeInTheDocument(); + const postRequest = waitForServerRequest(silenceCreateHandler()); + const start = new Date(); const end = new Date(start.getTime() + 24 * 60 * 60 * 1000); @@ -266,6 +270,20 @@ describe('Silence create/edit', () => { await userEvent.click(ui.editor.submit.get()); expect(await ui.notExpiredTable.find()).toBeInTheDocument(); + + const createSilenceRequest = await postRequest; + const requestBody = await createSilenceRequest.clone().json(); + expect(requestBody).toMatchObject( + expect.objectContaining({ + comment: expect.stringMatching(/created (\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2})/), + matchers: [ + { isEqual: true, isRegex: false, name: 'foo', value: 'bar' }, + { isEqual: false, isRegex: false, name: 'bar', value: 'buzz' }, + { isEqual: true, isRegex: true, name: 'region', value: 'us-west-.*' }, + { isEqual: false, isRegex: true, name: 'env', value: 'dev|staging' }, + ], + }) + ); }, TEST_TIMEOUT ); @@ -275,6 +293,8 @@ describe('Silence create/edit', () => { async () => { const user = userEvent.setup(); + const postRequest = waitForServerRequest(silenceCreateHandler()); + renderSilences(`${baseUrlPath}?alertmanager=Alertmanager`); await waitFor(() => expect(ui.editor.durationField.query()).not.toBeNull()); @@ -285,6 +305,14 @@ describe('Silence create/edit', () => { expect(await ui.notExpiredTable.find()).toBeInTheDocument(); expect(locationService.getSearch().get('alertmanager')).toBe('Alertmanager'); + + const createSilenceRequest = await postRequest; + const requestBody = await createSilenceRequest.clone().json(); + expect(requestBody).toMatchObject( + expect.objectContaining({ + matchers: [{ isEqual: true, isRegex: false, name: 'foo', value: 'bar' }], + }) + ); }, TEST_TIMEOUT ); diff --git a/public/app/features/alerting/unified/mocks/server/events.ts b/public/app/features/alerting/unified/mocks/server/events.ts new file mode 100644 index 00000000000..1feb57d5a89 --- /dev/null +++ b/public/app/features/alerting/unified/mocks/server/events.ts @@ -0,0 +1,23 @@ +import { HttpHandler, matchRequestUrl } from 'msw'; + +import server from 'app/features/alerting/unified/mockApi'; + +/** + * Wait for the mock server to receive a request for the given method + url combination, + * and resolve with information about the request that was made + * + * @deprecated Try not to use this 🙏 instead aim to assert against UI side effects + */ +export function waitForServerRequest(handler: HttpHandler) { + const { method, path } = handler.info; + return new Promise((resolve) => { + server.events.on('request:match', ({ request }) => { + const matchesMethod = request.method.toLowerCase() === String(method).toLowerCase(); + const matchesUrl = matchRequestUrl(new URL(request.url), path); + + if (matchesMethod && matchesUrl) { + resolve(request); + } + }); + }); +}