mirror of
https://github.com/grafana/grafana.git
synced 2025-02-09 23:16:16 -06:00
Chore: Test grafana/public/app/plugins/panel/text/TextPanel.tsx
(#52244)
* move sanitize test to its own test file * add a test for renderTextPanelMarkdown to always sanitize * setup TextPanel tests * add tests to always sanitize Text Panel contents and always convert correctly to html/markdown
This commit is contained in:
parent
13b23fd512
commit
bec500b69f
@ -1,5 +1,4 @@
|
||||
import { renderMarkdown } from './markdown';
|
||||
import { sanitizeTextPanelContent } from './sanitize';
|
||||
import { renderMarkdown, renderTextPanelMarkdown } from './markdown';
|
||||
|
||||
describe('Markdown wrapper', () => {
|
||||
it('should be able to handle undefined value', () => {
|
||||
@ -12,12 +11,8 @@ describe('Markdown wrapper', () => {
|
||||
expect(str).toBe('<script>alert()</script>');
|
||||
});
|
||||
|
||||
it('should allow whitelisted styles in text panel', () => {
|
||||
const html =
|
||||
'<div style="display:flex; flex-direction: column; flex-wrap: wrap; justify-content: start; gap: 2px;"><div style="flex-basis: 50%"></div></div>';
|
||||
const str = sanitizeTextPanelContent(html);
|
||||
expect(str).toBe(
|
||||
'<div style="display:flex; flex-direction:column; flex-wrap:wrap; justify-content:start; gap:2px;"><div style="flex-basis:50%;"></div></div>'
|
||||
);
|
||||
it('should sanitize content in text panel by default', () => {
|
||||
const str = renderTextPanelMarkdown('<script>alert()</script>');
|
||||
expect(str).toBe('<script>alert()</script>');
|
||||
});
|
||||
});
|
||||
|
12
packages/grafana-data/src/text/sanitize.test.ts
Normal file
12
packages/grafana-data/src/text/sanitize.test.ts
Normal file
@ -0,0 +1,12 @@
|
||||
import { sanitizeTextPanelContent } from './sanitize';
|
||||
|
||||
describe('Sanitize wrapper', () => {
|
||||
it('should allow whitelisted styles in text panel', () => {
|
||||
const html =
|
||||
'<div style="display:flex; flex-direction: column; flex-wrap: wrap; justify-content: start; gap: 2px;"><div style="flex-basis: 50%"></div></div>';
|
||||
const str = sanitizeTextPanelContent(html);
|
||||
expect(str).toBe(
|
||||
'<div style="display:flex; flex-direction:column; flex-wrap:wrap; justify-content:start; gap:2px;"><div style="flex-basis:50%;"></div></div>'
|
||||
);
|
||||
});
|
||||
});
|
120
public/app/plugins/panel/text/TextPanel.test.tsx
Normal file
120
public/app/plugins/panel/text/TextPanel.test.tsx
Normal file
@ -0,0 +1,120 @@
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import React from 'react';
|
||||
|
||||
import { dateTime, LoadingState, EventBusSrv } from '@grafana/data';
|
||||
|
||||
import { Props, TextPanel } from './TextPanel';
|
||||
import { TextMode } from './models.gen';
|
||||
|
||||
const replaceVariablesMock = jest.fn();
|
||||
const defaultProps: Props = {
|
||||
id: 1,
|
||||
data: {
|
||||
state: LoadingState.Done,
|
||||
series: [
|
||||
{
|
||||
fields: [],
|
||||
length: 0,
|
||||
},
|
||||
],
|
||||
timeRange: {
|
||||
from: dateTime('2022-01-01T15:55:00Z'),
|
||||
to: dateTime('2022-07-12T15:55:00Z'),
|
||||
raw: {
|
||||
from: 'now-15m',
|
||||
to: 'now',
|
||||
},
|
||||
},
|
||||
},
|
||||
timeRange: {
|
||||
from: dateTime('2022-07-11T15:55:00Z'),
|
||||
to: dateTime('2022-07-12T15:55:00Z'),
|
||||
raw: {
|
||||
from: 'now-15m',
|
||||
to: 'now',
|
||||
},
|
||||
},
|
||||
timeZone: 'utc',
|
||||
transparent: false,
|
||||
width: 120,
|
||||
height: 120,
|
||||
fieldConfig: {
|
||||
defaults: {},
|
||||
overrides: [],
|
||||
},
|
||||
renderCounter: 1,
|
||||
title: 'Test Text Panel',
|
||||
eventBus: new EventBusSrv(),
|
||||
options: { content: '', mode: TextMode.Markdown },
|
||||
onOptionsChange: jest.fn(),
|
||||
onFieldConfigChange: jest.fn(),
|
||||
replaceVariables: replaceVariablesMock,
|
||||
onChangeTimeRange: jest.fn(),
|
||||
};
|
||||
|
||||
const setup = (props: Props = defaultProps) => {
|
||||
render(<TextPanel {...props} />);
|
||||
};
|
||||
|
||||
describe('TextPanel', () => {
|
||||
it('should render panel without content', () => {
|
||||
expect(() => setup()).not.toThrow();
|
||||
});
|
||||
|
||||
it('sanitizes content in html mode', () => {
|
||||
const contentTest = '<form><p>Form tags are sanitized.</p></form>\n<script>Script tags are sanitized.</script>';
|
||||
replaceVariablesMock.mockReturnValueOnce(contentTest);
|
||||
const props = Object.assign({}, defaultProps, {
|
||||
options: { content: contentTest, mode: TextMode.HTML },
|
||||
});
|
||||
|
||||
setup(props);
|
||||
|
||||
expect(screen.getByTestId('TextPanel-converted-content').innerHTML).toEqual(
|
||||
'<form><p>Form tags are sanitized.</p></form>\n<script>Script tags are sanitized.</script>'
|
||||
);
|
||||
});
|
||||
|
||||
it('sanitizes content in markdown mode', () => {
|
||||
const contentTest = '<form><p>Form tags are sanitized.</p></form>\n<script>Script tags are sanitized.</script>';
|
||||
replaceVariablesMock.mockReturnValueOnce(contentTest);
|
||||
|
||||
const props = Object.assign({}, defaultProps, {
|
||||
options: { content: contentTest, mode: TextMode.Markdown },
|
||||
});
|
||||
|
||||
setup(props);
|
||||
|
||||
expect(screen.getByTestId('TextPanel-converted-content').innerHTML).toEqual(
|
||||
'<form><p>Form tags are sanitized.</p></form>\n<script>Script tags are sanitized.</script>'
|
||||
);
|
||||
});
|
||||
|
||||
it('converts content to markdown when in markdown mode', async () => {
|
||||
const contentTest = 'We begin by a simple sentence.\n```code block```';
|
||||
replaceVariablesMock.mockReturnValueOnce(contentTest);
|
||||
|
||||
const props = Object.assign({}, defaultProps, {
|
||||
options: { content: contentTest, mode: TextMode.Markdown },
|
||||
});
|
||||
|
||||
setup(props);
|
||||
|
||||
const waited = await screen.getByTestId('TextPanel-converted-content');
|
||||
expect(waited.innerHTML).toEqual('<p>We begin by a simple sentence.\n<code>code block</code></p>\n');
|
||||
});
|
||||
|
||||
it('converts content to html when in html mode', () => {
|
||||
const contentTest = 'We begin by a simple sentence.\n```This is a code block\n```';
|
||||
replaceVariablesMock.mockReturnValueOnce(contentTest);
|
||||
const props = Object.assign({}, defaultProps, {
|
||||
options: { content: contentTest, mode: TextMode.HTML },
|
||||
});
|
||||
|
||||
setup(props);
|
||||
|
||||
expect(screen.getByTestId('TextPanel-converted-content').innerHTML).toEqual(
|
||||
'We begin by a simple sentence.\n```This is a code block\n```'
|
||||
);
|
||||
});
|
||||
});
|
@ -12,7 +12,7 @@ import config from 'app/core/config';
|
||||
// Types
|
||||
import { PanelOptions, TextMode } from './models.gen';
|
||||
|
||||
interface Props extends PanelProps<PanelOptions> {}
|
||||
export interface Props extends PanelProps<PanelOptions> {}
|
||||
|
||||
interface State {
|
||||
html: string;
|
||||
@ -90,7 +90,11 @@ export class TextPanel extends PureComponent<Props, State> {
|
||||
const styles = getStyles();
|
||||
return (
|
||||
<CustomScrollbar autoHeightMin="100%">
|
||||
<DangerouslySetHtmlContent html={html} className={cx('markdown-html', styles.content)} />
|
||||
<DangerouslySetHtmlContent
|
||||
html={html}
|
||||
className={cx('markdown-html', styles.content)}
|
||||
data-testid="TextPanel-converted-content"
|
||||
/>
|
||||
</CustomScrollbar>
|
||||
);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user