Skip to content

Commit

Permalink
Implement tests for the page and header components
Browse files Browse the repository at this point in the history
  • Loading branch information
gkarat committed Feb 21, 2023
1 parent a010397 commit 9b770f9
Show file tree
Hide file tree
Showing 8 changed files with 236 additions and 11 deletions.
38 changes: 38 additions & 0 deletions cypress/fixtures/groups/620f9ae75A8F6b83d78F3B55Af1c4b2C.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
{
"count": 1,
"page": 1,
"per_page": 50,
"results": [
{
"name": "ea velit incididunt",
"updated_at": "1998-04-17T22:00:00.0Z",
"id": "620f9ae75A8F6b83d78F3B55Af1c4b2C",
"account": "irure ea exercitation adipisicing velit",
"org_id": "non",
"created_at": "1994-07-28T22:00:00.0Z",
"host_ids": [
"eEfb7FAa-1f0b-Bde3-a4FF-fDdCd5faA764",
"bb7417faE7f9eCdacEDDd0Fcae9Cf4BB",
"2095BB72Aa6E1d2D1DC48bdecF1085eb",
"E645A3Fb42B77c4eBf9faEfCad8f6F5a",
"7fb4fa758Cbc0A861C2Cb21695aeA9d6",
"f6BE4AafA6bF543693Fa3F1fadFaA4E9",
"D608C33f-5e6D-BBEF-Cab5-0FFE8eB1bAc4",
"Dd4De9b6-7f3a-ED3d-2a84-D60e4Af2Cd9d",
"ae08E8dd-FFdB-cBC1-BA2A-d0aaC61C1B55",
"dcaD88bD4CeaaDC8bceD5d730ffba4cF",
"5a9F9CDAE74F3116a9c848Eeb1C65EA0",
"f53eDCBe3Fb957BE5dBec9322f030F94",
"c6fbBE38-30D7-D7e9-C8C7-72F4a61Bea9c",
"20E5EedA1e3f2aC2dCaADDCa4BFEED5B",
"adEcDf6ac4A999ccecdbCe7E9e01e23C",
"Bf0E2e8C-7e96-f0C8-9fea-1bD5fa9E18ce",
"6349ADdf-8d6B-bF1e-F5AE-13f0B7ca4acE",
"DBD5E149-C967-12b3-Cc6B-6c9220bA32e1",
"4EC19BbD-b556-ED9E-33E7-Eb5Be40AaeDe",
"CE05B39b3FdDad8dDE2b5DebB7CABe7D"
]
}
],
"total": 1
}
28 changes: 28 additions & 0 deletions cypress/support/interceptors.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/* eslint-disable camelcase */
import { DEFAULT_ROW_COUNT } from '@redhat-cloud-services/frontend-components-utilities';
import fixtures from '../fixtures/groups.json';
import groupDetailFixtures from '../fixtures/groups/620f9ae75A8F6b83d78F3B55Af1c4b2C.json';

export const groupsInterceptors = {
'successful with some items': () =>
Expand Down Expand Up @@ -31,3 +32,30 @@ export const groupsInterceptors = {
}).as('getGroups');
}
};

export const groupDetailInterceptors = {
successful: () =>
cy
.intercept('GET', '/api/inventory/v1/groups/620f9ae75A8F6b83d78F3B55Af1c4b2C', groupDetailFixtures)
.as('getGroupDetail'),
empty: () =>
cy
.intercept('GET', '/api/inventory/v1/groups/620f9ae75A8F6b83d78F3B55Af1c4b2C', { statusCode: 404 })
.as('getGroupDetail'),
'failed with server error': () => {
Cypress.on('uncaught:exception', () => {
return false;
});
cy.intercept('GET', '/api/inventory/v1/groups/620f9ae75A8F6b83d78F3B55Af1c4b2C', { statusCode: 500 }).as(
'getGroupDetail'
);
},
'long responding': () => {
cy.intercept('GET', '/api/inventory/v1/groups/620f9ae75A8F6b83d78F3B55Af1c4b2C', (req) => {
req.reply({
body: groupDetailFixtures,
delay: 42000000 // milliseconds
});
}).as('getGroupDetail');
}
};
12 changes: 8 additions & 4 deletions src/components/InventoryGroupDetail/GroupDetailHeader.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,18 @@ import {
} from '@redhat-cloud-services/frontend-components';
import React from 'react';
import { useSelector } from 'react-redux';
import { Link, useParams } from 'react-router-dom';
import { Link } from 'react-router-dom';
import { routes } from '../../Routes';
import PropTypes from 'prop-types';

const GroupDetailHeader = () => {
const GroupDetailHeader = ({ groupId }) => {
const { uninitialized, loading, data } = useSelector((state) => state.groupDetail);
const { groupId } = useParams();

const nameOrId = uninitialized || loading ? (
<Skeleton width="250px" screenreaderText="Loading group details" />
) : (
// in case of error, render just id from URL
data?.name || groupId
data?.results?.[0]?.name || groupId
);

return (
Expand All @@ -32,4 +32,8 @@ const GroupDetailHeader = () => {
);
};

GroupDetailHeader.propTypes = {
groupId: PropTypes.string.isRequired
};

export default GroupDetailHeader;
57 changes: 57 additions & 0 deletions src/components/InventoryGroupDetail/InventoryGroupDetail.cy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { mount } from '@cypress/react';
import React from 'react';
import { Provider } from 'react-redux';
import { MemoryRouter } from 'react-router-dom';
import groupDetailFixtures from '../../../cypress/fixtures/groups/620f9ae75A8F6b83d78F3B55Af1c4b2C.json';
import { groupDetailInterceptors as interceptors } from '../../../cypress/support/interceptors';
import { getStore } from '../../store';
import InventoryGroupDetail from './InventoryGroupDetail';

const TEST_GROUP_ID = '620f9ae75A8F6b83d78F3B55Af1c4b2C';

const mountPage = () =>
mount(
<Provider store={getStore()}>
<MemoryRouter>
<InventoryGroupDetail groupId={TEST_GROUP_ID} />
</MemoryRouter>
</Provider>
);

before(() => {
cy.window().then(
(window) =>
(window.insights = {
chrome: {
isProd: false,
auth: {
getUser: () => {
return Promise.resolve({});
}
}
}
})
);
});

describe('group detail page', () => {
it('name from server is rendered in header and breadcrumb', () => {
interceptors.successful();
mountPage();

cy.wait('@getGroupDetail');
cy.get('h1').contains(groupDetailFixtures.results[0].name);
cy.get('[data-ouia-component-type="PF4/Breadcrumb"] li')
.last()
.should('have.text', groupDetailFixtures.results[0].name);
});

it('skeletons rendered while fetching data', () => {
interceptors['long responding']();
mountPage();

cy.get('[data-ouia-component-type="PF4/Breadcrumb"] li').last().find('.pf-c-skeleton');
cy.get('h1').find('.pf-c-skeleton');
cy.get('.pf-c-empty-state').find('.pf-c-spinner');
});
});
14 changes: 8 additions & 6 deletions src/components/InventoryGroupDetail/InventoryGroupDetail.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import React, { useEffect } from 'react';
import { useParams } from 'react-router-dom';
import useChrome from '@redhat-cloud-services/frontend-components/useChrome';
import { useDispatch, useSelector } from 'react-redux';
import { fetchGroupDetail } from '../../store/inventory-actions';
Expand All @@ -8,21 +7,20 @@ import { useState } from 'react';
import GroupDetailHeader from './GroupDetailHeader';
import GroupDetailSystems from './GroupDetailSystems';
import GroupDetailInfo from './GroupDetailInfo';
import PropTypes from 'prop-types';

const InventoryGroupDetail = () => {
const InventoryGroupDetail = ({ groupId }) => {
const dispatch = useDispatch();
const { data } = useSelector((state) => state.groupDetail);
const chrome = useChrome();

const { groupId } = useParams();

useEffect(() => {
dispatch(fetchGroupDetail(groupId));
}, []);

useEffect(() => {
// if available, change ID to the group's name in the window title
chrome.updateDocumentTitle(
chrome?.updateDocumentTitle?.(
`${data?.name || groupId} - Inventory Groups | Red Hat Insights`
);
}, [data]);
Expand All @@ -31,7 +29,7 @@ const InventoryGroupDetail = () => {

return (
<React.Fragment>
<GroupDetailHeader />
<GroupDetailHeader groupId={groupId} />
<PageSection variant='light' type='tabs'>
<Tabs
activeKey={activeTabKey}
Expand All @@ -57,4 +55,8 @@ const InventoryGroupDetail = () => {
);
};

InventoryGroupDetail.propTypes = {
groupId: PropTypes.string.isRequired
};

export default InventoryGroupDetail;
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import '@testing-library/jest-dom';
import { render } from '@testing-library/react';
import React from 'react';
import { MemoryRouter } from 'react-router-dom';
import GroupDetailHeader from '../GroupDetailHeader';

jest.mock('react-redux', () => {
return {
...jest.requireActual('react-redux'),
useSelector: () => ({
uninitialized: false,
loading: false,
data: {
results: [
{
name: 'group-name-1'
}
]
}
})
};
});

describe('group detail header', () => {
let getByRole;

beforeEach(() => {
const rendered = render(
<MemoryRouter>
<GroupDetailHeader groupId="group-id-2" />
</MemoryRouter>
);
getByRole = rendered.getByRole;
});

it('renders title and breadcrumbs', () => {
expect(getByRole('heading')).toBeInTheDocument();
});

it('has breadcrumbs', () => {
expect(getByRole('navigation')).toHaveClass('pf-c-breadcrumb');
expect(getByRole('navigation')).toHaveTextContent('group-name-1');
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import '@testing-library/jest-dom';
import { render } from '@testing-library/react';
import React from 'react';
import { MemoryRouter } from 'react-router-dom';
import InventoryGroupDetail from '../InventoryGroupDetail';

jest.mock('react-redux', () => {
return {
...jest.requireActual('react-redux'),
useSelector: () => ({
uninitialized: false,
loading: false,
data: {
results: [
{
name: 'group-name-1'
}
]
}
}),
useDispatch: () => () => {}
};
});

describe('group detail page component', () => {
let getByRole;
let container;

beforeEach(() => {
const rendered = render(
<MemoryRouter>
<InventoryGroupDetail groupId="group-id-2" />
</MemoryRouter>
);
getByRole = rendered.getByRole;
container = rendered.container;
});

it('renders two tabs', () => {
expect(getByRole('tablist')).toBeInTheDocument();
expect(container.querySelectorAll('.pf-c-tabs__item')[0]).toHaveTextContent('Systems');
expect(container.querySelectorAll('.pf-c-tabs__item')[1]).toHaveTextContent('Group info');
});
});
10 changes: 9 additions & 1 deletion src/components/InventoryGroupDetail/index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
import React from 'react';
import { useParams } from 'react-router-dom';
import InventoryGroupDetail from './InventoryGroupDetail';

export default InventoryGroupDetail;
const InventoryGroupDetailWrapper = () => {
const { groupId } = useParams();

return <InventoryGroupDetail groupId={groupId} />;
};

export default InventoryGroupDetailWrapper;

0 comments on commit 9b770f9

Please sign in to comment.