Skip to content
Open
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
123 changes: 123 additions & 0 deletions spec/components/Filters/Filters.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -753,4 +753,127 @@ describe('Testing Component: Filters', () => {
});
});
});

describe(' - Facet Blacklisting Tests', () => {
it('Should not render facets when isHiddenFilterFn returns true', async () => {
const isHiddenFilterFn = (facet) => facet.name === 'color'; // lowercase 'color'
const { queryByText, getByText } = render(
<CioPlp apiKey={DEMO_API_KEY}>
<Filters facets={mockTransformedFacets} isHiddenFilterFn={isHiddenFilterFn} />
</CioPlp>,
);

await waitFor(() => {
// Color facet should not be rendered
expect(queryByText('Color')).not.toBeInTheDocument();
// Other facets should still render
const otherFacet = mockTransformedFacets.find((f) => f.name !== 'color');
expect(getByText(otherFacet.displayName)).toBeInTheDocument();
});
});

it('Should not render facets with data.cio_plp_hidden = true', async () => {
const facetsWithHidden = mockTransformedFacets.map((facet, index) => ({
...facet,
data: {
...facet.data,
cio_plp_hidden: index === 0, // Hide first facet
},
}));

const { queryByText, getByText } = render(
<CioPlp apiKey={DEMO_API_KEY}>
<Filters facets={facetsWithHidden} />
</CioPlp>,
);

await waitFor(() => {
// First facet should not be rendered
expect(queryByText(facetsWithHidden[0].displayName)).not.toBeInTheDocument();
// Other facets should still render
expect(getByText(facetsWithHidden[1].displayName)).toBeInTheDocument();
});
});

it('Should not render options when isHiddenFilterOptionFn returns true', async () => {
const colorFacet = mockTransformedFacets.find((f) => f.name === 'color'); // lowercase
const optionToHide = colorFacet.options[0];
const isHiddenFilterOptionFn = (option) => option.value === optionToHide.value;

const { container } = render(
<CioPlp apiKey={DEMO_API_KEY}>
<Filters facets={[colorFacet]} isHiddenFilterOptionFn={isHiddenFilterOptionFn} initialNumOptions={100} />
</CioPlp>,
);

await waitFor(() => {
// The hidden option should not be rendered
const colorFilterGroup = container.querySelector('.cio-filter-group');
const optionLabels = colorFilterGroup.querySelectorAll('.cio-filter-multiple-option label');
const optionTexts = Array.from(optionLabels).map((label) => label.textContent);

expect(optionTexts).not.toContain(optionToHide.displayName);
// Other options should still render
expect(optionTexts.length).toBe(colorFacet.options.length - 1);
});
});

it('Should not render options with data.cio_plp_hidden = true', async () => {
const colorFacet = mockTransformedFacets.find((f) => f.name === 'color'); // lowercase
const facetWithHiddenOption = {
...colorFacet,
options: colorFacet.options.map((option, index) => ({
...option,
data: {
...option.data,
cio_plp_hidden: index === 0, // Hide first option
},
})),
};

const { container } = render(
<CioPlp apiKey={DEMO_API_KEY}>
<Filters facets={[facetWithHiddenOption]} initialNumOptions={100} />
</CioPlp>,
);

await waitFor(() => {
const colorFilterGroup = container.querySelector('.cio-filter-group');
const optionLabels = colorFilterGroup.querySelectorAll('.cio-filter-multiple-option label');
const optionTexts = Array.from(optionLabels).map((label) => label.textContent);

// First option should not be rendered
expect(optionTexts).not.toContain(colorFacet.options[0].displayName);
// Other options should still render
expect(optionTexts.length).toBe(colorFacet.options.length - 1);
});
});

it('Should hide facets from both isHiddenFilterFn and data.cio_plp_hidden', async () => {
const facetsWithHidden = mockTransformedFacets.map((facet, index) => ({
...facet,
data: {
...facet.data,
cio_plp_hidden: index === 0, // Hide first facet via metadata
},
}));

const isHiddenFilterFn = (facet) => facet.name === facetsWithHidden[1].name; // Hide second facet via fn

const { queryByText, container } = render(
<CioPlp apiKey={DEMO_API_KEY}>
<Filters facets={facetsWithHidden} isHiddenFilterFn={isHiddenFilterFn} />
</CioPlp>,
);

await waitFor(() => {
// Both first and second facets should be hidden
expect(queryByText(facetsWithHidden[0].displayName)).not.toBeInTheDocument();
expect(queryByText(facetsWithHidden[1].displayName)).not.toBeInTheDocument();
// Remaining facets should render
const filterGroups = container.querySelectorAll('.cio-filter-group');
expect(filterGroups.length).toBe(facetsWithHidden.length - 2);
});
});
});
});
153 changes: 153 additions & 0 deletions spec/hooks/useFilter/useFilter.test.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import '@testing-library/jest-dom';
import { renderHook, waitFor } from '@testing-library/react';
import React from 'react';
import useFilter from '../../../src/hooks/useFilter';
import useRequestConfigs from '../../../src/hooks/useRequestConfigs';
import mockSearchResponse from '../../local_examples/apiSearchResponse.json';
import { transformSearchResponse } from '../../../src/utils';
import { renderHookWithCioPlp } from '../../test-utils';
import { CioPlpProvider } from '../../../src/components/CioPlp';
import { DEMO_API_KEY } from '../../../src/constants';

describe('Testing Hook: useFilter', () => {
const originalWindowLocation = window.location;
Expand Down Expand Up @@ -236,4 +239,154 @@ describe('Testing Hook: useFilter', () => {
expect(requestConfig.section.toString()).toBe('Search Suggestions');
});
});

describe('isHiddenFilterFn', () => {
it('Should filter out facets when isHiddenFilterFn returns true', async () => {
const isHiddenFilterFn = (facet) => facet.name === 'brand'; // lowercase
const useFilterPropsWithHiddenFn = {
...useFilterProps,
isHiddenFilterFn,
};
const { result } = renderHookWithCioPlp(() => useFilter(useFilterPropsWithHiddenFn));

await waitFor(() => {
const {
current: { facets },
} = result;

expect(facets.length).toBe(searchData.response.facets.length - 1);
expect(facets.find((f) => f.name === 'brand')).toBeUndefined();
});
});

it('Should not filter facets when isHiddenFilterFn returns false', async () => {
const isHiddenFilterFn = () => false;
const useFilterPropsWithHiddenFn = {
...useFilterProps,
isHiddenFilterFn,
};
const { result } = renderHookWithCioPlp(() => useFilter(useFilterPropsWithHiddenFn));

await waitFor(() => {
const {
current: { facets },
} = result;

expect(facets.length).toBe(searchData.response.facets.length);
});
});

it('Should filter facets by multiple conditions', async () => {
const isHiddenFilterFn = (facet) => facet.type === 'range';
const useFilterPropsWithHiddenFn = {
...useFilterProps,
isHiddenFilterFn,
};
const { result } = renderHookWithCioPlp(() => useFilter(useFilterPropsWithHiddenFn));

await waitFor(() => {
const {
current: { facets },
} = result;

// Should filter out all range type facets
expect(facets.every((f) => f.type !== 'range')).toBe(true);
});
});
});

describe('getIsHiddenFilterField via metadata', () => {
it('Should filter out facets with data.cio_plp_hidden = true', async () => {
// Create facets with hidden flag
const facetsWithHidden = searchData.response.facets.map((facet, index) => ({
...facet,
data: {
...facet.data,
cio_plp_hidden: index === 0, // Hide first facet
},
}));

const useFilterPropsWithHiddenData = {
facets: facetsWithHidden,
};
const { result } = renderHookWithCioPlp(() => useFilter(useFilterPropsWithHiddenData));

await waitFor(() => {
const {
current: { facets },
} = result;

expect(facets.length).toBe(facetsWithHidden.length - 1);
// First facet should be hidden
expect(facets[0].name).not.toBe(facetsWithHidden[0].name);
});
});

it('Should use custom getIsHiddenFilterField from itemFieldGetters', async () => {
// Create a custom field getter that hides facets with a custom field
const customGetIsHiddenFilterField = (facet) => facet.data?.customHidden === true;

const facetsWithCustomField = searchData.response.facets.map((facet, index) => ({
...facet,
data: {
...facet.data,
customHidden: index === 1, // Hide second facet
},
}));

const { result } = renderHook(
() => useFilter({ facets: facetsWithCustomField }),
{
wrapper: ({ children }) => (
<CioPlpProvider
apiKey={DEMO_API_KEY}
itemFieldGetters={{ getIsHiddenFilterField: customGetIsHiddenFilterField }}
>
{children}
</CioPlpProvider>
),
}
);

await waitFor(() => {
const {
current: { facets },
} = result;

expect(facets.length).toBe(facetsWithCustomField.length - 1);
// Second facet should be hidden
expect(facets.find((f) => f.name === facetsWithCustomField[1].name)).toBeUndefined();
});
});

it('Should prioritize isHiddenFilterFn over getIsHiddenFilterField', async () => {
// Both methods should work together - if either returns true, facet is hidden
const facetsWithHidden = searchData.response.facets.map((facet, index) => ({
...facet,
data: {
...facet.data,
cio_plp_hidden: index === 0, // Hide first facet via metadata
},
}));

const isHiddenFilterFn = (facet) => facet.name === facetsWithHidden[1].name; // Also hide second facet via fn

const useFilterPropsWithBoth = {
facets: facetsWithHidden,
isHiddenFilterFn,
};
const { result } = renderHookWithCioPlp(() => useFilter(useFilterPropsWithBoth));

await waitFor(() => {
const {
current: { facets },
} = result;

// Both first and second facets should be hidden
expect(facets.length).toBe(facetsWithHidden.length - 2);
expect(facets.find((f) => f.name === facetsWithHidden[0].name)).toBeUndefined();
expect(facets.find((f) => f.name === facetsWithHidden[1].name)).toBeUndefined();
});
});
});
});
Loading
Loading