Skip to content

Commit

Permalink
fix: Render spinner before zero state or route is rendered
Browse files Browse the repository at this point in the history
This adds isLoading flag to Routes to indicate the state when component does not know yet about the number of systems available yet.
  • Loading branch information
gkarat committed Jan 5, 2024
1 parent d0b1280 commit c0536f0
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 56 deletions.
19 changes: 11 additions & 8 deletions src/Routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,13 @@ import React, {
import { Navigate, useRoutes } from 'react-router-dom';
import RenderWrapper from './Utilities/Wrapper';
import useFeatureFlag from './Utilities/useFeatureFlag';
import { Bullseye, Spinner } from '@patternfly/react-core';
import LostPage from './components/LostPage';
import AsyncComponent from '@redhat-cloud-services/frontend-components/AsyncComponent';
import ErrorState from '@redhat-cloud-services/frontend-components/ErrorState';
import { inventoryHasEdgeSystems } from './Utilities/edge';
import { inventoryHasConventionalSystems } from './Utilities/conventional';
import Fallback from './components/SpinnerFallback';

const InventoryOrEdgeGroupDetailsView = lazy(() =>
import('./routes/InventoryOrEdgeGroupDetailsComponent')
);
Expand Down Expand Up @@ -47,6 +48,8 @@ export const AccountStatContext = createContext({
export const Routes = () => {
const [hasConventionalSystems, setHasConventionalSystems] = useState(true);
const [hasEdgeDevices, setHasEdgeDevices] = useState(true);
const [isLoading, setIsLoading] = useState(true);

const edgeParityInventoryListEnabled = useFeatureFlag(
'edgeParity.inventory-list'
);
Expand All @@ -64,6 +67,8 @@ export const Routes = () => {
const hasEdgeSystems = await inventoryHasEdgeSystems();
setHasEdgeDevices(hasEdgeSystems);
}

setIsLoading(false);
})();
} catch (e) {
console.error(e);
Expand Down Expand Up @@ -113,14 +118,12 @@ export const Routes = () => {
? hasEdgeDevices || hasConventionalSystems
: hasConventionalSystems;

if (isLoading) {
return <Fallback />;
}

return !hasSystems ? (
<Suspense
fallback={
<Bullseye>
<Spinner size="xl" />
</Bullseye>
}
>
<Suspense fallback={<Fallback />}>
<AsyncComponent
appId={'inventory_zero_state'}
appName="dashboard"
Expand Down
101 changes: 53 additions & 48 deletions src/Routes.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,13 @@ import React, { Suspense } from 'react';
import { MemoryRouter } from 'react-router-dom';
import { Routes } from './Routes';
import useFeatureFlag from './Utilities/useFeatureFlag';
import InventoryGroups from './components/InventoryGroups';
import { inventoryHasConventionalSystems } from './Utilities/conventional';
import { inventoryHasEdgeSystems } from './Utilities/edge';

jest.mock('./Utilities/useFeatureFlag');
jest.mock('./components/InventoryGroups');
jest.mock('./routes/InventoryOrEdgeComponent', () => () => (
<span>Groups component</span>
));
jest.mock('./Utilities/conventional');
jest.mock('./Utilities/edge');
jest.mock(
Expand All @@ -28,69 +29,73 @@ const TestWrapper = ({ route }) => (
</MemoryRouter>
);

describe('/groups', () => {
InventoryGroups.mockReturnValue(<div>Inventory groups component</div>);
describe('routes', () => {
afterEach(() => {
jest.clearAllMocks();
});

useFeatureFlag.mockImplementation(
(flag) =>
({
'edgeParity.inventory-list': false,
}[flag])
);
useFeatureFlag.mockReturnValue({
'edgeParity.inventory-list': true, // to be removed once feature flag is gone
});

it('renders fallback on lazy load first', async () => {
render(<TestWrapper route={'/groups'} />);
describe('/groups', () => {
inventoryHasConventionalSystems.mockReturnValue(true);
inventoryHasEdgeSystems.mockReturnValue(true);

it('renders fallback on lazy load first', async () => {
render(<TestWrapper route={'/groups'} />);

await waitFor(() => {
expect(screen.getByText('Loading')).toBeVisible();
await waitFor(() => {
expect(screen.getByText('Loading')).toBeVisible();
});
});
});

it('renders the groups page content', async () => {
render(<TestWrapper route={'/groups'} />);
it('renders the groups route', async () => {
render(<TestWrapper route={'/groups'} />);

await waitFor(() => {
expect(screen.getByRole('heading', { name: 'Groups' })).toBeVisible();
expect(
screen.getByLabelText('Open Inventory groups popover')
).toBeVisible();
expect(screen.getByText('Inventory groups component')).toBeVisible(); // mocked
await waitFor(() => {
expect(screen.getByText('Groups component')).toBeVisible(); // mocked
});
});
});
});

describe('zero state', () => {
afterEach(() => {
jest.clearAllMocks();
});
describe('zero state', () => {
it('renderes zero state when there are no systems', async () => {
inventoryHasConventionalSystems.mockReturnValue(false);
inventoryHasEdgeSystems.mockReturnValue(false);
render(<TestWrapper route={'/'} />);

await waitFor(() => {
expect(screen.getByText('Zero state')).toBeVisible();
});
});

it('renderes zero state when there are no systems', async () => {
inventoryHasConventionalSystems.mockReturnValue(false);
inventoryHasEdgeSystems.mockReturnValue(false);
render(<TestWrapper route={'/'} />);
it('renders a route when there are some conventional systems', async () => {
inventoryHasConventionalSystems.mockReturnValue(true);
inventoryHasEdgeSystems.mockReturnValue(false);
render(<TestWrapper route={'/'} />);

await waitFor(() => {
expect(screen.getByText('Zero state')).toBeVisible();
await waitFor(() => {
expect(screen.getByText('Route component')).toBeVisible();
});
});
});

it('renders a route when there are some conventional systems', async () => {
inventoryHasConventionalSystems.mockReturnValue(true);
inventoryHasEdgeSystems.mockReturnValue(false);
render(<TestWrapper route={'/'} />);
it('renders a route when there are some edge systems', async () => {
inventoryHasConventionalSystems.mockReturnValue(false);
inventoryHasEdgeSystems.mockReturnValue(true);
render(<TestWrapper route={'/'} />);

await waitFor(() => {
expect(screen.getByText('Route component')).toBeVisible();
await waitFor(() => {
expect(screen.getByText('Route component')).toBeVisible();
});
});
});

it('renders a route when there are some edge systems', async () => {
inventoryHasConventionalSystems.mockReturnValue(false);
inventoryHasEdgeSystems.mockReturnValue(true);
render(<TestWrapper route={'/'} />);
it('renders spinner before any route', async () => {
render(<TestWrapper route={'/'} />);

await waitFor(() => {
expect(screen.getByText('Route component')).toBeVisible();
await waitFor(() => {
expect(screen.getByRole('progressbar')).toBeVisible();
});
});
});
});

0 comments on commit c0536f0

Please sign in to comment.