Skip to content

Commit be28ac2

Browse files
committed
feat(frontend/riexchange): inline column filters via shared lib
Wires per-column filter popovers to the RI Exchange reshape-recommendations table using the helpers extracted in merged #570 (parseNumericFilter + applyColumnFilters). Categorical columns (Source RI, Source/Target instance types, Reason) get a checkbox-list popover; numeric columns (Source/Target count, Utilization %, Normalized used/purchased) get a free-text expression popover that supports `>N`, `>=N`, `<N`, `<=N`, `N..M` ranges, exact match, and comma-separated OR. Numeric predicates compare against the display-rounded cell value so a user typing the displayed figure (e.g. 95.0 for utilization) matches the cell they see. Broken expressions are skipped (inline error in the popover) rather than collapsing the table. Filter state lives in the RI Exchange-specific slice on state.ts; no cross-tab coupling. No drive-by changes to the rest of the RI Exchange page (convertible-RI table, exchange modal, automation settings, history). Test-mocks for the riexchange + riexchange-permissions suites updated to expose the new state getters/setters so the existing happy-path assertions still pass. Refs #166.
1 parent dc31e54 commit be28ac2

3 files changed

Lines changed: 444 additions & 7 deletions

File tree

‎frontend/src/__tests__/riexchange-permissions.test.ts‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,12 @@ jest.mock('../state', () => ({
2424
// (issue #871); default to the AWS, all-accounts path used by these tests.
2525
getCurrentProvider: jest.fn(() => 'aws'),
2626
getCurrentAccountIDs: jest.fn(() => []),
27+
// RI Exchange column-filter slice (issue #166 follow-up). Permission
28+
// tests don't drive filter state; empty record keeps rendering on the
29+
// happy path.
30+
getRiExchangeColumnFilters: jest.fn(() => ({})),
31+
setRiExchangeColumnFilter: jest.fn(),
32+
clearAllRiExchangeColumnFilters: jest.fn(),
2733
}));
2834

2935
import * as api from '../api';

‎frontend/src/__tests__/riexchange.test.ts‎

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,12 @@ jest.mock('../state', () => ({
4646
getCurrentProvider: jest.fn(() => 'aws'),
4747
getCurrentAccountIDs: jest.fn(() => []),
4848
getCurrentUser: jest.fn(() => ({ id: 'u', email: 'u@example.com', groups: ['00000000-0000-5000-8000-000000000001'] })),
49+
// RI Exchange column-filter slice (issue #166 follow-up). Tests don't
50+
// exercise the filter state directly; an empty record + no-op setters
51+
// keep renderRecommendations on its happy path.
52+
getRiExchangeColumnFilters: jest.fn(() => ({})),
53+
setRiExchangeColumnFilter: jest.fn(),
54+
clearAllRiExchangeColumnFilters: jest.fn(),
4955
}));
5056

5157
import {
@@ -441,6 +447,13 @@ describe('reshape recommendations table', () => {
441447
tableContainer = document.createElement('div');
442448
tableContainer.id = 'ri-exchange-recommendations-list';
443449
document.body.appendChild(tableContainer);
450+
// Re-apply the column-filter mock impl after a prior test's
451+
// jest.resetAllMocks(); without this the renderer blows up on
452+
// Object.entries(undefined) when reading filter state.
453+
const stateMod = jest.requireMock('../state') as {
454+
getRiExchangeColumnFilters: jest.Mock;
455+
};
456+
stateMod.getRiExchangeColumnFilters.mockReturnValue({});
444457
});
445458

446459
afterEach(() => {

0 commit comments

Comments
 (0)