mirror of
https://github.com/grafana/grafana.git
synced 2024-12-01 13:09:22 -06:00
TextLink: Do not strip base from external urls (#81799)
This commit is contained in:
parent
f9c54abdcf
commit
ded0554bac
52
packages/grafana-ui/src/components/Link/TextLink.test.tsx
Normal file
52
packages/grafana-ui/src/components/Link/TextLink.test.tsx
Normal file
@ -0,0 +1,52 @@
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import React from 'react';
|
||||
import { MemoryRouter } from 'react-router-dom';
|
||||
|
||||
import { GrafanaConfig, locationUtil } from '@grafana/data';
|
||||
|
||||
import { TextLink } from './TextLink';
|
||||
|
||||
describe('TextLink', () => {
|
||||
let windowSpy: jest.SpyInstance;
|
||||
|
||||
beforeAll(() => {
|
||||
windowSpy = jest.spyOn(window, 'location', 'get');
|
||||
windowSpy.mockImplementation(() => ({
|
||||
origin: 'http://www.grafana.com',
|
||||
}));
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
windowSpy.mockRestore();
|
||||
});
|
||||
|
||||
const link = 'http://www.grafana.com/grafana/after-sub-url';
|
||||
it('should keep the whole url, including app sub url, if external', () => {
|
||||
locationUtil.initialize({
|
||||
config: { appSubUrl: '/grafana' } as GrafanaConfig,
|
||||
getVariablesUrlParams: jest.fn(),
|
||||
getTimeRangeForUrl: jest.fn(),
|
||||
});
|
||||
|
||||
render(
|
||||
<TextLink href={link} external>
|
||||
Link to Grafana
|
||||
</TextLink>
|
||||
);
|
||||
expect(screen.getByRole('link')).toHaveAttribute('href', link);
|
||||
});
|
||||
it('should turn it into a relative url, if not external', () => {
|
||||
locationUtil.initialize({
|
||||
config: { appSubUrl: '/grafana' } as GrafanaConfig,
|
||||
getVariablesUrlParams: jest.fn(),
|
||||
getTimeRangeForUrl: jest.fn(),
|
||||
});
|
||||
|
||||
render(
|
||||
<MemoryRouter>
|
||||
<TextLink href={link}>Link to Grafana</TextLink>
|
||||
</MemoryRouter>
|
||||
);
|
||||
expect(screen.getByRole('link')).toHaveAttribute('href', '/after-sub-url');
|
||||
});
|
||||
});
|
@ -46,19 +46,25 @@ export const TextLink = forwardRef<HTMLAnchorElement, TextLinkProps>(
|
||||
{ href, color = 'link', external = false, inline = true, variant = 'body', weight, icon, children, ...rest },
|
||||
ref
|
||||
) => {
|
||||
const validUrl = locationUtil.stripBaseFromUrl(textUtil.sanitizeUrl(href ?? ''));
|
||||
const validUrl = textUtil.sanitizeUrl(href ?? '');
|
||||
|
||||
const theme = useTheme2();
|
||||
const styles = getLinkStyles(theme, inline, variant, weight, color);
|
||||
const externalIcon = icon || 'external-link-alt';
|
||||
|
||||
return external ? (
|
||||
<a href={validUrl} ref={ref} {...rest} target="_blank" rel="noreferrer" className={styles}>
|
||||
{children}
|
||||
<Icon size={svgSizes[variant] || 'md'} name={externalIcon} />
|
||||
</a>
|
||||
) : (
|
||||
<Link ref={ref} href={validUrl} {...rest} className={styles}>
|
||||
if (external) {
|
||||
return (
|
||||
<a href={validUrl} ref={ref} {...rest} target="_blank" rel="noreferrer" className={styles}>
|
||||
{children}
|
||||
<Icon size={svgSizes[variant] || 'md'} name={externalIcon} />
|
||||
</a>
|
||||
);
|
||||
}
|
||||
|
||||
const strippedUrl = locationUtil.stripBaseFromUrl(validUrl);
|
||||
|
||||
return (
|
||||
<Link ref={ref} href={strippedUrl} {...rest} className={styles}>
|
||||
{children}
|
||||
{icon && <Icon name={icon} size={svgSizes[variant] || 'md'} />}
|
||||
</Link>
|
||||
|
@ -104,7 +104,7 @@ describe('ShareModal', () => {
|
||||
mockLocationHref('http://dashboards.grafana.com/d/abcdefghi/my-dash');
|
||||
render(<ShareLink {...props} />);
|
||||
|
||||
const base = '/render/d-solo/abcdefghi/my-dash';
|
||||
const base = 'http://dashboards.grafana.com/render/d-solo/abcdefghi/my-dash';
|
||||
const params = '?from=1000&to=2000&orgId=1&panelId=22&width=1000&height=500&tz=UTC';
|
||||
expect(
|
||||
await screen.findByRole('link', { name: selectors.pages.SharePanelModal.linkToRenderedImage })
|
||||
@ -115,7 +115,7 @@ describe('ShareModal', () => {
|
||||
mockLocationHref('http://dashboards.grafana.com/dashboard/script/my-dash.js');
|
||||
render(<ShareLink {...props} />);
|
||||
|
||||
const base = '/render/dashboard-solo/script/my-dash.js';
|
||||
const base = 'http://dashboards.grafana.com/render/dashboard-solo/script/my-dash.js';
|
||||
const params = '?from=1000&to=2000&orgId=1&panelId=22&width=1000&height=500&tz=UTC';
|
||||
expect(
|
||||
await screen.findByRole('link', { name: selectors.pages.SharePanelModal.linkToRenderedImage })
|
||||
@ -151,7 +151,7 @@ describe('ShareModal', () => {
|
||||
);
|
||||
expect(
|
||||
await screen.findByRole('link', { name: selectors.pages.SharePanelModal.linkToRenderedImage })
|
||||
).toHaveAttribute('href', path + '?from=1000&to=2000&orgId=1&panelId=1&width=1000&height=500&tz=UTC');
|
||||
).toHaveAttribute('href', base + path + '?from=1000&to=2000&orgId=1&panelId=1&width=1000&height=500&tz=UTC');
|
||||
});
|
||||
|
||||
it('should shorten url', async () => {
|
||||
@ -198,7 +198,7 @@ describe('when appUrl is set in the grafana config', () => {
|
||||
await screen.findByRole('link', { name: selectors.pages.SharePanelModal.linkToRenderedImage })
|
||||
).toHaveAttribute(
|
||||
'href',
|
||||
`/render/d-solo/${mockDashboard.uid}?orgId=1&from=1000&to=2000&panelId=${mockPanel.id}&width=1000&height=500&tz=UTC`
|
||||
`http://dashboards.grafana.com/render/d-solo/${mockDashboard.uid}?orgId=1&from=1000&to=2000&panelId=${mockPanel.id}&width=1000&height=500&tz=UTC`
|
||||
);
|
||||
});
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user