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
2 changes: 1 addition & 1 deletion public/app.js

Large diffs are not rendered by default.

6 changes: 4 additions & 2 deletions src/components/Controls.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ export default function Controls({ state, setState, mapbox }) {
<div className="position-relative">
<form className="input-group" onSubmit={locationSearch}>
<input
aria-label={strings.modes[state.input.mode]}
className="form-control"
disabled={state.input.mode === 'me'}
onChange={e => {
Expand Down Expand Up @@ -194,7 +195,7 @@ export default function Controls({ state, setState, mapbox }) {
<div className="col-sm-6 col-lg mb-3" key={filter}>
<Dropdown
defaultValue={strings[filter + '_any']}
end={!canShowViews && !filters[index + 1]}
end={!canShowViews && index === filters.length - 1}
filter={filter}
open={dropdown === filter}
setDropdown={setDropdown}
Expand All @@ -204,10 +205,11 @@ export default function Controls({ state, setState, mapbox }) {
</div>
))}
{canShowViews && (
<div aria-hidden="true" className="col-sm-6 col-lg mb-3">
<div className="col-sm-6 col-lg mb-3">
<div className="btn-group h-100 w-100" role="group">
{views.map(view => (
<button
aria-label={strings.views[view]}
className={cx(
'btn btn-outline-secondary d-flex align-items-center justify-content-center w-100',
{
Expand Down
121 changes: 121 additions & 0 deletions src/components/Controls.spec.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
import { fireEvent, render, screen } from '@testing-library/react';
import Controls from './Controls';
import { strings } from '../helpers';

describe('<Controls />', () => {
jest.useFakeTimers();

const mockState = {
capabilities: {
coordinates: true,
geolocation: true,
region: true,
distance: true,
},
indexes: {
distance: [{ name: 'Foo', key: 'foo', slugs: [] }],
region: [{ name: 'Bar', key: 'bar', slugs: [] }],
},
input: {
mode: 'search',
distance: [],
region: [],
search: '',
view: 'list',
},
meetings: {
foo: { search: 'foo' },
bar: { search: 'bar' },
},
};

const mockSetState = jest.fn();

const mapbox = 'pk.abc123';

const { region_any, modes, views } = strings;

it('has clickable dropdowns', () => {
render(
<Controls state={mockState} setState={mockSetState} mapbox={mapbox} />
);

//click a dropdown button
const button = screen.getByRole('button', { name: region_any });
fireEvent.click(button);

//dropdown opens
const dropdown = screen.getByLabelText(region_any);
expect(dropdown).toHaveClass('show');

//dropdown closes
fireEvent.click(document.body);
expect(dropdown).not.toHaveClass('show');

//change the search mode
const locationLink = screen.getByText(modes.location);
fireEvent.click(locationLink);

//expect stateful thing to happen
expect(mockSetState).toBeCalledTimes(1);

jest.runAllTimers();
});

it('has working text search', () => {
render(
<Controls
state={{
...mockState,
capabilities: { ...mockState.capabilities, coordinates: false },
}}
setState={mockSetState}
mapbox={mapbox}
/>
);

//text search
const input = screen.getByRole('searchbox');
fireEvent.change(input, { target: { value: 'foo' } });

//try submitting
const form = input.closest('form');
fireEvent.submit(form);

expect(mockSetState).toBeCalledTimes(2);

jest.runAllTimers();
});

it('has working location search', () => {
render(
<Controls
state={{
...mockState,
input: { ...mockState.input, mode: 'location', view: 'map' },
}}
setState={mockSetState}
mapbox={mapbox}
/>
);

//enter search values
const input = screen.getByRole('searchbox');
fireEvent.change(input, { target: { value: 'bar' } });

//submit form
const form = input.closest('form');
fireEvent.submit(form);

//toggle
const button = screen.getByRole('button', { name: modes.location });
fireEvent.click(button);
fireEvent.click(button);

//toggle map button
const mapButton = screen.getByLabelText(views.map);
fireEvent.click(mapButton);

expect(mockSetState).toBeCalledTimes(4);
});
});
3 changes: 2 additions & 1 deletion src/components/Dropdown.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -81,9 +81,10 @@ export default function Dropdown({
return (
<div className="dropdown">
<button
aria-expanded={open}
className="btn btn-outline-secondary dropdown-toggle w-100"
onClick={() => setDropdown(open ? null : filter)}
id={filter}
onClick={() => setDropdown(open ? null : filter)}
>
{values?.length && options?.length
? values.map(value => getIndexByKey(options, value)?.name).join(' + ')
Expand Down
4 changes: 4 additions & 0 deletions src/i18n/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,10 @@ const en: Translation = {
},
unnamed_meeting: 'Unnamed meeting',
updated: 'Updated %updated%',
views: {
table: 'List',
map: 'Map',
},
wednesday: 'Wednesday',
weekday_any: 'Any Day',
};
Expand Down
4 changes: 4 additions & 0 deletions src/i18n/es.ts
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,10 @@ const es: Translation = {
},
unnamed_meeting: 'Reunión sin nombre',
updated: 'Actualizado el %updated%',
views: {
table: 'Lista',
map: 'Mapa',
},
wednesday: 'Miércoles',
weekday_any: 'Cualquier día',
};
Expand Down
4 changes: 4 additions & 0 deletions src/i18n/fr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,10 @@ const fr: Translation = {
},
unnamed_meeting: 'Réunion sans nom',
updated: 'Mis à jour le %updated%',
views: {
table: 'Liste',
map: 'Carte',
},
wednesday: 'Mercredi',
weekday_any: 'Tous les jours',
};
Expand Down
4 changes: 4 additions & 0 deletions src/types/Translation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,10 @@ export interface Translation {
types: Record<MeetingType, string>;
unnamed_meeting: string;
updated: string;
views: {
table: string;
map: string;
};
wednesday: string;
weekday_any: string;
}