From 859b3ff78bcd5949b8b9d32e795cba5b459ddd7e Mon Sep 17 00:00:00 2001 From: Tom Ratcliffe Date: Fri, 24 May 2024 14:02:46 +0100 Subject: [PATCH] Alerting: Fix "copy link" not including full URL (#88210) --- .../rules/RuleActionsButtons.test.tsx | 38 ++++++++++++++++++- .../features/alerting/unified/utils/misc.ts | 2 +- .../features/alerting/unified/utils/url.ts | 4 +- 3 files changed, 39 insertions(+), 5 deletions(-) diff --git a/public/app/features/alerting/unified/components/rules/RuleActionsButtons.test.tsx b/public/app/features/alerting/unified/components/rules/RuleActionsButtons.test.tsx index 7fa0fca52ce..04f1e9cc3ac 100644 --- a/public/app/features/alerting/unified/components/rules/RuleActionsButtons.test.tsx +++ b/public/app/features/alerting/unified/components/rules/RuleActionsButtons.test.tsx @@ -3,7 +3,7 @@ import React from 'react'; import { render, screen, userEvent } from 'test/test-utils'; import { byLabelText } from 'testing-library-selector'; -import { setPluginExtensionsHook } from '@grafana/runtime'; +import { config, setPluginExtensionsHook } from '@grafana/runtime'; import { contextSrv } from 'app/core/services/context_srv'; import { RuleActionsButtons } from 'app/features/alerting/unified/components/rules/RuleActionsButtons'; import { setupMswServer } from 'app/features/alerting/unified/mockApi'; @@ -57,6 +57,12 @@ setPluginExtensionsHook(() => ({ isLoading: false, })); +const clickCopyLink = async () => { + const user = userEvent.setup(); + await user.click(await ui.moreButton.find()); + await user.click(await screen.findByText(/copy link/i)); +}; + describe('RuleActionsButtons', () => { it('renders correct options for grafana managed rule', async () => { const user = userEvent.setup(); @@ -123,4 +129,34 @@ describe('RuleActionsButtons', () => { expect(screen.queryByText(/delete/i)).not.toBeInTheDocument(); }); + + describe('copy link', () => { + beforeEach(() => { + grantAllPermissions(); + config.appUrl = 'http://localhost:3000/'; + config.appSubUrl = '/sub'; + }); + + it('copies correct URL for grafana managed alert rule', async () => { + const mockRule = getGrafanaRule({ rulerRule: mockGrafanaRulerRule({ uid: 'foo', provenance: 'file' }) }); + + render(); + + await clickCopyLink(); + + expect(await navigator.clipboard.readText()).toBe('http://localhost:3000/sub/alerting/grafana/foo/view'); + }); + + it('copies correct URL for cloud rule', async () => { + const mockRule = getCloudRule(); + + render(); + + await clickCopyLink(); + + expect(await navigator.clipboard.readText()).toBe( + 'http://localhost:3000/sub/alerting/Prometheus-2/mockRule/find' + ); + }); + }); }); diff --git a/public/app/features/alerting/unified/utils/misc.ts b/public/app/features/alerting/unified/utils/misc.ts index 350c39abf0c..af0801f8ea3 100644 --- a/public/app/features/alerting/unified/utils/misc.ts +++ b/public/app/features/alerting/unified/utils/misc.ts @@ -61,7 +61,7 @@ export function createShareLink(ruleSource: RulesSource, rule: CombinedRule): st `/alerting/${encodeURIComponent(ruleSource.name)}/${encodeURIComponent(escapePathSeparators(rule.name))}/find` ); } else if (isGrafanaRulerRule(rule.rulerRule)) { - return createUrl(`/alerting/grafana/${rule.rulerRule.grafana_alert.uid}/view`); + return createAbsoluteUrl(`/alerting/grafana/${rule.rulerRule.grafana_alert.uid}/view`); } return; diff --git a/public/app/features/alerting/unified/utils/url.ts b/public/app/features/alerting/unified/utils/url.ts index b712e7ab1e6..7b2fda519aa 100644 --- a/public/app/features/alerting/unified/utils/url.ts +++ b/public/app/features/alerting/unified/utils/url.ts @@ -15,9 +15,7 @@ export function createAbsoluteUrl( const searchParamsString = searchParams.toString(); try { - const baseUrl = new URL(config.appSubUrl, config.appUrl); - baseUrl.pathname = path; - + const baseUrl = new URL(config.appSubUrl + path, config.appUrl); return `${baseUrl.href}${searchParamsString ? `?${searchParamsString}` : ''}`; } catch (err) { return createUrl(path, queryParams);