Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 2 additions & 2 deletions playwright/UI/FilterTypePatch.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -188,8 +188,8 @@ test.describe('Patch Filters', () => {
await applyFilterSubtype(page, 'Name', { name: packageName!, inputType: 'search' });

const rows = page.getByRole('row');
await expect(rows).toHaveCount(2);
await expect(rows.filter({ hasText: packageName })).toHaveCount(1);
expect(await rows.count()).toBeGreaterThan(1); // header + at least one body row
await expect(rows.filter({ has: page.getByText(packageName!, { exact: true }) })).toHaveCount(1);

await resetFilters(page);
});
Expand Down
2 changes: 1 addition & 1 deletion playwright/UI/PaginationTests.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ test.describe('Pagination', () => {
await test.step('Filter and sort the table', async () => {
await page.getByPlaceholder(/^Filter by name.*$/).fill(prefix);
await waitForTableLoad(page);
await page.getByRole('columnheader', { name: 'Name' }).click();
await page.getByRole('columnheader', { name: 'Name' }).getByRole('button').click();

await expect(toolbarPaginationButton).toHaveText('1 - 12 of 12');
await expect(targetRows).toHaveCount(12);
Expand Down
3 changes: 3 additions & 0 deletions playwright/UI/VerifyExportingFeature.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,9 @@ test.describe('Verify exporting feature', () => {
getRowCellByHeader(page, row, 'Installed packages'),
]);

await expect(osCell).not.toBeEmpty();
await expect(installedPackagesCell).not.toBeEmpty();

const [osText, installedPackagesText] = await Promise.all([
osCell.textContent(),
installedPackagesCell.textContent(),
Expand Down
4 changes: 2 additions & 2 deletions playwright/test-utils/helpers/filters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -164,10 +164,10 @@ export const applyFilterSubtype = async (
// Select the filter type first
await selectFilterType(page, filterType);

// Tags uses a textbox (combobox) "input with dropdown and clear", not Group filter.
// Tags uses a textbox (combobox) "input with dropdown and clear button", not Group filter.
// Two exist (global filter + table toolbar); use the table toolbar one (second) when filtering the Systems table.
if (filterType === 'Tags' && subtype.inputType !== 'search') {
const tagsTextbox = page.getByRole('textbox', { name: 'input with dropdown and clear' }).nth(1);
const tagsTextbox = page.locator('.pf-v6-c-toolbar').getByRole('textbox', { name: 'input with dropdown and clear button' }).first();
await tagsTextbox.waitFor({ state: 'visible', timeout: 10000 });
await tagsTextbox.click();
} else {
Expand Down
2 changes: 1 addition & 1 deletion playwright/test-utils/helpers/navigation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,6 @@ export const navigateToTemplates = async (page: Page) => {
await page.goto('/insights/content/templates');
}
await expect(page.getByRole('heading', { name: 'Templates' })).toBeVisible();
const subheading = page.getByText('View all content templates within your organization.');
const subheading = page.getByText('Control content stability of your systems by combining repositories into templates.');
await expect(subheading).toBeVisible(); // Wait for either list page or zero state
};
25 changes: 11 additions & 14 deletions src/SmartComponents/AdvisorySystems/AdvisorySystemsTable.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import propTypes from 'prop-types';
import { shallowEqual, useDispatch, useSelector, useStore } from 'react-redux';
import { combineReducers } from 'redux';
import messages from '../../Messages';
import searchFilter from '../../PresentationalComponents/Filters/SearchFilter';
import { defaultReducers } from '../../store';
import { systemSelectAction } from '../../store/Actions/Actions';
import {
Expand Down Expand Up @@ -59,30 +58,21 @@ const AdvisorySystemsTable = ({
const { systemProfile, selectedTags, filter, search, page, perPage, sort } = queryParams;

const [deleteFilters, deleteFilterGroup] = useRemoveFilter(
{ search, ...filter },
filter,
apply,
pageDefaultFilters.advisorySystems,
);

const filterConfig = {
items: [
searchFilter(
apply,
search,
intl.formatMessage(messages.labelsFiltersSystemsSearchTitle),
intl.formatMessage(messages.labelsFiltersSystemsSearchPlaceholder),
),
advisoryStatusFilter(apply, filter),
],
items: [advisoryStatusFilter(apply, filter)],
};

const activeFiltersConfig = buildActiveFilterConfig(
filter,
search,
undefined,
deleteFilters,
deleteFilterGroup,
intl.formatMessage(messages.labelsFiltersSystemsSearchTitle),
deleteFilterGroup,
pageDefaultFilters.advisorySystems,
);

Expand Down Expand Up @@ -134,12 +124,19 @@ const AdvisorySystemsTable = ({
autoRefresh
initialLoading
ignoreRefresh
hideFilters={{ all: true, tags: false, hostGroupFilter: false, operatingSystem: false }}
hideFilters={{
all: true,
name: false,
tags: false,
hostGroupFilter: false,
operatingSystem: false,
}}
columns={(inventoryColumns) =>
mergeInventoryColumns(ADVISORY_SYSTEMS_COLUMNS, inventoryColumns)
}
showTags
customFilters={{
filters: [...(search ? [{ value: 'hostname_or_id', filter: search }] : [])],
patchParams: {
search,
filter,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ describe('AdvisorySystemsTable.js', () => {
expect(InventoryTable).toHaveBeenCalledWith(
expect.objectContaining({
customFilters: {
filters: [{ filter: 'test-search', value: 'hostname_or_id' }],
patchParams: {
filter: { status: ['Installable'] },
search: 'test-search',
Expand All @@ -90,6 +91,7 @@ describe('AdvisorySystemsTable.js', () => {
expect.objectContaining({
hideFilters: {
all: true,
name: false,
tags: false,
hostGroupFilter: false,
operatingSystem: false,
Expand Down Expand Up @@ -136,16 +138,6 @@ describe('AdvisorySystemsTable.js', () => {
expect.objectContaining({
filterConfig: {
items: [
{
filterValues: {
'aria-label': 'search-field',
onChange: expect.any(Function),
placeholder: 'Filter by name',
value: undefined,
},
label: 'Name',
type: 'text',
},
{
filterValues: {
items: [
Expand Down
27 changes: 12 additions & 15 deletions src/SmartComponents/PackageSystems/PackageSystems.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import propTypes from 'prop-types';
import { shallowEqual, useDispatch, useSelector, useStore } from 'react-redux';
import { useSearchParams } from 'react-router-dom';
import messages from '../../Messages';
import searchFilter from '../../PresentationalComponents/Filters/SearchFilter';
import statusFilter from '../../PresentationalComponents/Filters/StatusFilter';
import versionFilter from '../../PresentationalComponents/Filters/VersionFilter';
import ErrorHandler from '../../PresentationalComponents/Snippets/ErrorHandler';
Expand Down Expand Up @@ -85,35 +84,26 @@ const PackageSystems = ({ packageName }) => {
);

const [deleteFilters, deleteFilterGroup] = useRemoveFilter(
{ ...filter, search },
filter,
apply,
pageDefaultFilters.packageSystems,
);

const filterConfig = {
items: [
searchFilter(
apply,
search,
intl.formatMessage(messages.labelsFiltersSystemsSearchTitle),
intl.formatMessage(messages.labelsFiltersSystemsSearchPlaceholder),
),
statusFilter(apply, filter),
versionFilter(apply, filter, packageVersions),
],
items: [statusFilter(apply, filter), versionFilter(apply, filter, packageVersions)],
};

const activeFiltersConfig = useMemo(
() =>
buildActiveFilterConfig(
filter,
search,
undefined,
deleteFilters,
deleteFilterGroup,
intl.formatMessage(messages.labelsFiltersSystemsSearchTitle),
pageDefaultFilters.packageSystems,
),
[deleteFilters, deleteFilterGroup, filter, search],
[deleteFilters, deleteFilterGroup, filter],
);

const constructFilename = (system) => `${system.available_evra}`;
Expand Down Expand Up @@ -189,13 +179,20 @@ const PackageSystems = ({ packageName }) => {
isFullView
autoRefresh
initialLoading
hideFilters={{ all: true, tags: false, hostGroupFilter: false, operatingSystem: false }}
hideFilters={{
all: true,
name: false,
tags: false,
hostGroupFilter: false,
operatingSystem: false,
}}
columns={(inventoryColumns) =>
mergeInventoryColumns(PACKAGE_SYSTEMS_COLUMNS, inventoryColumns)
}
showTags
getEntities={getEntites}
customFilters={{
filters: [...(search ? [{ value: 'hostname_or_id', filter: search }] : [])],
patchParams: {
search,
filter,
Expand Down
3 changes: 3 additions & 0 deletions src/SmartComponents/Systems/SystemTable.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ describe('SystemsTable', () => {
SystemsStore: {
queryParams: {
filter: { packages_updatable: 'eq:0' },
search: 'test-search',
selectedTags: ['tags=test-tag'],
systemProfile: { ansible: { controller_version: 'not_nil' } },
},
Expand All @@ -87,8 +88,10 @@ describe('SystemsTable', () => {
expect(InventoryTable).toHaveBeenCalledWith(
expect.objectContaining({
customFilters: {
filters: [{ filter: 'test-search', value: 'hostname_or_id' }],
patchParams: {
filter: { packages_updatable: 'eq:0' },
search: 'test-search',
selectedTags: ['tags=test-tag'],
systemProfile: { ansible: { controller_version: 'not_nil' } },
},
Expand Down
15 changes: 8 additions & 7 deletions src/SmartComponents/Systems/SystemsTable.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ const SystemsTable = ({
page,
perPage,
sort,
search,
} = queryParams;
const {
os: operatingSystemFilter,
Expand Down Expand Up @@ -135,7 +136,7 @@ const SystemsTable = ({
const activeFiltersConfig = useMemo(() => {
const config = buildActiveFilterConfig(
filter,
'',
undefined,
deleteFilters,
deleteFilterGroup,
intl.formatMessage(messages.labelsFiltersSystemsSearchTitle),
Expand Down Expand Up @@ -208,12 +209,12 @@ const SystemsTable = ({
columns={(inventoryColumns) => mergeInventoryColumns(SYSTEMS_LIST_COLUMNS, inventoryColumns)}
showTags
customFilters={{
...(operatingSystemFilter
? {
filters: [...(osFilter || [])],
}
: {}),
filters: [
...(search ? [{ value: 'hostname_or_id', filter: search }] : []),
...(operatingSystemFilter ? osFilter : []),
],
patchParams: {
search,
filter: apiFilter,
systemProfile: mergedSystemProfile,
selectedTags,
Expand All @@ -228,7 +229,7 @@ const SystemsTable = ({
...defaultReducers,
...mergeWithEntities(
inventoryEntitiesReducer(SYSTEMS_LIST_COLUMNS, modifyInventory),
persistantParams({ page, perPage, sort }, decodedParams),
persistantParams({ page, perPage, sort, search }, decodedParams),
),
}),
);
Expand Down
24 changes: 24 additions & 0 deletions src/Utilities/SystemHelpers.test.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { renderHook } from '@testing-library/react';
import {
buildFilterConfig,
createSystemsSortBy,
mergeInventoryColumns,
workloadToSystemProfile,
Expand Down Expand Up @@ -170,3 +172,25 @@ describe('workloadToSystemProfile', () => {
});
});
});

describe('buildFilterConfig', () => {
it('should return filter items for status, patch status, and workload', () => {
const apply = jest.fn();
const filter = { stale: [true, false] };

const { result } = renderHook(() => buildFilterConfig(filter, apply));
expect(result.current.items).toHaveLength(3);
expect(result.current.items[0]).toMatchObject({
label: 'Status',
type: 'checkbox',
});
expect(result.current.items[1]).toMatchObject({
label: 'Patch status',
type: 'singleSelect',
});
expect(result.current.items[2]).toMatchObject({
label: 'Workload',
type: 'checkbox',
});
});
});
3 changes: 2 additions & 1 deletion src/Utilities/hooks/Hooks.js
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ export const useGetEntities = (
) => {
const { selectedTags: activeTags = [] } = patchParams;
const { selectedTags } = mapGlobalFilters(filters.tagFilters);
const search = filters?.hostnameOrId || '';
const search = filters?.hostnameOrId ?? '';

const sort = createSystemsSortBy(orderBy, orderDirection, packageName);
const filter = buildApiFilters(patchParams.filter, filters);
Expand Down Expand Up @@ -277,6 +277,7 @@ export const useGetEntities = (
perPage,
sort,
filter,
search,
}),
{
replace: true,
Expand Down
27 changes: 27 additions & 0 deletions src/Utilities/hooks/Hooks.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,33 @@ describe('Custom hooks tests', () => {
await request;
});

it('useGetEntities: should propagate search from inventory filters to setSearchParams', async () => {
const fetchApi = jest.fn(() => Promise.resolve({ data: [], meta: { total_items: 0 } }));
const apply = jest.fn();
const setSearchParams = jest.fn();
const params = {
orderBy: 'display_name',
orderDirection: 'ASC',
page: 1,
per_page: 20,
patchParams: {
filter: { stale: [true, false] },
},
filters: {
hostnameOrId: 'test-host',
},
};
const { result } = renderHook(() => useGetEntities(fetchApi, apply, {}, setSearchParams));

await result.current([], params);

expect(fetchApi).toHaveBeenCalledWith(expect.objectContaining({ search: 'test-host' }));
expect(apply).toHaveBeenCalledWith(expect.objectContaining({ search: 'test-host' }));
expect(setSearchParams).toHaveBeenCalledWith(expect.stringContaining('search=test-host'), {
replace: true,
});
});

it('useEntitlements, should return correct entitlements', async () => {
const { result } = renderHook(() => useEntitlements());
const finalResult = await result.current();
Expand Down
Loading