1
0
mirror of https://github.com/matrix-org/matrix-react-sdk.git synced 2025-08-07 21:23:00 +03:00

Live location share - focus on user location on list item click (PSG-609) (#9051)

* extract preventDefaultWrapper into utils

* add click handling to beacon list item

* add click handling to dialog sidebar

* focus in on beacons when clicked in list

* stylelint

* fussy import ordering

* test beacon focusing in beaocnviewdialog
This commit is contained in:
Kerry
2022-07-18 10:34:39 +02:00
committed by GitHub
parent 38a913488f
commit dc6ceb1d1c
16 changed files with 473 additions and 89 deletions

View File

@@ -15,7 +15,7 @@ limitations under the License.
*/
import React from 'react';
import { mount } from 'enzyme';
import { mount, ReactWrapper } from 'enzyme';
import { act } from 'react-dom/test-utils';
import {
MatrixClient,
@@ -28,15 +28,18 @@ import maplibregl from 'maplibre-gl';
import BeaconViewDialog from '../../../../src/components/views/beacon/BeaconViewDialog';
import {
findByAttr,
findByTestId,
getMockClientWithEventEmitter,
makeBeaconEvent,
makeBeaconInfoEvent,
makeRoomWithBeacons,
makeRoomWithStateEvents,
} from '../../../test-utils';
import { TILE_SERVER_WK_KEY } from '../../../../src/utils/WellKnownUtils';
import { OwnBeaconStore } from '../../../../src/stores/OwnBeaconStore';
import { BeaconDisplayStatus } from '../../../../src/components/views/beacon/displayStatus';
import BeaconListItem from '../../../../src/components/views/beacon/BeaconListItem';
describe('<BeaconViewDialog />', () => {
// 14.03.2022 16:15
@@ -89,13 +92,18 @@ describe('<BeaconViewDialog />', () => {
const getComponent = (props = {}) =>
mount(<BeaconViewDialog {...defaultProps} {...props} />);
const openSidebar = (component: ReactWrapper) => act(() => {
findByTestId(component, 'beacon-view-dialog-open-sidebar').at(0).simulate('click');
component.setProps({});
});
beforeAll(() => {
maplibregl.AttributionControl = jest.fn();
});
beforeEach(() => {
jest.spyOn(OwnBeaconStore.instance, 'getLiveBeaconIds').mockRestore();
jest.spyOn(global.Date, 'now').mockReturnValue(now);
jest.clearAllMocks();
});
@@ -225,10 +233,7 @@ describe('<BeaconViewDialog />', () => {
beacon.addLocations([location1]);
const component = getComponent();
act(() => {
findByTestId(component, 'beacon-view-dialog-open-sidebar').at(0).simulate('click');
component.setProps({});
});
openSidebar(component);
expect(component.find('DialogSidebar').length).toBeTruthy();
});
@@ -240,20 +245,134 @@ describe('<BeaconViewDialog />', () => {
const component = getComponent();
// open the sidebar
act(() => {
findByTestId(component, 'beacon-view-dialog-open-sidebar').at(0).simulate('click');
component.setProps({});
});
openSidebar(component);
expect(component.find('DialogSidebar').length).toBeTruthy();
// now close it
act(() => {
findByTestId(component, 'dialog-sidebar-close').at(0).simulate('click');
findByAttr('data-testid')(component, 'dialog-sidebar-close').at(0).simulate('click');
component.setProps({});
});
expect(component.find('DialogSidebar').length).toBeFalsy();
});
});
describe('focused beacons', () => {
const beacon2Event = makeBeaconInfoEvent(bobId,
roomId,
{ isLive: true },
'$bob-room1-2',
);
const location2 = makeBeaconEvent(
bobId, { beaconInfoId: beacon2Event.getId(), geoUri: 'geo:33,22', timestamp: now + 1 },
);
const fitBoundsOptions = { maxZoom: 15, padding: 100 };
it('opens map with both beacons in view on first load without initialFocusedBeacon', () => {
const [beacon1, beacon2] = makeRoomWithBeacons(
roomId, mockClient, [defaultEvent, beacon2Event], [location1, location2],
);
getComponent({ beacons: [beacon1, beacon2] });
// start centered on mid point between both beacons
expect(mockMap.setCenter).toHaveBeenCalledWith({ lat: 42, lon: 31.5 });
// only called once
expect(mockMap.setCenter).toHaveBeenCalledTimes(1);
// bounds fit both beacons, only called once
expect(mockMap.fitBounds).toHaveBeenCalledWith(new maplibregl.LngLatBounds(
[22, 33], [41, 51],
), fitBoundsOptions);
expect(mockMap.fitBounds).toHaveBeenCalledTimes(1);
});
it('opens map with both beacons in view on first load with an initially focused beacon', () => {
const [beacon1, beacon2] = makeRoomWithBeacons(
roomId, mockClient, [defaultEvent, beacon2Event], [location1, location2],
);
getComponent({ beacons: [beacon1, beacon2], initialFocusedBeacon: beacon1 });
// start centered on initialFocusedBeacon
expect(mockMap.setCenter).toHaveBeenCalledWith({ lat: 51, lon: 41 });
// only called once
expect(mockMap.setCenter).toHaveBeenCalledTimes(1);
// bounds fit both beacons, only called once
expect(mockMap.fitBounds).toHaveBeenCalledWith(new maplibregl.LngLatBounds(
[22, 33], [41, 51],
), fitBoundsOptions);
expect(mockMap.fitBounds).toHaveBeenCalledTimes(1);
});
it('focuses on beacon location on sidebar list item click', () => {
const [beacon1, beacon2] = makeRoomWithBeacons(
roomId, mockClient, [defaultEvent, beacon2Event], [location1, location2],
);
const component = getComponent({ beacons: [beacon1, beacon2] });
// reset call counts on map mocks after initial render
jest.clearAllMocks();
openSidebar(component);
act(() => {
// click on the first beacon in the list
component.find(BeaconListItem).at(0).simulate('click');
});
// centered on clicked beacon
expect(mockMap.setCenter).toHaveBeenCalledWith({ lat: 51, lon: 41 });
// only called once
expect(mockMap.setCenter).toHaveBeenCalledTimes(1);
// bounds fitted just to clicked beacon
expect(mockMap.fitBounds).toHaveBeenCalledWith(new maplibregl.LngLatBounds(
[41, 51], [41, 51],
), fitBoundsOptions);
expect(mockMap.fitBounds).toHaveBeenCalledTimes(1);
});
it('refocuses on same beacon when clicking list item again', () => {
// test the map responds to refocusing the same beacon
const [beacon1, beacon2] = makeRoomWithBeacons(
roomId, mockClient, [defaultEvent, beacon2Event], [location1, location2],
);
const component = getComponent({ beacons: [beacon1, beacon2] });
// reset call counts on map mocks after initial render
jest.clearAllMocks();
openSidebar(component);
act(() => {
// click on the second beacon in the list
component.find(BeaconListItem).at(1).simulate('click');
});
const expectedBounds = new maplibregl.LngLatBounds(
[22, 33], [22, 33],
);
// date is mocked but this relies on timestamp, manually mock a tick
jest.spyOn(global.Date, 'now').mockReturnValue(now + 1);
act(() => {
// click on the second beacon in the list
component.find(BeaconListItem).at(1).simulate('click');
});
// centered on clicked beacon
expect(mockMap.setCenter).toHaveBeenCalledWith({ lat: 33, lon: 22 });
// bounds fitted just to clicked beacon
expect(mockMap.fitBounds).toHaveBeenCalledWith(expectedBounds, fitBoundsOptions);
// each called once per click
expect(mockMap.setCenter).toHaveBeenCalledTimes(2);
expect(mockMap.fitBounds).toHaveBeenCalledTimes(2);
});
});
});