Skip to content

Commit

Permalink
SAAS-153 check panel viewer access message (#747)
Browse files Browse the repository at this point in the history
* SASS-153 ditch react-test-renderer

* SAAS-153 more tests to check for error messages

* SAAS-153 message & tests for the home panel

* SAAS-153 add message & tests to the details page

* SAAS-153 throw away numeral

* SAAS-153 refix the panel scroll again

* SAAS-153 ts-compatible data-qa passed to components

* SAAS-153 trigger the build
  • Loading branch information
Alexander Tymchuk authored Jun 1, 2020
1 parent a1bb0f2 commit 4aa375e
Show file tree
Hide file tree
Showing 34 changed files with 1,912 additions and 336 deletions.
3 changes: 3 additions & 0 deletions codecov.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
codecov:
token: 3e5d4324-1a64-417c-bdab-3583c34f2911

coverage:
range: "10...80"

Expand Down
5 changes: 0 additions & 5 deletions pmm-app/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 3 additions & 5 deletions pmm-app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@
"scripts": {
"build": "grafana-toolkit plugin:build",
"test": "grafana-toolkit plugin:test",
"jest": "jest",
"test:update": "grafana-toolkit plugin:test --updateSnapshot",
"jest": "jest",
"coverage": "grafana-toolkit plugin:test --coverage",
"dev": "grafana-toolkit plugin:dev",
"watch": "grafana-toolkit plugin:dev --watch",
Expand All @@ -22,7 +22,7 @@
"codecov": "codecov"
},
"bin": {
"toolkit": "node_modules/grafana/packages/grafana-toolkit/bin/grafana-toolkit.js"
"toolkit": "node_modules/@grafana/toolkit/bin/grafana-toolkit.dist.js"
},
"keywords": [
"percona",
Expand All @@ -37,10 +37,9 @@
"antd": "^3.24.3",
"axios": "^0.19.0",
"emotion": "10.0.27",
"final-form": "^4.18.5",
"final-form": "^4.19.1",
"history": "^4.10.1",
"lodash": "^4.17.15",
"numeral": "^2.0.6",
"react": "16.12.0",
"react-dom": "16.12.0",
"react-final-form": "^6.3.5",
Expand Down Expand Up @@ -83,7 +82,6 @@
"node-sass": "^4.12.0",
"playwright": "^0.12.1",
"playwright-video": "^0.13.0",
"react-test-renderer": "^16.12.0",
"sass-loader": "^8.0.2",
"selenium-standalone": "^6.17.0",
"style-loader": "^1.1.4",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import { getInstanceData } from './AddRemoteInstance';

jest.mock('../../../react-plugins-deps/components/helpers/notification-manager', () => () => ({
showErrorNotification: () => {},
}));
jest.mock('../../../react-plugins-deps/components/helpers/notification-manager');

describe('Add remote instance', () => {
it('get instance data should return correct one when isRDS is false', () => {
Expand Down
10 changes: 8 additions & 2 deletions pmm-app/src/pmm-check-home/CheckPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export interface CheckPanelProps extends PanelProps<CheckPanelOptions> {}

export interface CheckPanelState {
failedChecks?: FailedChecks;
hasNoAccess: boolean;
isSttEnabled: boolean;
isLoading: boolean;
}
Expand All @@ -21,6 +22,7 @@ const history = createBrowserHistory();
export class CheckPanel extends PureComponent<CheckPanelProps, CheckPanelState> {
state: CheckPanelState = {
failedChecks: undefined,
hasNoAccess: false,
isSttEnabled: false,
isLoading: true,
};
Expand Down Expand Up @@ -50,24 +52,28 @@ export class CheckPanel extends PureComponent<CheckPanelProps, CheckPanelState>
try {
const resp = (await CheckService.getSettings()) as Settings;
this.setState({ isSttEnabled: !!resp.settings?.stt_enabled });
this.setState({ hasNoAccess: false });
if (resp.settings?.stt_enabled) {
this.fetchAlerts();
} else {
this.setState({ isLoading: false });
}
} catch (err) {
this.setState({ isLoading: false });
if (err.response?.status === 401) {
this.setState({ hasNoAccess: true });
}
console.error(err);
}
}

render() {
const { isSttEnabled, failedChecks, isLoading } = this.state;
const { isSttEnabled, failedChecks, isLoading, hasNoAccess } = this.state;

return (
<div className={styles.panel} data-qa="db-check-panel-home">
{isLoading && <Spinner />}
{!isLoading && <Failed failed={failedChecks} isSttEnabled={isSttEnabled} />}
{!isLoading && <Failed failed={failedChecks} isSttEnabled={isSttEnabled} hasNoAccess={hasNoAccess} />}
</div>
);
}
Expand Down
13 changes: 10 additions & 3 deletions pmm-app/src/pmm-check-home/components/Failed/Failed.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { Failed } from './Failed';

describe('Failed::', () => {
it('should render a sum of total failed checks with severity details', () => {
const root = shallow(<Failed failed={[1, 0, 1]} isSttEnabled />);
const root = shallow(<Failed failed={[1, 0, 1]} isSttEnabled hasNoAccess={false} />);

const spans = root.find('div a > span');
expect(spans.at(0).text()).toEqual('1');
Expand All @@ -15,16 +15,23 @@ describe('Failed::', () => {
});

it('should render 0 when the sum of all checks is zero', () => {
const root = shallow(<Failed failed={[0, 0, 0]} isSttEnabled />);
const root = shallow(<Failed failed={[0, 0, 0]} isSttEnabled hasNoAccess={false} />);

expect(root.find('div > span').text()).toEqual('0');
root.unmount();
});

it('should render an inner tooltip component', () => {
const root = shallow(<Failed failed={[1, 0, 1]} isSttEnabled />);
const root = shallow(<Failed failed={[1, 0, 1]} isSttEnabled hasNoAccess={false} />);

expect(root.find(Tooltip).length).toEqual(1);
root.unmount();
});

it('should render a message when the user only has reader access', () => {
const root = shallow(<Failed failed={[1, 0, 1]} isSttEnabled hasNoAccess />);

expect(root.find('[data-qa="db-check-panel-no-access"]').text()).toEqual('Insufficient access rights.');
root.unmount();
});
});
11 changes: 10 additions & 1 deletion pmm-app/src/pmm-check-home/components/Failed/Failed.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,21 @@ import * as styles from './Failed.styles';

interface FailedProps {
failed?: FailedChecks;
hasNoAccess: boolean;
isSttEnabled: boolean;
}

export const Failed: FC<FailedProps> = ({ failed = [0, 0, 0], isSttEnabled }) => {
export const Failed: FC<FailedProps> = ({ failed = [0, 0, 0], isSttEnabled, hasNoAccess }) => {
const sum = useMemo(() => failed.reduce((acc, val) => acc + val, 0), [failed]);

if (hasNoAccess) {
return (
<div className={styles.Empty} data-qa="db-check-panel-no-access">
Insufficient access rights.
</div>
);
}

if (!isSttEnabled) {
return (
<div className={styles.Empty} data-qa="db-check-panel-settings-link">
Expand Down
5 changes: 3 additions & 2 deletions pmm-app/src/pmm-check/CheckPanel.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ describe('CheckPanel::', () => {
await root.instance().fetchAlerts();
wrapper.update();

expect(root.state('dataSource')).toEqual(activeCheckStub);
expect(root.state().dataSource).toEqual(activeCheckStub);
expect(root.state().isLoading).toEqual(false);
expect(root.state().isSttEnabled).toEqual(false);

Expand All @@ -64,7 +64,8 @@ describe('CheckPanel::', () => {
root.setState({ isLoading: false });
wrapper.update();

expect(root.state('isLoading')).toEqual(false);
expect(root.state().isLoading).toEqual(false);
expect(root.state().hasNoAccess).toEqual(false);

const table = wrapper.find('[data-qa="db-check-panel"]').find(Table);
// Check if the table is rendered, the rest is tested by the Table itself
Expand Down
19 changes: 16 additions & 3 deletions pmm-app/src/pmm-check/CheckPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export interface CheckPanelProps extends PanelProps<CheckPanelOptions> {}

export interface CheckPanelState {
dataSource?: ActiveCheck[];
hasNoAccess: boolean;
isLoading: boolean;
isSttEnabled: boolean;
}
Expand All @@ -22,6 +23,7 @@ const history = createBrowserHistory();
export class CheckPanel extends PureComponent<CheckPanelProps, CheckPanelState> {
state = {
dataSource: undefined,
hasNoAccess: false,
isLoading: true,
isSttEnabled: false,
};
Expand Down Expand Up @@ -51,22 +53,27 @@ export class CheckPanel extends PureComponent<CheckPanelProps, CheckPanelState>
try {
const resp = (await CheckService.getSettings()) as Settings;
this.setState({ isSttEnabled: !!resp.settings?.stt_enabled });
this.setState({ hasNoAccess: false });

if (resp.settings?.stt_enabled) {
this.fetchAlerts();
} else {
this.setState({ isLoading: false });
}
} catch (err) {
console.error(err);
this.setState({ isLoading: false });
if (err.response?.status === 401) {
this.setState({ hasNoAccess: true });
}
console.error(err);
}
}

render() {
const {
options: { title },
} = this.props;
const { dataSource, isSttEnabled, isLoading } = this.state;
const { dataSource, isSttEnabled, isLoading, hasNoAccess } = this.state;

return (
<div className={styles.panel} data-qa="db-check-panel">
Expand All @@ -76,7 +83,13 @@ export class CheckPanel extends PureComponent<CheckPanelProps, CheckPanelState>
</div>
)}
{!isLoading && (
<Table caption={title} data={dataSource} columns={COLUMNS} isSttEnabled={isSttEnabled} />
<Table
caption={title}
data={dataSource}
columns={COLUMNS}
isSttEnabled={isSttEnabled}
hasNoAccess={hasNoAccess}
/>
)}
</div>
);
Expand Down
7 changes: 7 additions & 0 deletions pmm-app/src/pmm-check/components/Table/Table.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -52,4 +52,11 @@ describe('Table::', () => {
expect(table.find(TableHeader).length).toEqual(1);
expect(table.find(TableBody).length).toEqual(1);
});

it('should render the table with a message when the user only has reader access', () => {
const root = shallow(<Table caption="" columns={COLUMNS} isSttEnabled hasNoAccess />);

const empty = root.find('[data-qa="db-check-panel-no-access"]');
expect(empty.text()).toEqual('Insufficient access rights.');
});
});
18 changes: 17 additions & 1 deletion pmm-app/src/pmm-check/components/Table/Table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,30 @@ interface TableProps {
caption?: string;
columns: Column[];
data?: ActiveCheck[];
hasNoAccess?: boolean;
isSttEnabled: boolean;
}

export const Table: FC<TableProps> = ({ caption, columns, data = [], isSttEnabled }) => {
export const Table: FC<TableProps> = ({ caption, columns, data = [], isSttEnabled, hasNoAccess = false }) => {
const theme = useTheme();
const styles = getStyles(theme);
const isEmpty = !data.length;

if (hasNoAccess) {
return (
<>
<div className={styles.caption} data-qa="db-check-panel-table-caption">
{caption}
</div>
<div className={styles.wrapper}>
<div className={styles.empty} data-qa="db-check-panel-no-access">
Insufficient access rights.
</div>
</div>
</>
);
}

return (
<>
{caption && (
Expand Down
17 changes: 7 additions & 10 deletions pmm-app/src/pmm-settings/Parts/AlertManager/AlertManager.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
import { InputField } from '../../../react-plugins-deps/components/FormComponents/Input/Input';
import { TextAreaField } from '../../../react-plugins-deps/components/FormComponents/TextArea/TextArea';
import React, { ReactElement, useEffect, useState } from 'react';
import ButtonElement from '../../../react-plugins-deps/components/FormComponents/Button/Button';
import { Form as FormFinal } from 'react-final-form';
import { SettingsService } from '../../Settings.service';
import { showSuccessNotification } from '../../../react-plugins-deps/components/helpers/notification-manager';
import { FormElement } from '../../../react-plugins-deps/components/FormComponents/FormElement/FormElement';
import { PluginTooltip } from '../../../react-plugins-deps/components/helpers/Helpers';
import { css } from 'emotion';
import { Button, FormElement, InputField, TextAreaField } from 'react-plugins-deps/components/FormComponents';
import { showSuccessNotification } from 'react-plugins-deps/components/helpers/notification-manager';
import { PluginTooltip } from 'react-plugins-deps/components/helpers/Helpers';
import { SettingsService } from '../../Settings.service';
import { GUI_DOC_URL } from '../../panel.constants';

interface AlertManagerSettingsInterface {
Expand Down Expand Up @@ -61,7 +58,7 @@ const AlertManager = props => {
<form onSubmit={handleSubmit}>
<>
<FormElement
data-qa="form-field-am-url"
dataQa="form-field-am-url"
label="Alertmanager URL"
tooltip={
<PluginTooltip
Expand All @@ -83,7 +80,7 @@ const AlertManager = props => {
}
/>
<FormElement
data-qa="form-field-alerting-rules"
dataQa="form-field-alerting-rules"
label="Prometheus Alerting rules"
tooltip={
<PluginTooltip
Expand All @@ -105,7 +102,7 @@ const AlertManager = props => {
}
alignLabel="top"
/>
<ButtonElement loading={loading} text="Apply Alertmanager settings" />
<Button loading={loading} text="Apply Alertmanager settings" />
</>
</form>
);
Expand Down
15 changes: 8 additions & 7 deletions pmm-app/src/pmm-settings/Parts/Diagnostics/Diagnostics.test.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import Diagnostics from './Diagnostics';
import React from 'react';
import renderer from 'react-test-renderer';
import { shallow } from 'enzyme';
import Diagnostics from './Diagnostics';

describe('Diagnostics part', () => {
it('Renders diagnostics', () => {
const root = shallow(<Diagnostics />);

describe('Diagnostics part test', () => {
it('Renders correct', () => {
const component = renderer.create(<Diagnostics />);
const tree = component.toJSON();
expect(tree).toMatchSnapshot();
expect(root).toMatchSnapshot();
root.unmount();
});
});
Loading

0 comments on commit 4aa375e

Please sign in to comment.