Skip to content

Commit

Permalink
Checks catalog stories (#1953)
Browse files Browse the repository at this point in the history
* Make ChecksCatalog component storybookable

* Add ChecksCatalog stories

* Use concat function properly
  • Loading branch information
arbulu89 authored Oct 26, 2023
1 parent c7fee85 commit a8a1bf8
Show file tree
Hide file tree
Showing 6 changed files with 154 additions and 71 deletions.
39 changes: 9 additions & 30 deletions assets/js/components/ChecksCatalog/ChecksCatalog.jsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,7 @@
/* eslint-disable react/no-array-index-key */
import React, { useState, useEffect } from 'react';
import { useSelector, useDispatch } from 'react-redux';
import React, { useEffect, useState } from 'react';
import { groupBy } from 'lodash';

import { getCatalog } from '@state/selectors/catalog';
import { updateCatalog } from '@state/actions/catalog';
import {
providerData,
checkProviderExists,
} from '@components/ProviderLabel/ProviderLabel';
import { providerData } from '@components/ProviderLabel/ProviderLabel';
import PageHeader from '@components/PageHeader';
import Accordion from '@components/Accordion';
import CatalogContainer from './CatalogContainer';
Expand All @@ -22,27 +15,13 @@ const updatedProvider = {
...providerData,
};

const buildUpdateCatalogAction = (provider) => {
const payload = checkProviderExists(provider)
? { provider, target_type: 'cluster' }
: {};
return updateCatalog(payload);
};

// eslint-disable-next-line import/prefer-default-export
function ChecksCatalog() {
const dispatch = useDispatch();
function ChecksCatalog({ catalogData, catalogError, loading, updateCatalog }) {
const [selectedProvider, setProviderSelected] = useState(ALL_FILTER);

const {
data: catalogData,
error: catalogError,
loading,
} = useSelector(getCatalog());

useEffect(() => {
dispatch(buildUpdateCatalogAction(selectedProvider));
}, [dispatch, selectedProvider]);
updateCatalog(selectedProvider);
}, [selectedProvider]);

return (
<>
<div className="flex">
Expand All @@ -55,15 +34,15 @@ function ChecksCatalog() {
/>
</div>
<CatalogContainer
onRefresh={() => dispatch(buildUpdateCatalogAction(selectedProvider))}
onRefresh={() => updateCatalog(selectedProvider)}
isCatalogEmpty={catalogData.length === 0}
catalogError={catalogError}
loading={loading}
>
<div>
{Object.entries(groupBy(catalogData, 'group')).map(
([group, checks], idx) => (
<ul key={idx}>
([group, checks]) => (
<ul key={group}>
<Accordion
defaultOpen
className="check-group mb-4"
Expand Down
82 changes: 82 additions & 0 deletions assets/js/components/ChecksCatalog/ChecksCatalog.stories.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import React from 'react';
import { MemoryRouter } from 'react-router-dom';
import { faker } from '@faker-js/faker';

import { catalogCheckFactory } from '@lib/test-utils/factories';
import ChecksCatalog from './ChecksCatalog';

const groupName1 = faker.string.uuid();
const groupName2 = faker.string.uuid();
const groupName3 = faker.string.uuid();
const group1 = catalogCheckFactory.buildList(5, { group: groupName1 });
const group2 = catalogCheckFactory.buildList(5, { group: groupName2 });
const group3 = catalogCheckFactory.buildList(5, { group: groupName3 });
const catalogData = group1.concat(group2, group3);

function ContainerWrapper({ children }) {
return (
<div className="max-w-7xl mx-auto px-4 sm:px-6 md:px-8">{children}</div>
);
}

export default {
title: 'Layouts/ChecksCatalog',
component: ChecksCatalog,
argTypes: {
catalogData: {
control: 'object',
description: 'Catalog content',
},
catalogError: {
control: 'text',
description: 'Error message getting catalog data',
table: {
type: { summary: 'string' },
},
},
loading: {
control: { type: 'boolean' },
description: 'Catalog data is being loaded',
table: {
type: { summary: 'string' },
defaultValue: { summary: false },
},
},
updateCatalog: {
action: 'Update catalog',
description: 'Update catalog content',
},
},
decorators: [
(Story) => (
<MemoryRouter>
<Story />
</MemoryRouter>
),
],
render: (args) => (
<ContainerWrapper>
<ChecksCatalog {...args} />
</ContainerWrapper>
),
};

export const Default = {
args: {
catalogData,
},
};

export const Loading = {
args: {
...Default.args,
loading: true,
},
};

export const Error = {
args: {
...Default.args,
catalogError: 'Error loading catalog',
},
};
59 changes: 22 additions & 37 deletions assets/js/components/ChecksCatalog/ChecksCatalog.test.jsx
Original file line number Diff line number Diff line change
@@ -1,30 +1,32 @@
import React from 'react';

import { screen, within, act, waitFor } from '@testing-library/react';
import { screen, within, render } from '@testing-library/react';
import '@testing-library/jest-dom';
import userEvent from '@testing-library/user-event';

import { faker } from '@faker-js/faker';
import { withState, renderWithRouter } from '@lib/test-utils';
import { catalogCheckFactory } from '@lib/test-utils/factories';

import ChecksCatalog from './ChecksCatalog';

describe('ChecksCatalog ChecksCatalog component', () => {
it('should render the checks catalog with fetched data', async () => {
it('should render the checks catalog with fetched data', () => {
const groupName1 = faker.string.uuid();
const groupName2 = faker.string.uuid();
const group1 = catalogCheckFactory.buildList(5, { group: groupName1 });
const group2 = catalogCheckFactory.buildList(5, { group: groupName2 });
const catalogData = group1.concat(group2);

const initialState = {
catalog: { loading: false, data: [...group1, ...group2], error: null },
};
const [statefulCatalog, store] = withState(<ChecksCatalog />, initialState);
const mockUpdateCatalog = jest.fn();

await act(async () => renderWithRouter(statefulCatalog));
render(
<ChecksCatalog
catalogData={catalogData}
updateCatalog={mockUpdateCatalog}
/>
);

const groups = await waitFor(() => screen.getAllByRole('list'));
const groups = screen.getAllByRole('list');
expect(groups.length).toBe(2);

groups.forEach((group) => {
Expand All @@ -33,46 +35,29 @@ describe('ChecksCatalog ChecksCatalog component', () => {
expect(checks.length).toBe(5);
});

const actions = store.getActions();
const expectedActions = [
{
type: 'UPDATE_CATALOG',
payload: {},
},
];
expect(actions).toEqual(expectedActions);
expect(mockUpdateCatalog).toHaveBeenCalledWith('all');
});

it('should query the catalog with the correct provider', async () => {
const user = userEvent.setup();

const catalog = catalogCheckFactory.buildList(5);
const catalogData = catalogCheckFactory.buildList(5);
const mockUpdateCatalog = jest.fn();

const initialState = {
catalog: { loading: false, data: catalog, error: null },
};

const [statefulCatalog, store] = withState(<ChecksCatalog />, initialState);

await act(async () => renderWithRouter(statefulCatalog, store));
render(
<ChecksCatalog
catalogData={catalogData}
updateCatalog={mockUpdateCatalog}
/>
);

await user.click(screen.getByText('All'));

const providerFilter = screen.getByText('AWS');

await user.click(providerFilter);

const actions = store.getActions();
const expectedActions = [
{
type: 'UPDATE_CATALOG',
payload: {},
},
{
type: 'UPDATE_CATALOG',
payload: { provider: 'aws', target_type: 'cluster' },
},
];
expect(actions).toEqual(expectedActions);
expect(mockUpdateCatalog).toHaveBeenNthCalledWith(1, 'all');
expect(mockUpdateCatalog).toHaveBeenNthCalledWith(2, 'aws');
});
});
37 changes: 37 additions & 0 deletions assets/js/components/ChecksCatalog/ChecksCatalogPage.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import React from 'react';
import { useSelector, useDispatch } from 'react-redux';

import { getCatalog } from '@state/selectors/catalog';
import { updateCatalog } from '@state/actions/catalog';
import { checkProviderExists } from '@components/ProviderLabel/ProviderLabel';
import ChecksCatalog from './ChecksCatalog';

const buildUpdateCatalogAction = (provider) => {
const payload = checkProviderExists(provider)
? { provider, target_type: 'cluster' }
: {};
return updateCatalog(payload);
};

function ChecksCatalogPage() {
const dispatch = useDispatch();

const {
data: catalogData,
error: catalogError,
loading,
} = useSelector(getCatalog());

return (
<ChecksCatalog
catalogData={catalogData}
catalogError={catalogError}
loading={loading}
updateCatalog={(selectedProvider) =>
dispatch(buildUpdateCatalogAction(selectedProvider))
}
/>
);
}

export default ChecksCatalogPage;
4 changes: 2 additions & 2 deletions assets/js/components/ChecksCatalog/index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
import ChecksCatalog from './ChecksCatalog';
import ChecksCatalogPage from './ChecksCatalogPage';

export default ChecksCatalog;
export default ChecksCatalogPage;
4 changes: 2 additions & 2 deletions assets/js/trento.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import { ExecutionResultsPage } from '@components/ExecutionResults';
import SapSystemsOverviewPage from '@components/SapSystemsOverview';
import HostDetailsPage, { HostSettingsPage } from '@components/HostDetails';
import DatabasesOverviewPage from '@components/DatabasesOverview';
import ChecksCatalog from '@components/ChecksCatalog';
import ChecksCatalogPage from '@components/ChecksCatalog';
import NotFound from '@components/NotFound';
import SomethingWentWrong from '@components/SomethingWentWrong';
import SaptuneDetailsPage from '@components/SaptuneDetails';
Expand Down Expand Up @@ -75,7 +75,7 @@ function App() {
element={<SapSystemsOverviewPage />}
/>
<Route path="databases" element={<DatabasesOverviewPage />} />
<Route path="catalog" element={<ChecksCatalog />} />
<Route path="catalog" element={<ChecksCatalogPage />} />
<Route path="settings" element={<Settings />} />
<Route path="about" element={<AboutPage />} />
<Route path="hosts/:hostID" element={<HostDetailsPage />} />
Expand Down

0 comments on commit a8a1bf8

Please sign in to comment.