diff --git a/public/app/core/utils/shortLinks.test.ts b/public/app/core/utils/shortLinks.test.ts index c6732d6f4f1..39a43af6629 100644 --- a/public/app/core/utils/shortLinks.test.ts +++ b/public/app/core/utils/shortLinks.test.ts @@ -13,7 +13,7 @@ jest.mock('@grafana/runtime', () => ({ getBackendSrv: () => { return { post: () => { - return Promise.resolve({ url: 'www.test.grafana.com/goto/bewyw48durgu8d?orgId=1' }); + return Promise.resolve({ url: 'https://www.test.grafana.com/goto/bewyw48durgu8d?orgId=1' }); }, }; }, @@ -44,6 +44,11 @@ beforeEach(() => { document.execCommand = jest.fn(); config.featureToggles.useKubernetesShortURLsAPI = false; + // clear memoizeOne function + if ('clear' in createShortLink) { + (createShortLink as { clear: () => void }).clear(); + } + // Clear any caches between tests jest.clearAllMocks(); }); @@ -51,7 +56,7 @@ beforeEach(() => { describe('createShortLink', () => { it('creates short link', async () => { const shortUrl = await createShortLink('d/edhmipji89b0gb/welcome?orgId=1&from=now-6h&to=now&timezone=browser'); - expect(shortUrl).toBe('www.test.grafana.com/goto/bewyw48durgu8d?orgId=1'); + expect(shortUrl).toBe('https://www.test.grafana.com/goto/bewyw48durgu8d?orgId=1'); }); }); @@ -88,7 +93,9 @@ describe('createAndCopyShortLink', () => { it('copies short link to clipboard via navigator.clipboard.writeText when ClipboardItem is undefined', async () => { window.isSecureContext = true; await createAndCopyShortLink('d/edhmipji89b0gb/welcome?orgId=1&from=now-6h&to=now&timezone=browser'); - expect(navigator.clipboard.writeText).toHaveBeenCalledWith('www.test.grafana.com/goto/bewyw48durgu8d?orgId=1'); + expect(navigator.clipboard.writeText).toHaveBeenCalledWith( + 'https://www.test.grafana.com/goto/bewyw48durgu8d?orgId=1' + ); }); it('copies short link to clipboard via navigator.clipboard.write and ClipboardItem when it is defined', async () => { diff --git a/public/app/core/utils/shortLinks.ts b/public/app/core/utils/shortLinks.ts index 536911f9942..706857c122c 100644 --- a/public/app/core/utils/shortLinks.ts +++ b/public/app/core/utils/shortLinks.ts @@ -33,15 +33,16 @@ function getRelativeURLPath(url: string) { return path.startsWith('/') ? path.substring(1, path.length) : path; } -// Memoized legacy API call - preserves original behavior -const createShortLinkLegacy = memoizeOne(async (path: string): Promise => { +const createShortLinkLegacy = async (path: string): Promise => { const shortLink = await getBackendSrv().post(`/api/short-urls`, { path: getRelativeURLPath(path), }); return shortLink.url; -}); +}; -export const createShortLink = async function (path: string) { +// Memoized API call, to not re-execute the same request multiple times +// this function creates a shortURL using the legacy or the new k8s api depending on the feature toggle +export const createShortLink = memoizeOne(async (path: string): Promise => { try { if (config.featureToggles.useKubernetesShortURLsAPI) { // Use RTK API - it handles caching/failures/retries automatically @@ -69,7 +70,6 @@ export const createShortLink = async function (path: string) { throw new Error('Failed to create short URL'); } else { - // Old API - use memoized function (preserves original behavior) return await createShortLinkLegacy(path); } } catch (err) { @@ -77,7 +77,7 @@ export const createShortLink = async function (path: string) { dispatch(notifyApp(createErrorNotification('Error generating shortened link'))); throw err; // Re-throw so callers know it failed } -}; +}); /** * Creates a ClipboardItem for the shortened link. This is used due to clipboard issues in Safari after making async calls.