Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
b102784
WEB-4654 abstract tags filter into own component TagFilterDropdown
henry-tp Jul 14, 2026
988bb7c
WEB-4654 abstract tags filter
henry-tp Jul 14, 2026
9697697
WEB-4654 extract sites filter
henry-tp Jul 14, 2026
a8f3ff7
WEB-4654 remove prefixPopHealthMetric from abstracted components
henry-tp Jul 14, 2026
ae860b6
Merge branch 'WEB-4654-filter-bar' into WEB-4654-tags
henry-tp Jul 14, 2026
be84197
WEB-4654 remove unused popup state hooks
henry-tp Jul 14, 2026
dcb6cd4
WEB-4654 restyle tags and sites dropdown to new UI design
henry-tp Jul 14, 2026
1601f39
WEB-4654 fix margins
henry-tp Jul 14, 2026
43d0e72
WEB-4654 add safety in case of missing label
henry-tp Jul 14, 2026
330081c
Merge branch 'WEB-4654-filter-bar' into WEB-4654-tags
henry-tp Jul 15, 2026
e4f1c9f
Merge branch 'WEB-4654-filter-bar' into WEB-4654-tags
henry-tp Jul 15, 2026
26b52b4
WEB-4654 change directory for FilterBySites & FilterByTags
henry-tp Jul 15, 2026
44f608d
WEB-4654 change empty tag/site copy per new requirements
henry-tp Jul 16, 2026
f904994
WEB-4654 fix copy per new requirements
henry-tp Jul 16, 2026
2f75d56
WEB-4654 use circle-add icon
henry-tp Jul 16, 2026
f3407da
WEB-4654 clear unneeded props
henry-tp Jul 16, 2026
2db2bfe
WEB-4654 update trackMetric fn calls
henry-tp Jul 16, 2026
c01fd80
WEB-4654 use dedicated file for useClinicMetricsPageName
henry-tp Jul 16, 2026
bde85e8
WEB-4654 add tests for adapter components
henry-tp Jul 16, 2026
c13309c
WEB-4654 add tests for TagFilterDropdown
henry-tp Jul 16, 2026
4d585cb
WEB-4654 re-add in top-level integration test for filtering
henry-tp Jul 16, 2026
8bcd604
Merge branch 'WEB-4654-filter-bar' into WEB-4654-tags
henry-tp Jul 17, 2026
db493a6
WEB-4654 optimize tag icon
henry-tp Jul 17, 2026
dfecb45
WEB-4654 use MemoryRouter instead of mocking out location hook
henry-tp Jul 19, 2026
d6f0e85
WEB-4654 autofocus search on mount
henry-tp Jul 20, 2026
9424e83
Merge branch 'WEB-4654-filter-bar' into WEB-4654-tags
henry-tp Jul 20, 2026
1d01fc2
WEB-4654 remove unused var
henry-tp Jul 20, 2026
5279bce
WEB-4654 fix jumping issue
henry-tp Jul 21, 2026
e749547
WEB-4654 use overflow clip to prevent jump
henry-tp Jul 21, 2026
a4dcf28
WEB-4654 fix missing metric update
henry-tp Jul 26, 2026
822e03b
Merge branch 'WEB-4654-filter-bar' into WEB-4654-tags
henry-tp Jul 26, 2026
aee5467
Merge branch 'WEB-4654-filter-bar' into WEB-4654-tags
henry-tp Jul 26, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
123 changes: 11 additions & 112 deletions __tests__/unit/app/pages/clinicworkspace/ClinicPatients.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -382,146 +382,45 @@ describe('ClinicPatients', () => {

describe('filtering for patients', () => {
afterEach(() => {
// Clear any persisted filter state between tests
localStorage.clear();
});

it('should allow filtering by sites', async () => {
it('maps an applied tag filter into the getPatientsForClinic query', async () => {
render(
<MockedProviderWrappers>
<ClinicPatients {...defaultProps} />
</MockedProviderWrappers>
);

// Open the Sites filter dropdown and filter for 2 sites
await userEvent.click(screen.getByRole('button', { name: /Sites/ }));

const site1checkbox = screen.getByTestId('clinic-site-filter-option-checkbox-site-1-id');
const site2checkbox = screen.getByTestId('clinic-site-filter-option-checkbox-site-2-id');

expect(site1checkbox).not.toBeChecked();
expect(site2checkbox).not.toBeChecked();

await userEvent.click(site1checkbox);
await userEvent.click(site2checkbox);

expect(site1checkbox).toBeChecked();
expect(site2checkbox).toBeChecked();

// Click Apply
await userEvent.click(screen.getByRole('button', { name: /Apply/ }));

expect(defaultProps.api.clinics.getPatientsForClinic).toHaveBeenCalledWith(
'clinicID123',
{ sites: ['site-1-id', 'site-2-id'], limit: 50, offset: 0, period: '14d', sortType: 'cgm', sort: '-lastData' },
expect.any(Function),
);

expect(defaultProps.trackMetric).toHaveBeenCalledWith(
'Clinic - Population Health - Clinic sites filter apply',
{ clinicId: 'clinicID123' },
);
}, TEST_TIMEOUT_MS);

it('should allow filtering by for patients with zero sites', async () => {
render(
<MockedProviderWrappers>
<ClinicPatients {...defaultProps} />
</MockedProviderWrappers>
);

// Open the Sites filter dropdown and filter for 2 sites
await userEvent.click(screen.getByRole('button', { name: /Sites/ }));

const site1checkbox = screen.getByTestId('clinic-site-filter-option-checkbox-site-1-id');
const site2checkbox = screen.getByTestId('clinic-site-filter-option-checkbox-site-2-id');
await userEvent.click(site1checkbox);
await userEvent.click(site2checkbox);
expect(site1checkbox).toBeChecked();
expect(site2checkbox).toBeChecked();

// Click the checkbox to filter for pwds with zero sites. Others should uncheck.
const zeroSiteCheckbox = screen.getByTestId('clinic-site-filter-option-checkbox-PWDS_WITH_ZERO_SITES');
await userEvent.click(zeroSiteCheckbox);
expect(site1checkbox).not.toBeChecked();
expect(site2checkbox).not.toBeChecked();

// Click Apply. A query of `['_']` should be made for sites.
await userEvent.click(screen.getByRole('button', { name: /Apply/ }));

expect(defaultProps.api.clinics.getPatientsForClinic).toHaveBeenCalledWith(
'clinicID123',
{ sites: ['_'], limit: 50, offset: 0, period: '14d', sortType: 'cgm', sort: '-lastData' },
expect.any(Function),
);
}, TEST_TIMEOUT_MS);

it('should allow filtering by tags', async () => {
render(
<MockedProviderWrappers>
<ClinicPatients {...defaultProps} />
</MockedProviderWrappers>
);

// Open the Tags filter dropdown and filter for 2 sites
// Open the Tags filter dropdown, select 2 tags, and apply
await userEvent.click(screen.getByRole('button', { name: /Tags/ }));

const tag1checkbox = screen.getByTestId('tag-filter-option-checkbox-tag1');
const tag3checkbox = screen.getByTestId('tag-filter-option-checkbox-tag3');

expect(tag1checkbox).not.toBeChecked();
expect(tag3checkbox).not.toBeChecked();

await userEvent.click(tag1checkbox);
await userEvent.click(tag3checkbox);

expect(tag1checkbox).toBeChecked();
expect(tag3checkbox).toBeChecked();

// Click Apply
await userEvent.click(screen.getByTestId('tag-filter-option-checkbox-tag1'));
await userEvent.click(screen.getByTestId('tag-filter-option-checkbox-tag3'));
await userEvent.click(screen.getByRole('button', { name: /Apply/ }));

expect(defaultProps.api.clinics.getPatientsForClinic).toHaveBeenLastCalledWith(
'clinicID123',
{ tags: ['tag1', 'tag3'], limit: 50, offset: 0, period: '14d', sortType: 'cgm', sort: '-lastData' },
expect.any(Function),
);

expect(defaultProps.trackMetric).toHaveBeenCalledWith(
'Clinic - Population Health - Patient tag filter apply',
{ clinicId: 'clinicID123' },
);
}, TEST_TIMEOUT_MS);

it('should allow filtering by for patients with zero tags', async () => {
it('maps an applied site filter into the getPatientsForClinic query', async () => {
render(
<MockedProviderWrappers>
<ClinicPatients {...defaultProps} />
</MockedProviderWrappers>
);

// Open the Tags filter dropdown and filter for 2 tags
await userEvent.click(screen.getByRole('button', { name: /Tags/ }));

const tag1checkbox = screen.getByTestId('tag-filter-option-checkbox-tag1');
const tag2checkbox = screen.getByTestId('tag-filter-option-checkbox-tag2');
await userEvent.click(tag1checkbox);
await userEvent.click(tag2checkbox);
expect(tag1checkbox).toBeChecked();
expect(tag2checkbox).toBeChecked();

// Click the checkbox to filter for pwds with zero tags. Others should uncheck.
const zeroTagCheckbox = screen.getByTestId('tag-filter-option-checkbox-PWDS_WITH_ZERO_TAGS');
await userEvent.click(zeroTagCheckbox);
expect(tag1checkbox).not.toBeChecked();
expect(tag2checkbox).not.toBeChecked();

// Click Apply. A query of `['_']` should be made for sites.
// Open the Sites filter dropdown, select 2 sites, and apply
await userEvent.click(screen.getByRole('button', { name: /Sites/ }));
await userEvent.click(screen.getByTestId('clinic-site-filter-option-checkbox-site-1-id'));
await userEvent.click(screen.getByTestId('clinic-site-filter-option-checkbox-site-2-id'));
await userEvent.click(screen.getByRole('button', { name: /Apply/ }));

expect(defaultProps.api.clinics.getPatientsForClinic).toHaveBeenCalledWith(
expect(defaultProps.api.clinics.getPatientsForClinic).toHaveBeenLastCalledWith(
'clinicID123',
{ tags: ['_'], limit: 50, offset: 0, period: '14d', sortType: 'cgm', sort: '-lastData' },
{ sites: ['site-1-id', 'site-2-id'], limit: 50, offset: 0, period: '14d', sortType: 'cgm', sort: '-lastData' },
expect.any(Function),
);
}, TEST_TIMEOUT_MS);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
import React from 'react';
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { Provider } from 'react-redux';
import configureStore from 'redux-mock-store';
import { thunk } from 'redux-thunk';
import { MemoryRouter } from 'react-router-dom';

import * as actions from '@app/redux/actions';
import FilterBySites from '@app/pages/clinicworkspace/clinicPatientsFilters/FilterBySites';
import { trackMetric as mockTrackMetric } from '../../../../../app/core/metricUtils';
import useIsClinicAdmin from '@app/pages/clinicworkspace/useIsClinicAdmin';

jest.mock('@app/pages/clinicworkspace/useIsClinicAdmin');

jest.mock('@app/redux/actions', () => ({
async: { fetchClinicSites: jest.fn().mockReturnValue({ type: 'FETCH_CLINIC_SITES' }) },
}));

const mockStore = configureStore([thunk]);

describe('FilterBySites', () => {
let store;
let wrapper;

const api = { some: 'api' };
const selectedClinicId = 'clinic123';

const clinicSiteDefs = [
{ id: 'site1', name: 'Site One' },
{ id: 'site2', name: 'Site Two' },
];

const setActiveFilters = jest.fn();
const setShowClinicSitesDialog = jest.fn();

useIsClinicAdmin.mockReturnValue(true);

const ui = (props = {}) => (
<Provider store={store}>
<MemoryRouter initialEntries={['/clinic-workspace']}>
<FilterBySites
api={api}
setActiveFilters={setActiveFilters}
setShowClinicSitesDialog={setShowClinicSitesDialog}
{...props}
/>
</MemoryRouter>
</Provider>
);

const renderComponent = (props = {}) => render(ui(props));

beforeEach(() => {
store = mockStore({
blip: {
selectedClinicId,
clinics: { [selectedClinicId]: { id: selectedClinicId, sites: clinicSiteDefs } },
},
});

setActiveFilters.mockClear();
setShowClinicSitesDialog.mockClear();
});

describe('handleChange', () => {
it('calls setActiveFilters with the applied sites merged into the existing activeFilters', async () => {
wrapper = renderComponent({ activeFilters: { clinicSites: [], patientTags: ['tag1'] } });

await userEvent.click(screen.getByRole('button', { name: /^Clinic Sites/ }));
await screen.findByTestId('clinic-site-filter-option-checkbox-site1');

await userEvent.click(screen.getByTestId('clinic-site-filter-option-checkbox-site1'));
await userEvent.click(screen.getByRole('button', { name: 'Apply' }));

expect(setActiveFilters).toHaveBeenCalledTimes(1);
expect(setActiveFilters).toHaveBeenCalledWith({
clinicSites: ['site1'],
patientTags: ['tag1'],
});
});
});

describe('onClickEditSites visibility', () => {
it('offers the edit-sites control to clinic admins only', async () => {
// Hidden if not admin
useIsClinicAdmin.mockReturnValue(false);
const { rerender } = renderComponent();

expect(screen.queryByRole('button', { name: 'Edit Sites' })).not.toBeInTheDocument();

// Visible if not admin
useIsClinicAdmin.mockReturnValue(true);
rerender(ui());

await userEvent.click(screen.getByRole('button', { name: /^Clinic Sites/ }));
await screen.findByTestId('clinic-site-filter-option-checkbox-site1');

const editButton = screen.getByRole('button', { name: 'Edit Sites' });
expect(editButton).toBeInTheDocument();

await userEvent.click(editButton);

expect(actions.async.fetchClinicSites).toHaveBeenCalledWith(api, selectedClinicId);
expect(setShowClinicSitesDialog).toHaveBeenCalledWith(true);
expect(mockTrackMetric).toHaveBeenCalledWith(
'Clinic - Edit clinic sites open',
expect.objectContaining({ clinicId: selectedClinicId, source: 'Filter menu', pageName: 'Population Health' })
);
});
});

describe('clinicSites passthrough', () => {
it('reflects the active clinic sites in the filter count', () => {
wrapper = renderComponent({ activeFilters: { clinicSites: ['site1', 'site2'] } });

expect(screen.getByLabelText('clinic site count')).toHaveTextContent('2');
});
});
});
Loading