Skip to content

Commit

Permalink
fix: add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
VikaCep committed Nov 19, 2024
1 parent 2702429 commit fcfd26a
Show file tree
Hide file tree
Showing 9 changed files with 281 additions and 7 deletions.
14 changes: 13 additions & 1 deletion src/components/ProbeCard/ProbeCard.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { userEvent } from '@testing-library/user-event';
import { DataTestIds } from 'test/dataTestIds';
import { OFFLINE_PROBE, ONLINE_PROBE, PRIVATE_PROBE, PUBLIC_PROBE } from 'test/fixtures/probes';
import { render } from 'test/render';
import { probeToExtendedProbe, runTestAsViewer } from 'test/utils';
import { probeToExtendedProbe, runTestAsRbacReader, runTestAsViewer } from 'test/utils';

import { type ExtendedProbe, ROUTES } from 'types';
import { getRoute } from 'components/Routing.utils';
Expand Down Expand Up @@ -91,6 +91,18 @@ it(`Displays the correct information for a private probe as a viewer`, async ()
expect(button).toHaveTextContent('View');
});

it(`Displays the correct information for a private probe as a RBAC viewer`, async () => {
runTestAsRbacReader();
const probe = probeToExtendedProbe(PRIVATE_PROBE);

render(<ProbeCard probe={probe} />);
await screen.findByText(probe.name, { exact: false });

const button = screen.getByTestId('probe-card-action-button');
expect(button).toBeInTheDocument();
expect(button).toHaveTextContent('View');
});

it(`Displays the correct information for a public probe`, async () => {
const probe = probeToExtendedProbe(PUBLIC_PROBE);

Expand Down
14 changes: 13 additions & 1 deletion src/components/ProbeEditor/ProbeEditor.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { config } from '@grafana/runtime';
import { screen } from '@testing-library/react';
import { PRIVATE_PROBE, PUBLIC_PROBE } from 'test/fixtures/probes';
import { render } from 'test/render';
import { fillProbeForm, probeToExtendedProbe, runTestAsViewer, UPDATED_VALUES } from 'test/utils';
import { fillProbeForm, probeToExtendedProbe, runTestAsRbacReader, runTestAsViewer, UPDATED_VALUES } from 'test/utils';

import { ExtendedProbe, FeatureName, Probe } from 'types';
import { TEMPLATE_PROBE } from 'page/NewProbe';
Expand Down Expand Up @@ -104,6 +104,12 @@ it('the form is uneditable when logged in as a viewer', async () => {
await assertUneditable();
});

it('the form is uneditable when logged in as a RBAC viewer', async () => {
runTestAsRbacReader();
await renderProbeEditor();
await assertUneditable();
});

it('the form actions are unavailable when viewing a public probe', async () => {
await renderProbeEditor({ probe: PUBLIC_PROBE });
await assertNoActions();
Expand All @@ -115,6 +121,12 @@ it('the form actions are unavailable as a viewer', async () => {
await assertNoActions();
});

it('the form actions are unavailable as a RBAC viewer', async () => {
runTestAsRbacReader();
await renderProbeEditor();
await assertNoActions();
});

async function assertUneditable() {
const nameInput = await screen.findByLabelText('Probe Name', { exact: false });
expect(nameInput).toBeDisabled();
Expand Down
10 changes: 9 additions & 1 deletion src/components/ProbeStatus/ProbeStatus.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React from 'react';
import { screen, waitFor } from '@testing-library/react';
import { OFFLINE_PROBE, ONLINE_PROBE, PRIVATE_PROBE } from 'test/fixtures/probes';
import { render } from 'test/render';
import { probeToExtendedProbe, runTestAsViewer } from 'test/utils';
import { probeToExtendedProbe, runTestAsRbacReader, runTestAsViewer } from 'test/utils';

import { formatDate } from 'utils';

Expand All @@ -16,6 +16,14 @@ it(`hides the reset button when the user is a viewer`, async () => {
expect(resetButton).not.toBeInTheDocument();
});

it(`hides the reset button when the user is a RBAC viewer`, async () => {
runTestAsRbacReader();
// We need to wait for contexts to finish loading to avoid issue with act
await waitFor(() => render(<ProbeStatus probe={probeToExtendedProbe(PRIVATE_PROBE)} onReset={jest.fn()} />));
const resetButton = await getResetButton(true);
expect(resetButton).not.toBeInTheDocument();
});

it(`shows the reset probe access token when the user is an editor`, async () => {
render(<ProbeStatus probe={probeToExtendedProbe(PRIVATE_PROBE)} onReset={jest.fn()} />);
const resetButton = await getResetButton();
Expand Down
40 changes: 39 additions & 1 deletion src/page/CheckRouter.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React from 'react';
import { screen, waitFor } from '@testing-library/react';
import { BASIC_HTTP_CHECK, BASIC_SCRIPTED_CHECK } from 'test/fixtures/checks';
import { render } from 'test/render';
import { runTestAsViewer } from 'test/utils';
import { runTestAsRbacEditor, runTestAsRbacReader, runTestAsViewer } from 'test/utils';

import { CheckType, CheckTypeGroup, ROUTES } from 'types';
import { PLUGIN_URL_PATH } from 'components/Routing.consts';
Expand Down Expand Up @@ -102,3 +102,41 @@ describe(`<CheckRouter />`, () => {
});
});
});

describe('RBAC Permissions', () => {
describe('When user is viewer', () => {
beforeEach(() => {
runTestAsRbacReader();
});
it(`Should not load the edit check route and redirect to the homepage`, async () => {
const checkType = CheckType.Scripted;
const checkID = BASIC_SCRIPTED_CHECK.id;

const { history } = render(<CheckRouter />, {
path: `${PLUGIN_URL_PATH}${ROUTES.Checks}/edit/${checkType}/${checkID}`,
route: `${PLUGIN_URL_PATH}${ROUTES.Checks}`,
});

await waitFor(() => expect(history.location.pathname).toBe(`${PLUGIN_URL_PATH}${ROUTES.Checks}`));
});
});

describe('When user is editor', () => {
beforeEach(() => {
runTestAsRbacEditor();
});

it(`Should load the edit check route`, async () => {
const checkType = CheckType.Scripted;
const checkID = BASIC_SCRIPTED_CHECK.id;

render(<CheckRouter />, {
path: `${PLUGIN_URL_PATH}${ROUTES.Checks}/edit/${checkType}/${checkID}`,
route: `${PLUGIN_URL_PATH}${ROUTES.Checks}`,
});

const title = await screen.findByText(`Editing ${BASIC_SCRIPTED_CHECK.job}`);
expect(title).toBeInTheDocument();
});
});
});
94 changes: 93 additions & 1 deletion src/page/ConfigPage/ConfigPage.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,13 @@ import { screen } from '@testing-library/react';
import { LOGS_DATASOURCE, METRICS_DATASOURCE, SM_DATASOURCE } from 'test/fixtures/datasources';
import { CREATE_ACCESS_TOKEN } from 'test/fixtures/tokens';
import { render } from 'test/render';
import { runTestWithoutLogsAccess, runTestWithoutMetricsAccess } from 'test/utils';
import {
runTestAsRbacAdmin,
runTestAsRbacEditor,
runTestAsRbacReader,
runTestWithoutLogsAccess,
runTestWithoutMetricsAccess,
} from 'test/utils';

import { ConfigPage } from './ConfigPage';

Expand Down Expand Up @@ -92,3 +98,89 @@ describe(`<ConfigPage /> initialised state`, () => {
expect(pluginVersion).toBeInTheDocument();
});
});

describe('RBAC Permissions', () => {
describe('When user is viewer', () => {
beforeEach(() => {
runTestAsRbacReader();
});
it(`does not render the setup button`, async () => {
render(<ConfigPage />);

const setupButton = await screen.queryByText(/Setup/i);
expect(setupButton).not.toBeInTheDocument();
});

it(`does not render access token generation`, async () => {
render(<ConfigPage initialized />);

const accessTokenButton = await screen.queryByText(/Generate access token/);
expect(accessTokenButton).not.toBeInTheDocument();
});

it(`does not render disabling the plugin`, async () => {
render(<ConfigPage initialized />);

const disableButton = await screen.queryByText(/Disable synthetic monitoring/i);
expect(disableButton).not.toBeInTheDocument();
});
});

describe('When user is editor', () => {
beforeEach(() => {
runTestAsRbacEditor();
});

it(`renders the setup button`, async () => {
render(<ConfigPage />);

const setupButton = await screen.findByText(/Setup/i);
expect(setupButton).toBeInTheDocument();
});

it(`does not render access token generation`, async () => {
render(<ConfigPage initialized />);

const accessTokenButton = await screen.queryByText(/Generate access token/);
expect(accessTokenButton).not.toBeInTheDocument();
});

it(`does not render disabling the plugin`, async () => {
render(<ConfigPage initialized />);

const disableButton = await screen.queryByText(/Disable synthetic monitoring/i);
expect(disableButton).not.toBeInTheDocument();
});
});

describe('When user is admin', () => {
beforeEach(() => {
runTestAsRbacAdmin();
});

it(`renders the setup button`, async () => {
render(<ConfigPage />);

const setupButton = await screen.findByText(/Setup/i);
expect(setupButton).toBeInTheDocument();
});

it(`renders access token generation and can generate a token`, async () => {
const { user } = render(<ConfigPage initialized />);

const accessTokenButton = await screen.findByText(/Generate access token/);
expect(accessTokenButton).toBeInTheDocument();
await user.click(accessTokenButton);

const accessToken = await screen.findByText(CREATE_ACCESS_TOKEN);
expect(accessToken).toBeInTheDocument();
});

it(`renders disabling the plugin`, async () => {
render(<ConfigPage initialized />);

const disableButton = await screen.findByText(/Disable synthetic monitoring/i);
expect(disableButton).toBeInTheDocument();
});
});
});
8 changes: 7 additions & 1 deletion src/page/EditCheck/__tests__/EditCheck.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { screen } from '@testing-library/react';
import { BASIC_HTTP_CHECK } from 'test/fixtures/checks';
import { apiRoute } from 'test/handlers';
import { server } from 'test/server';
import { runTestAsViewer } from 'test/utils';
import { runTestAsRbacReader, runTestAsViewer } from 'test/utils';

import { renderEditForm } from 'page/__testHelpers__/checkForm';

Expand Down Expand Up @@ -59,4 +59,10 @@ describe(`<EditCheck />`, () => {
await renderEditForm(BASIC_HTTP_CHECK);
expect(screen.getByRole(`button`, { name: `Submit` })).toBeDisabled();
});

it(`disables the form when the user is a RBAC viewer`, async () => {
runTestAsRbacReader();
await renderEditForm(BASIC_HTTP_CHECK);
expect(screen.getByRole(`button`, { name: `Submit` })).toBeDisabled();
});
});
50 changes: 50 additions & 0 deletions src/test/fixtures/rbacPermissions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
export const FULL_ADMIN_ACCESS = {
'grafana-synthetic-monitoring-app:read': true,
'grafana-synthetic-monitoring-app:write': true,
'grafana-synthetic-monitoring-app.plugin:enable': true,
'grafana-synthetic-monitoring-app.plugin:disable': true,
'grafana-synthetic-monitoring-app.checks:write': true,
'grafana-synthetic-monitoring-app.probes:write': true,
'grafana-synthetic-monitoring-app.alerts:write': true,
'grafana-synthetic-monitoring-app.thresholds:write': true,
'grafana-synthetic-monitoring-app.tokens:write': true,
'grafana-synthetic-monitoring-app.checks:read': true,
'grafana-synthetic-monitoring-app.probes:read': true,
'grafana-synthetic-monitoring-app.alerts:read': true,
'grafana-synthetic-monitoring-app.thresholds:read': true,
'grafana-synthetic-monitoring-app.tokens:read': true,
'grafana-synthetic-monitoring-app.checks:delete': true,
'grafana-synthetic-monitoring-app.probes:delete': true,
'grafana-synthetic-monitoring-app.alerts:delete': true,
'grafana-synthetic-monitoring-app.thresholds:delete': true,
'grafana-synthetic-monitoring-app.tokens:delete': true,
};

export const FULL_WRITER_ACCESS = {
'grafana-synthetic-monitoring-app:read': true,
'grafana-synthetic-monitoring-app:write': true,
'grafana-synthetic-monitoring-app.checks:write': true,
'grafana-synthetic-monitoring-app.probes:write': true,
'grafana-synthetic-monitoring-app.alerts:write': true,
'grafana-synthetic-monitoring-app.thresholds:write': true,
'grafana-synthetic-monitoring-app.tokens:write': true,
'grafana-synthetic-monitoring-app.checks:read': true,
'grafana-synthetic-monitoring-app.probes:read': true,
'grafana-synthetic-monitoring-app.alerts:read': true,
'grafana-synthetic-monitoring-app.thresholds:read': true,
'grafana-synthetic-monitoring-app.tokens:read': true,
'grafana-synthetic-monitoring-app.checks:delete': true,
'grafana-synthetic-monitoring-app.probes:delete': true,
'grafana-synthetic-monitoring-app.alerts:delete': true,
'grafana-synthetic-monitoring-app.thresholds:delete': true,
'grafana-synthetic-monitoring-app.tokens:delete': true,
};

export const FULL_READONLY_ACCESS = {
'grafana-synthetic-monitoring-app:read': true,
'grafana-synthetic-monitoring-app.checks:read': true,
'grafana-synthetic-monitoring-app.probes:read': true,
'grafana-synthetic-monitoring-app.alerts:read': true,
'grafana-synthetic-monitoring-app.thresholds:read': true,
'grafana-synthetic-monitoring-app.tokens:read': true,
};
3 changes: 2 additions & 1 deletion src/test/mocks/@grafana/runtime.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ import { BackendSrvRequest } from '@grafana/runtime';
import axios from 'axios';
import { from } from 'rxjs';
import { LOGS_DATASOURCE, METRICS_DATASOURCE, SM_DATASOURCE } from 'test/fixtures/datasources';
import { FULL_ADMIN_ACCESS } from 'test/fixtures/rbacPermissions';

import { SMDataSource } from 'datasource/DataSource';

jest.mock('@grafana/runtime', () => {
const actual = jest.requireActual('@grafana/runtime');

return {
...actual,
config: {
Expand All @@ -25,6 +25,7 @@ jest.mock('@grafana/runtime', () => {
user: {
...actual.config.user,
orgRole: OrgRole.Admin,
permissions: FULL_ADMIN_ACCESS,
},
},
},
Expand Down
Loading

0 comments on commit fcfd26a

Please sign in to comment.