You've already forked matrix-react-sdk
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:
@@ -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);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
Reference in New Issue
Block a user