Table: Add unit tests for MaybeWrapWithLink (#109932)
This commit is contained in:
@@ -2,7 +2,7 @@ import { css } from '@emotion/css';
|
|||||||
|
|
||||||
import { formattedValueToString } from '@grafana/data';
|
import { formattedValueToString } from '@grafana/data';
|
||||||
|
|
||||||
import { MaybeWrapWithLink } from '../MaybeWrapWithLink';
|
import { MaybeWrapWithLink } from '../components/MaybeWrapWithLink';
|
||||||
import { AutoCellProps, TableCellStyles } from '../types';
|
import { AutoCellProps, TableCellStyles } from '../types';
|
||||||
|
|
||||||
export function AutoCell({ value, field, rowIdx }: AutoCellProps) {
|
export function AutoCell({ value, field, rowIdx }: AutoCellProps) {
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { ThresholdsConfig, ThresholdsMode, VizOrientation, getFieldConfigWithMin
|
|||||||
import { BarGaugeDisplayMode, BarGaugeValueMode, TableCellDisplayMode } from '@grafana/schema';
|
import { BarGaugeDisplayMode, BarGaugeValueMode, TableCellDisplayMode } from '@grafana/schema';
|
||||||
|
|
||||||
import { BarGauge } from '../../../BarGauge/BarGauge';
|
import { BarGauge } from '../../../BarGauge/BarGauge';
|
||||||
import { MaybeWrapWithLink } from '../MaybeWrapWithLink';
|
import { MaybeWrapWithLink } from '../components/MaybeWrapWithLink';
|
||||||
import { TABLE } from '../constants';
|
import { TABLE } from '../constants';
|
||||||
import { BarGaugeCellProps } from '../types';
|
import { BarGaugeCellProps } from '../types';
|
||||||
import { getCellOptions, getAlignmentFactor } from '../utils';
|
import { getCellOptions, getAlignmentFactor } from '../utils';
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { css } from '@emotion/css';
|
import { css } from '@emotion/css';
|
||||||
|
|
||||||
import { TableCellDisplayMode } from '../../types';
|
import { TableCellDisplayMode } from '../../types';
|
||||||
import { MaybeWrapWithLink } from '../MaybeWrapWithLink';
|
import { MaybeWrapWithLink } from '../components/MaybeWrapWithLink';
|
||||||
import { ImageCellProps, TableCellStyles } from '../types';
|
import { ImageCellProps, TableCellStyles } from '../types';
|
||||||
|
|
||||||
export const ImageCell = ({ cellOptions, field, value, rowIdx }: ImageCellProps) => {
|
export const ImageCell = ({ cellOptions, field, value, rowIdx }: ImageCellProps) => {
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { css } from '@emotion/css';
|
|||||||
|
|
||||||
import { renderMarkdown } from '@grafana/data';
|
import { renderMarkdown } from '@grafana/data';
|
||||||
|
|
||||||
import { MaybeWrapWithLink } from '../MaybeWrapWithLink';
|
import { MaybeWrapWithLink } from '../components/MaybeWrapWithLink';
|
||||||
import { MarkdownCellProps, TableCellStyles } from '../types';
|
import { MarkdownCellProps, TableCellStyles } from '../types';
|
||||||
|
|
||||||
export function MarkdownCell({ field, rowIdx, disableSanitizeHtml }: MarkdownCellProps) {
|
export function MarkdownCell({ field, rowIdx, disableSanitizeHtml }: MarkdownCellProps) {
|
||||||
|
|||||||
+199
@@ -0,0 +1,199 @@
|
|||||||
|
import { render, screen } from '@testing-library/react';
|
||||||
|
|
||||||
|
import { ActionType, Field, FieldType, HttpRequestMethod } from '@grafana/data';
|
||||||
|
|
||||||
|
import { MaybeWrapWithLink } from './MaybeWrapWithLink';
|
||||||
|
|
||||||
|
describe('MaybeWrapWithLink', () => {
|
||||||
|
describe('single link', () => {
|
||||||
|
it('renders children as a link when there is a single link', () => {
|
||||||
|
const link = { title: 'My link', url: 'http://example.com' };
|
||||||
|
const field: Field = {
|
||||||
|
type: FieldType.string,
|
||||||
|
name: 'Test Field',
|
||||||
|
values: [],
|
||||||
|
getLinks: jest.fn(() => [{ title: link.title, href: link.url, target: '_blank', origin: field }]),
|
||||||
|
config: {
|
||||||
|
links: [link],
|
||||||
|
actions: [],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const rowIdx = 0;
|
||||||
|
const children = <span>Test Link</span>;
|
||||||
|
|
||||||
|
render(<MaybeWrapWithLink field={field} rowIdx={rowIdx} children={children} />);
|
||||||
|
const linkElement = screen.getByTitle(link.title);
|
||||||
|
expect(linkElement).toBeInTheDocument();
|
||||||
|
expect(linkElement).toHaveAttribute('href', link.url);
|
||||||
|
expect(linkElement).toHaveTextContent('Test Link');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('does not throw if getLinks unexpectedly returns nothing when a single link is present', () => {
|
||||||
|
const field: Field = {
|
||||||
|
type: FieldType.string,
|
||||||
|
name: 'Test Field',
|
||||||
|
values: [],
|
||||||
|
getLinks: jest.fn(() => []),
|
||||||
|
config: {
|
||||||
|
links: [{ title: 'My link', url: 'http://example.com' }],
|
||||||
|
actions: [],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const rowIdx = 0;
|
||||||
|
const children = <span>Test Link</span>;
|
||||||
|
|
||||||
|
render(<MaybeWrapWithLink field={field} rowIdx={rowIdx} children={children} />);
|
||||||
|
|
||||||
|
const childElement = screen.getByText('Test Link');
|
||||||
|
expect(childElement).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('multi link and/or actions', () => {
|
||||||
|
it('renders a popup target link if multiple links are present', () => {
|
||||||
|
const links = [
|
||||||
|
{ title: 'My link', url: 'http://example.com' },
|
||||||
|
{ title: 'Another link', url: 'http://example.com' },
|
||||||
|
];
|
||||||
|
const field: Field = {
|
||||||
|
type: FieldType.string,
|
||||||
|
name: 'Test Field',
|
||||||
|
values: [],
|
||||||
|
getLinks: jest.fn(() => links.map((l) => ({ title: l.title, href: l.url, target: '_blank', origin: field }))),
|
||||||
|
config: {
|
||||||
|
links,
|
||||||
|
actions: [],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const rowIdx = 0;
|
||||||
|
const children = <span>Test Link</span>;
|
||||||
|
|
||||||
|
render(<MaybeWrapWithLink field={field} rowIdx={rowIdx} children={children} />);
|
||||||
|
|
||||||
|
const linkElement = screen.getByTitle('view data links and actions');
|
||||||
|
expect(linkElement).toBeInTheDocument();
|
||||||
|
expect(linkElement.tagName).toBe('A');
|
||||||
|
expect(linkElement).toHaveAttribute('aria-haspopup', 'menu');
|
||||||
|
expect(linkElement).toHaveTextContent('Test Link');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('renders a popup target link if multiple actions are present', () => {
|
||||||
|
const field: Field = {
|
||||||
|
type: FieldType.string,
|
||||||
|
name: 'Test Field',
|
||||||
|
values: [],
|
||||||
|
getLinks: jest.fn(() => []),
|
||||||
|
config: {
|
||||||
|
links: [],
|
||||||
|
actions: [
|
||||||
|
{
|
||||||
|
type: ActionType.Fetch,
|
||||||
|
title: 'My action',
|
||||||
|
[ActionType.Fetch]: { method: HttpRequestMethod.GET, url: 'http://example.com' },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: ActionType.Fetch,
|
||||||
|
title: 'Another action',
|
||||||
|
[ActionType.Fetch]: { method: HttpRequestMethod.POST, url: 'http://example.com' },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const rowIdx = 0;
|
||||||
|
const children = <span>Test Link</span>;
|
||||||
|
|
||||||
|
render(<MaybeWrapWithLink field={field} rowIdx={rowIdx} children={children} />);
|
||||||
|
|
||||||
|
const linkElement = screen.getByTitle('view data links and actions');
|
||||||
|
expect(linkElement).toBeInTheDocument();
|
||||||
|
expect(linkElement.tagName).toBe('A');
|
||||||
|
expect(linkElement).toHaveAttribute('aria-haspopup', 'menu');
|
||||||
|
expect(linkElement).toHaveTextContent('Test Link');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('renders a popup target link if a single action is present', () => {
|
||||||
|
const field: Field = {
|
||||||
|
type: FieldType.string,
|
||||||
|
name: 'Test Field',
|
||||||
|
values: [],
|
||||||
|
getLinks: jest.fn(() => []),
|
||||||
|
config: {
|
||||||
|
links: [],
|
||||||
|
actions: [
|
||||||
|
{
|
||||||
|
type: ActionType.Fetch,
|
||||||
|
title: 'My action',
|
||||||
|
[ActionType.Fetch]: { method: HttpRequestMethod.GET, url: 'http://example.com' },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const rowIdx = 0;
|
||||||
|
const children = <span>Test Link</span>;
|
||||||
|
|
||||||
|
render(<MaybeWrapWithLink field={field} rowIdx={rowIdx} children={children} />);
|
||||||
|
|
||||||
|
const linkElement = screen.getByTitle('view data links and actions');
|
||||||
|
expect(linkElement).toBeInTheDocument();
|
||||||
|
expect(linkElement.tagName).toBe('A');
|
||||||
|
expect(linkElement).toHaveAttribute('aria-haspopup', 'menu');
|
||||||
|
expect(linkElement).toHaveTextContent('Test Link');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('renders a popup target link if a mixture of actions and links are present', () => {
|
||||||
|
const links = [{ title: 'My link', url: 'http://example.com' }];
|
||||||
|
const field: Field = {
|
||||||
|
type: FieldType.string,
|
||||||
|
name: 'Test Field',
|
||||||
|
values: [],
|
||||||
|
getLinks: jest.fn(() => links.map((l) => ({ title: l.title, href: l.url, target: '_blank', origin: field }))),
|
||||||
|
config: {
|
||||||
|
links,
|
||||||
|
actions: [
|
||||||
|
{
|
||||||
|
type: ActionType.Fetch,
|
||||||
|
title: 'My action',
|
||||||
|
[ActionType.Fetch]: { method: HttpRequestMethod.GET, url: 'http://example.com' },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const rowIdx = 0;
|
||||||
|
const children = <span>Test Link</span>;
|
||||||
|
|
||||||
|
render(<MaybeWrapWithLink field={field} rowIdx={rowIdx} children={children} />);
|
||||||
|
|
||||||
|
const linkElement = screen.getByTitle('view data links and actions');
|
||||||
|
expect(linkElement).toBeInTheDocument();
|
||||||
|
expect(linkElement.tagName).toBe('A');
|
||||||
|
expect(linkElement).toHaveAttribute('aria-haspopup', 'menu');
|
||||||
|
expect(linkElement).toHaveTextContent('Test Link');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('no links or actions', () => {
|
||||||
|
it('passes the children through when no links or actions are present', () => {
|
||||||
|
const links = [
|
||||||
|
{ title: 'My link', url: 'http://example.com' },
|
||||||
|
{ title: 'Another link', url: 'http://example.com' },
|
||||||
|
];
|
||||||
|
const field: Field = {
|
||||||
|
type: FieldType.string,
|
||||||
|
name: 'Test Field',
|
||||||
|
values: [],
|
||||||
|
getLinks: jest.fn(() => []),
|
||||||
|
config: {
|
||||||
|
links,
|
||||||
|
actions: [],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const rowIdx = 0;
|
||||||
|
const children = <span>Test Link</span>;
|
||||||
|
|
||||||
|
render(<MaybeWrapWithLink field={field} rowIdx={rowIdx} children={children} />);
|
||||||
|
|
||||||
|
const childElement = screen.getByText('Test Link');
|
||||||
|
expect(childElement).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
+9
-5
@@ -1,10 +1,10 @@
|
|||||||
import { memo, ReactNode } from 'react';
|
import { memo, ReactNode } from 'react';
|
||||||
|
|
||||||
import { Field } from '@grafana/data';
|
import { Field } from '@grafana/data';
|
||||||
|
import { t } from '@grafana/i18n';
|
||||||
|
|
||||||
import { renderSingleLink } from '../DataLinksActionsTooltip';
|
import { renderSingleLink } from '../../DataLinksActionsTooltip';
|
||||||
|
import { getCellLinks } from '../utils';
|
||||||
import { getCellLinks } from './utils';
|
|
||||||
|
|
||||||
interface MaybeWrapWithLinkProps {
|
interface MaybeWrapWithLinkProps {
|
||||||
field: Field;
|
field: Field;
|
||||||
@@ -23,8 +23,12 @@ export const MaybeWrapWithLink = memo(({ field, rowIdx, children }: MaybeWrapWit
|
|||||||
}
|
}
|
||||||
// as faux link that acts as hit-area for tooltip activation
|
// as faux link that acts as hit-area for tooltip activation
|
||||||
else if (linksCount + actionsCount > 0) {
|
else if (linksCount + actionsCount > 0) {
|
||||||
// eslint-disable-next-line jsx-a11y/anchor-is-valid
|
return (
|
||||||
return <a aria-haspopup="menu">{children}</a>;
|
// eslint-disable-next-line jsx-a11y/anchor-is-valid
|
||||||
|
<a title={t('table.link-wrapper.menu', 'view data links and actions')} aria-haspopup="menu">
|
||||||
|
{children}
|
||||||
|
</a>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// raw value
|
// raw value
|
||||||
@@ -12751,6 +12751,9 @@
|
|||||||
"label-alt-text": "Alt text",
|
"label-alt-text": "Alt text",
|
||||||
"label-title-text": "Title text"
|
"label-title-text": "Title text"
|
||||||
},
|
},
|
||||||
|
"link-wrapper": {
|
||||||
|
"menu": "view data links and actions"
|
||||||
|
},
|
||||||
"markdown-cell-options-editor": {
|
"markdown-cell-options-editor": {
|
||||||
"description-dynamic-height": "We recommend enabling pagination with this option to avoid performance issues.",
|
"description-dynamic-height": "We recommend enabling pagination with this option to avoid performance issues.",
|
||||||
"label": {
|
"label": {
|
||||||
|
|||||||
Reference in New Issue
Block a user