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
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,27 @@ afterEach(() => {
});

describe('main filter panel', () => {
it('opens continent search without applying Africa or navigating before a choice', async () => {
Element.prototype.scrollIntoView = vi.fn();
const user = userEvent.setup();
const continents: FilterConfigSchema = {
...configs[0],
kind: 'SEARCH',
label: 'Continent',
paramKey: 'continents',
options: [
{ label: 'Africa', value: 'africa' },
{ label: 'Europe', value: 'europe' },
],
};
render(<FiltersAsideClient configs={[continents]} />);
await user.click(screen.getByRole('button', { name: 'Continent' }));
const search = screen.getByPlaceholderText('Search continent...');
await user.type(search, 'Europe');
expect(search).toHaveValue('Europe');
expect(setParam).not.toHaveBeenCalled();
});

it('offers previously hidden filters directly and applies the chosen option without selecting a default first', async () => {
const user = userEvent.setup();
render(<FiltersAsideClient configs={configs} />);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ const locationConfig = (position: number, label: string, paramKey: string) => ({
});

describe('dtoToFilterConfig location facets', () => {
it('keeps each geographic dimension distinct and suggested', () => {
it('keeps each geographic dimension searchable even with only two options', () => {
const result = dtoToFilterConfig({
countries: locationConfig(1, 'Country', 'countries'),
regions: locationConfig(2, 'Region', 'regions'),
Expand Down Expand Up @@ -64,6 +64,7 @@ describe('dtoToFilterConfig location facets', () => {
]),
);
for (const config of result) {
expect(config.kind).toBe('SEARCH');
if (!('options' in config)) continue;
for (const option of config.options) {
expect(option.value).toMatch(/^[a-z0-9]+(?:-[a-z0-9]+)*$/);
Expand Down
14 changes: 14 additions & 0 deletions src/features/filters/server/dtos/dto-to-filter-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,15 @@ const SUGGESTED_RANGE_PARAM_KEYS = new Set([
'maxActiveLeads',
]);

// Geography controls stay searchable even when only a few places are available.
const SEARCHABLE_LOCATION_PARAM_KEYS = new Set<string>([
PARAM_KEYS.CITIES,
PARAM_KEYS.REGIONS,
PARAM_KEYS.COUNTRIES,
PARAM_KEYS.CONTINENTS,
PARAM_KEYS.TIMEZONES,
]);

const RADIO_FILTER_OPTION_THRESHOLD = 6;
const CHECKBOX_FILTER_OPTION_THRESHOLD = 6;
const SELECT_OPTION_THRESHOLD = 2;
Expand Down Expand Up @@ -317,14 +326,19 @@ const handleMultiSelect = (
const normalizedDto = withRequiredRemoteWorkModes(dto);

// Get rid of issues where options look borked
const searchableLocation = SEARCHABLE_LOCATION_PARAM_KEYS.has(
normalizedDto.paramKey,
);
const minimumOptions =
searchableLocation ||
normalizedDto.paramKey === PARAM_KEYS.COLLABORATION_HOURS
? 1
: SELECT_OPTION_THRESHOLD;
const hasNoOptions = normalizedDto.options.length < minimumOptions;
if (hasNoOptions) return null;

const isCheckbox =
!searchableLocation &&
normalizedDto.options.length <= CHECKBOX_FILTER_OPTION_THRESHOLD;
const baseFilter = isCheckbox
? dtoToCheckboxFilterConfig(normalizedDto)
Expand Down
Loading