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);