Apply prettier formatting

This commit is contained in:
Michael Weimann 2022-12-12 12:24:14 +01:00
parent 1cac306093
commit 526645c791
No known key found for this signature in database
GPG key ID: 53F535A266BB9584
1576 changed files with 65385 additions and 62478 deletions

View file

@ -14,32 +14,28 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import React from 'react';
import React from "react";
import { fireEvent, render } from "@testing-library/react";
import {
Beacon,
RoomMember,
MatrixEvent,
} from 'matrix-js-sdk/src/matrix';
import { LocationAssetType } from 'matrix-js-sdk/src/@types/location';
import { act } from 'react-dom/test-utils';
import { Beacon, RoomMember, MatrixEvent } from "matrix-js-sdk/src/matrix";
import { LocationAssetType } from "matrix-js-sdk/src/@types/location";
import { act } from "react-dom/test-utils";
import BeaconListItem from '../../../../src/components/views/beacon/BeaconListItem';
import MatrixClientContext from '../../../../src/contexts/MatrixClientContext';
import BeaconListItem from "../../../../src/components/views/beacon/BeaconListItem";
import MatrixClientContext from "../../../../src/contexts/MatrixClientContext";
import {
getMockClientWithEventEmitter,
makeBeaconEvent,
makeBeaconInfoEvent,
makeRoomWithBeacons,
} from '../../../test-utils';
} from "../../../test-utils";
describe('<BeaconListItem />', () => {
describe("<BeaconListItem />", () => {
// 14.03.2022 16:15
const now = 1647270879403;
// go back in time to create beacons and locations in the past
jest.spyOn(global.Date, 'now').mockReturnValue(now - 600000);
const roomId = '!room:server';
const aliceId = '@alice:server';
jest.spyOn(global.Date, "now").mockReturnValue(now - 600000);
const roomId = "!room:server";
const aliceId = "@alice:server";
const mockClient = getMockClientWithEventEmitter({
getUserId: jest.fn().mockReturnValue(aliceId),
@ -47,36 +43,41 @@ describe('<BeaconListItem />', () => {
isGuest: jest.fn().mockReturnValue(false),
});
const aliceBeaconEvent = makeBeaconInfoEvent(aliceId,
roomId,
{ isLive: true },
'$alice-room1-1',
);
const alicePinBeaconEvent = makeBeaconInfoEvent(aliceId,
const aliceBeaconEvent = makeBeaconInfoEvent(aliceId, roomId, { isLive: true }, "$alice-room1-1");
const alicePinBeaconEvent = makeBeaconInfoEvent(
aliceId,
roomId,
{ isLive: true, assetType: LocationAssetType.Pin, description: "Alice's car" },
'$alice-room1-1',
"$alice-room1-1",
);
const pinBeaconWithoutDescription = makeBeaconInfoEvent(aliceId,
const pinBeaconWithoutDescription = makeBeaconInfoEvent(
aliceId,
roomId,
{ isLive: true, assetType: LocationAssetType.Pin },
'$alice-room1-1',
"$alice-room1-1",
);
const aliceLocation1 = makeBeaconEvent(
aliceId, { beaconInfoId: aliceBeaconEvent.getId(), geoUri: 'geo:51,41', timestamp: now - 1 },
);
const aliceLocation2 = makeBeaconEvent(
aliceId, { beaconInfoId: aliceBeaconEvent.getId(), geoUri: 'geo:52,42', timestamp: now - 500000 },
);
const aliceLocation1 = makeBeaconEvent(aliceId, {
beaconInfoId: aliceBeaconEvent.getId(),
geoUri: "geo:51,41",
timestamp: now - 1,
});
const aliceLocation2 = makeBeaconEvent(aliceId, {
beaconInfoId: aliceBeaconEvent.getId(),
geoUri: "geo:52,42",
timestamp: now - 500000,
});
const defaultProps = {
beacon: new Beacon(aliceBeaconEvent),
};
const getComponent = (props = {}) => render(<MatrixClientContext.Provider value={mockClient}>
<BeaconListItem {...defaultProps} {...props} />
</MatrixClientContext.Provider>);
const getComponent = (props = {}) =>
render(
<MatrixClientContext.Provider value={mockClient}>
<BeaconListItem {...defaultProps} {...props} />
</MatrixClientContext.Provider>,
);
const setupRoomWithBeacons = (beaconInfoEvents: MatrixEvent[], locationEvents?: MatrixEvent[]): Beacon[] => {
const beacons = makeRoomWithBeacons(roomId, mockClient, beaconInfoEvents, locationEvents);
@ -84,102 +85,101 @@ describe('<BeaconListItem />', () => {
const member = new RoomMember(roomId, aliceId);
member.name = `Alice`;
const room = mockClient.getRoom(roomId);
jest.spyOn(room, 'getMember').mockReturnValue(member);
jest.spyOn(room, "getMember").mockReturnValue(member);
return beacons;
};
beforeEach(() => {
jest.clearAllMocks();
jest.spyOn(Date, 'now').mockReturnValue(now);
jest.spyOn(Date, "now").mockReturnValue(now);
});
it('renders null when beacon is not live', () => {
const notLiveBeacon = makeBeaconInfoEvent(aliceId,
roomId,
{ isLive: false },
);
it("renders null when beacon is not live", () => {
const notLiveBeacon = makeBeaconInfoEvent(aliceId, roomId, { isLive: false });
const [beacon] = setupRoomWithBeacons([notLiveBeacon]);
const { container } = getComponent({ beacon });
expect(container.innerHTML).toBeFalsy();
});
it('renders null when beacon has no location', () => {
it("renders null when beacon has no location", () => {
const [beacon] = setupRoomWithBeacons([aliceBeaconEvent]);
const { container } = getComponent({ beacon });
expect(container.innerHTML).toBeFalsy();
});
describe('when a beacon is live and has locations', () => {
it('renders beacon info', () => {
describe("when a beacon is live and has locations", () => {
it("renders beacon info", () => {
const [beacon] = setupRoomWithBeacons([alicePinBeaconEvent], [aliceLocation1]);
const { asFragment } = getComponent({ beacon });
expect(asFragment()).toMatchSnapshot();
});
describe('non-self beacons', () => {
it('uses beacon description as beacon name', () => {
describe("non-self beacons", () => {
it("uses beacon description as beacon name", () => {
const [beacon] = setupRoomWithBeacons([alicePinBeaconEvent], [aliceLocation1]);
const { container } = getComponent({ beacon });
expect(container.querySelector('.mx_BeaconStatus_label')).toHaveTextContent("Alice's car");
expect(container.querySelector(".mx_BeaconStatus_label")).toHaveTextContent("Alice's car");
});
it('uses beacon owner mxid as beacon name for a beacon without description', () => {
it("uses beacon owner mxid as beacon name for a beacon without description", () => {
const [beacon] = setupRoomWithBeacons([pinBeaconWithoutDescription], [aliceLocation1]);
const { container } = getComponent({ beacon });
expect(container.querySelector('.mx_BeaconStatus_label')).toHaveTextContent(aliceId);
expect(container.querySelector(".mx_BeaconStatus_label")).toHaveTextContent(aliceId);
});
it('renders location icon', () => {
it("renders location icon", () => {
const [beacon] = setupRoomWithBeacons([alicePinBeaconEvent], [aliceLocation1]);
const { container } = getComponent({ beacon });
expect(container.querySelector('.mx_StyledLiveBeaconIcon')).toBeTruthy();
expect(container.querySelector(".mx_StyledLiveBeaconIcon")).toBeTruthy();
});
});
describe('self locations', () => {
it('renders beacon owner avatar', () => {
describe("self locations", () => {
it("renders beacon owner avatar", () => {
const [beacon] = setupRoomWithBeacons([aliceBeaconEvent], [aliceLocation1]);
const { container } = getComponent({ beacon });
expect(container.querySelector('.mx_BaseAvatar')).toBeTruthy();
expect(container.querySelector(".mx_BaseAvatar")).toBeTruthy();
});
it('uses beacon owner name as beacon name', () => {
it("uses beacon owner name as beacon name", () => {
const [beacon] = setupRoomWithBeacons([aliceBeaconEvent], [aliceLocation1]);
const { container } = getComponent({ beacon });
expect(container.querySelector('.mx_BeaconStatus_label')).toHaveTextContent("Alice");
expect(container.querySelector(".mx_BeaconStatus_label")).toHaveTextContent("Alice");
});
});
describe('on location updates', () => {
it('updates last updated time on location updated', () => {
describe("on location updates", () => {
it("updates last updated time on location updated", () => {
const [beacon] = setupRoomWithBeacons([aliceBeaconEvent], [aliceLocation2]);
const { container } = getComponent({ beacon });
expect(container.querySelector('.mx_BeaconListItem_lastUpdated'))
.toHaveTextContent('Updated 9 minutes ago');
expect(container.querySelector(".mx_BeaconListItem_lastUpdated")).toHaveTextContent(
"Updated 9 minutes ago",
);
// update to a newer location
act(() => {
beacon.addLocations([aliceLocation1]);
});
expect(container.querySelector('.mx_BeaconListItem_lastUpdated'))
.toHaveTextContent('Updated a few seconds ago');
expect(container.querySelector(".mx_BeaconListItem_lastUpdated")).toHaveTextContent(
"Updated a few seconds ago",
);
});
});
describe('interactions', () => {
it('does not call onClick handler when clicking share button', () => {
describe("interactions", () => {
it("does not call onClick handler when clicking share button", () => {
const [beacon] = setupRoomWithBeacons([alicePinBeaconEvent], [aliceLocation1]);
const onClick = jest.fn();
const { getByTestId } = getComponent({ beacon, onClick });
fireEvent.click(getByTestId('open-location-in-osm'));
fireEvent.click(getByTestId("open-location-in-osm"));
expect(onClick).not.toHaveBeenCalled();
});
it('calls onClick handler when clicking outside of share buttons', () => {
it("calls onClick handler when clicking outside of share buttons", () => {
const [beacon] = setupRoomWithBeacons([alicePinBeaconEvent], [aliceLocation1]);
const onClick = jest.fn();
const { container } = getComponent({ beacon, onClick });

View file

@ -14,36 +14,30 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import React from 'react';
import React from "react";
// eslint-disable-next-line deprecate/import
import { mount } from 'enzyme';
import maplibregl from 'maplibre-gl';
import { act } from 'react-dom/test-utils';
import {
Beacon,
Room,
RoomMember,
MatrixEvent,
getBeaconInfoIdentifier,
} from 'matrix-js-sdk/src/matrix';
import { mount } from "enzyme";
import maplibregl from "maplibre-gl";
import { act } from "react-dom/test-utils";
import { Beacon, Room, RoomMember, MatrixEvent, getBeaconInfoIdentifier } from "matrix-js-sdk/src/matrix";
import BeaconMarker from '../../../../src/components/views/beacon/BeaconMarker';
import MatrixClientContext from '../../../../src/contexts/MatrixClientContext';
import BeaconMarker from "../../../../src/components/views/beacon/BeaconMarker";
import MatrixClientContext from "../../../../src/contexts/MatrixClientContext";
import {
getMockClientWithEventEmitter,
makeBeaconEvent,
makeBeaconInfoEvent,
makeRoomWithStateEvents,
} from '../../../test-utils';
import { TILE_SERVER_WK_KEY } from '../../../../src/utils/WellKnownUtils';
} from "../../../test-utils";
import { TILE_SERVER_WK_KEY } from "../../../../src/utils/WellKnownUtils";
describe('<BeaconMarker />', () => {
describe("<BeaconMarker />", () => {
// 14.03.2022 16:15
const now = 1647270879403;
// stable date for snapshots
jest.spyOn(global.Date, 'now').mockReturnValue(now);
const roomId = '!room:server';
const aliceId = '@alice:server';
jest.spyOn(global.Date, "now").mockReturnValue(now);
const roomId = "!room:server";
const aliceId = "@alice:server";
const aliceMember = new RoomMember(roomId, aliceId);
@ -51,7 +45,7 @@ describe('<BeaconMarker />', () => {
const mockClient = getMockClientWithEventEmitter({
getClientWellKnown: jest.fn().mockReturnValue({
[TILE_SERVER_WK_KEY.name]: { map_style_url: 'maps.com' },
[TILE_SERVER_WK_KEY.name]: { map_style_url: "maps.com" },
}),
getUserId: jest.fn().mockReturnValue(aliceId),
getRoom: jest.fn(),
@ -62,27 +56,23 @@ describe('<BeaconMarker />', () => {
// as we update room state
const setupRoom = (stateEvents: MatrixEvent[] = []): Room => {
const room1 = makeRoomWithStateEvents(stateEvents, { roomId, mockClient });
jest.spyOn(room1, 'getMember').mockReturnValue(aliceMember);
jest.spyOn(room1, "getMember").mockReturnValue(aliceMember);
return room1;
};
const defaultEvent = makeBeaconInfoEvent(aliceId,
roomId,
{ isLive: true },
'$alice-room1-1',
);
const notLiveEvent = makeBeaconInfoEvent(aliceId,
roomId,
{ isLive: false },
'$alice-room1-2',
);
const defaultEvent = makeBeaconInfoEvent(aliceId, roomId, { isLive: true }, "$alice-room1-1");
const notLiveEvent = makeBeaconInfoEvent(aliceId, roomId, { isLive: false }, "$alice-room1-2");
const location1 = makeBeaconEvent(
aliceId, { beaconInfoId: defaultEvent.getId(), geoUri: 'geo:51,41', timestamp: now + 1 },
);
const location2 = makeBeaconEvent(
aliceId, { beaconInfoId: defaultEvent.getId(), geoUri: 'geo:52,42', timestamp: now + 10000 },
);
const location1 = makeBeaconEvent(aliceId, {
beaconInfoId: defaultEvent.getId(),
geoUri: "geo:51,41",
timestamp: now + 1,
});
const location2 = makeBeaconEvent(aliceId, {
beaconInfoId: defaultEvent.getId(),
geoUri: "geo:52,42",
timestamp: now + 10000,
});
const defaultProps = {
map: mockMap,
@ -99,21 +89,21 @@ describe('<BeaconMarker />', () => {
jest.clearAllMocks();
});
it('renders nothing when beacon is not live', () => {
it("renders nothing when beacon is not live", () => {
const room = setupRoom([notLiveEvent]);
const beacon = room.currentState.beacons.get(getBeaconInfoIdentifier(notLiveEvent));
const component = getComponent({ beacon });
expect(component.html()).toBe(null);
});
it('renders nothing when beacon has no location', () => {
it("renders nothing when beacon has no location", () => {
const room = setupRoom([defaultEvent]);
const beacon = room.currentState.beacons.get(getBeaconInfoIdentifier(defaultEvent));
const component = getComponent({ beacon });
expect(component.html()).toBe(null);
});
it('renders marker when beacon has location', () => {
it("renders marker when beacon has location", () => {
const room = setupRoom([defaultEvent]);
const beacon = room.currentState.beacons.get(getBeaconInfoIdentifier(defaultEvent));
beacon.addLocations([location1]);
@ -121,12 +111,12 @@ describe('<BeaconMarker />', () => {
expect(component).toMatchSnapshot();
});
it('updates with new locations', () => {
it("updates with new locations", () => {
const room = setupRoom([defaultEvent]);
const beacon = room.currentState.beacons.get(getBeaconInfoIdentifier(defaultEvent));
beacon.addLocations([location1]);
const component = getComponent({ beacon });
expect(component.find('SmartMarker').props()['geoUri']).toEqual('geo:51,41');
expect(component.find("SmartMarker").props()["geoUri"]).toEqual("geo:51,41");
act(() => {
beacon.addLocations([location2]);
@ -134,6 +124,6 @@ describe('<BeaconMarker />', () => {
component.setProps({});
// updated to latest location
expect(component.find('SmartMarker').props()['geoUri']).toEqual('geo:52,42');
expect(component.find("SmartMarker").props()["geoUri"]).toEqual("geo:52,42");
});
});

View file

@ -14,75 +14,75 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import React from 'react';
import React from "react";
// eslint-disable-next-line deprecate/import
import { mount } from 'enzyme';
import { Beacon } from 'matrix-js-sdk/src/matrix';
import { mount } from "enzyme";
import { Beacon } from "matrix-js-sdk/src/matrix";
import BeaconStatus from '../../../../src/components/views/beacon/BeaconStatus';
import { BeaconDisplayStatus } from '../../../../src/components/views/beacon/displayStatus';
import { findByTestId, makeBeaconInfoEvent } from '../../../test-utils';
import BeaconStatus from "../../../../src/components/views/beacon/BeaconStatus";
import { BeaconDisplayStatus } from "../../../../src/components/views/beacon/displayStatus";
import { findByTestId, makeBeaconInfoEvent } from "../../../test-utils";
describe('<BeaconStatus />', () => {
describe("<BeaconStatus />", () => {
const defaultProps = {
displayStatus: BeaconDisplayStatus.Loading,
label: 'test label',
label: "test label",
withIcon: true,
};
const getComponent = (props = {}) =>
mount(<BeaconStatus {...defaultProps} {...props} />);
const getComponent = (props = {}) => mount(<BeaconStatus {...defaultProps} {...props} />);
it('renders loading state', () => {
it("renders loading state", () => {
const component = getComponent({ displayStatus: BeaconDisplayStatus.Loading });
expect(component).toMatchSnapshot();
});
it('renders stopped state', () => {
it("renders stopped state", () => {
const component = getComponent({ displayStatus: BeaconDisplayStatus.Stopped });
expect(component).toMatchSnapshot();
});
it('renders without icon', () => {
it("renders without icon", () => {
const component = getComponent({ withIcon: false, displayStatus: BeaconDisplayStatus.Stopped });
expect(component.find('StyledLiveBeaconIcon').length).toBeFalsy();
expect(component.find("StyledLiveBeaconIcon").length).toBeFalsy();
});
describe('active state', () => {
it('renders without children', () => {
describe("active state", () => {
it("renders without children", () => {
// mock for stable snapshot
jest.spyOn(Date, 'now').mockReturnValue(123456789);
const beacon = new Beacon(makeBeaconInfoEvent('@user:server', '!room:server', { isLive: false }, '$1'));
jest.spyOn(Date, "now").mockReturnValue(123456789);
const beacon = new Beacon(makeBeaconInfoEvent("@user:server", "!room:server", { isLive: false }, "$1"));
const component = getComponent({ beacon, displayStatus: BeaconDisplayStatus.Active });
expect(component).toMatchSnapshot();
});
it('renders with children', () => {
const beacon = new Beacon(makeBeaconInfoEvent('@user:server', '!room:sever', { isLive: false }));
it("renders with children", () => {
const beacon = new Beacon(makeBeaconInfoEvent("@user:server", "!room:sever", { isLive: false }));
const component = getComponent({
beacon,
children: <span data-test-id='test'>test</span>,
children: <span data-test-id="test">test</span>,
displayStatus: BeaconDisplayStatus.Active,
});
expect(findByTestId(component, 'test-child')).toMatchSnapshot();
expect(findByTestId(component, "test-child")).toMatchSnapshot();
});
it('renders static remaining time when displayLiveTimeRemaining is falsy', () => {
it("renders static remaining time when displayLiveTimeRemaining is falsy", () => {
// mock for stable snapshot
jest.spyOn(Date, 'now').mockReturnValue(123456789);
const beacon = new Beacon(makeBeaconInfoEvent('@user:server', '!room:server', { isLive: false }, '$1'));
jest.spyOn(Date, "now").mockReturnValue(123456789);
const beacon = new Beacon(makeBeaconInfoEvent("@user:server", "!room:server", { isLive: false }, "$1"));
const component = getComponent({ beacon, displayStatus: BeaconDisplayStatus.Active });
expect(component.text().includes('Live until 11:17')).toBeTruthy();
expect(component.text().includes("Live until 11:17")).toBeTruthy();
});
it('renders live time remaining when displayLiveTimeRemaining is truthy', () => {
it("renders live time remaining when displayLiveTimeRemaining is truthy", () => {
// mock for stable snapshot
jest.spyOn(Date, 'now').mockReturnValue(123456789);
const beacon = new Beacon(makeBeaconInfoEvent('@user:server', '!room:server', { isLive: false }, '$1'));
jest.spyOn(Date, "now").mockReturnValue(123456789);
const beacon = new Beacon(makeBeaconInfoEvent("@user:server", "!room:server", { isLive: false }, "$1"));
const component = getComponent({
beacon, displayStatus: BeaconDisplayStatus.Active,
beacon,
displayStatus: BeaconDisplayStatus.Active,
displayLiveTimeRemaining: true,
});
expect(component.text().includes('1h left')).toBeTruthy();
expect(component.text().includes("1h left")).toBeTruthy();
});
});
});

View file

@ -14,21 +14,15 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import React from 'react';
import React from "react";
// eslint-disable-next-line deprecate/import
import { mount, ReactWrapper } from 'enzyme';
import { act } from 'react-dom/test-utils';
import {
MatrixClient,
MatrixEvent,
Room,
RoomMember,
getBeaconInfoIdentifier,
} from 'matrix-js-sdk/src/matrix';
import maplibregl from 'maplibre-gl';
import { mocked } from 'jest-mock';
import { mount, ReactWrapper } from "enzyme";
import { act } from "react-dom/test-utils";
import { MatrixClient, MatrixEvent, Room, RoomMember, getBeaconInfoIdentifier } from "matrix-js-sdk/src/matrix";
import maplibregl from "maplibre-gl";
import { mocked } from "jest-mock";
import BeaconViewDialog from '../../../../src/components/views/beacon/BeaconViewDialog';
import BeaconViewDialog from "../../../../src/components/views/beacon/BeaconViewDialog";
import {
findByAttr,
findByTestId,
@ -37,26 +31,26 @@ import {
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';
} 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 />', () => {
describe("<BeaconViewDialog />", () => {
// 14.03.2022 16:15
const now = 1647270879403;
// stable date for snapshots
jest.spyOn(global.Date, 'now').mockReturnValue(now);
const roomId = '!room:server';
const aliceId = '@alice:server';
const bobId = '@bob:server';
jest.spyOn(global.Date, "now").mockReturnValue(now);
const roomId = "!room:server";
const aliceId = "@alice:server";
const bobId = "@bob:server";
const aliceMember = new RoomMember(roomId, aliceId);
const mockClient = getMockClientWithEventEmitter({
getClientWellKnown: jest.fn().mockReturnValue({
[TILE_SERVER_WK_KEY.name]: { map_style_url: 'maps.com' },
[TILE_SERVER_WK_KEY.name]: { map_style_url: "maps.com" },
}),
getUserId: jest.fn().mockReturnValue(bobId),
getRoom: jest.fn(),
@ -70,20 +64,18 @@ describe('<BeaconViewDialog />', () => {
// as we update room state
const setupRoom = (stateEvents: MatrixEvent[] = []): Room => {
const room1 = makeRoomWithStateEvents(stateEvents, { roomId, mockClient });
jest.spyOn(room1, 'getMember').mockReturnValue(aliceMember);
jest.spyOn(room1, "getMember").mockReturnValue(aliceMember);
return room1;
};
const defaultEvent = makeBeaconInfoEvent(aliceId,
roomId,
{ isLive: true },
'$alice-room1-1',
);
const defaultEvent = makeBeaconInfoEvent(aliceId, roomId, { isLive: true }, "$alice-room1-1");
const location1 = makeBeaconEvent(
aliceId, { beaconInfoId: defaultEvent.getId(), geoUri: 'geo:51,41', timestamp: now + 1 },
);
const location1 = makeBeaconEvent(aliceId, {
beaconInfoId: defaultEvent.getId(),
geoUri: "geo:51,41",
timestamp: now + 1,
});
const defaultProps = {
onFinished: jest.fn(),
@ -91,74 +83,73 @@ describe('<BeaconViewDialog />', () => {
matrixClient: mockClient as MatrixClient,
};
const getComponent = (props = {}) =>
mount(<BeaconViewDialog {...defaultProps} {...props} />);
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({});
});
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(OwnBeaconStore.instance, 'getBeaconById').mockRestore();
jest.spyOn(global.Date, 'now').mockReturnValue(now);
jest.spyOn(OwnBeaconStore.instance, "getLiveBeaconIds").mockRestore();
jest.spyOn(OwnBeaconStore.instance, "getBeaconById").mockRestore();
jest.spyOn(global.Date, "now").mockReturnValue(now);
jest.clearAllMocks();
});
it('renders a map with markers', () => {
it("renders a map with markers", () => {
const room = setupRoom([defaultEvent]);
const beacon = room.currentState.beacons.get(getBeaconInfoIdentifier(defaultEvent));
beacon.addLocations([location1]);
const component = getComponent();
expect(component.find('Map').props()).toEqual(expect.objectContaining({
centerGeoUri: 'geo:51,41',
interactive: true,
}));
expect(component.find('SmartMarker').length).toEqual(1);
expect(component.find("Map").props()).toEqual(
expect.objectContaining({
centerGeoUri: "geo:51,41",
interactive: true,
}),
);
expect(component.find("SmartMarker").length).toEqual(1);
});
it('does not render any own beacon status when user is not live sharing', () => {
it("does not render any own beacon status when user is not live sharing", () => {
// default event belongs to alice, we are bob
const room = setupRoom([defaultEvent]);
const beacon = room.currentState.beacons.get(getBeaconInfoIdentifier(defaultEvent));
beacon.addLocations([location1]);
const component = getComponent();
expect(component.find('DialogOwnBeaconStatus').html()).toBeNull();
expect(component.find("DialogOwnBeaconStatus").html()).toBeNull();
});
it('renders own beacon status when user is live sharing', () => {
it("renders own beacon status when user is live sharing", () => {
// default event belongs to alice
const room = setupRoom([defaultEvent]);
const beacon = room.currentState.beacons.get(getBeaconInfoIdentifier(defaultEvent));
beacon.addLocations([location1]);
// mock own beacon store to show default event as alice's live beacon
jest.spyOn(OwnBeaconStore.instance, 'getLiveBeaconIds').mockReturnValue([beacon.identifier]);
jest.spyOn(OwnBeaconStore.instance, 'getBeaconById').mockReturnValue(beacon);
jest.spyOn(OwnBeaconStore.instance, "getLiveBeaconIds").mockReturnValue([beacon.identifier]);
jest.spyOn(OwnBeaconStore.instance, "getBeaconById").mockReturnValue(beacon);
const component = getComponent();
expect(component.find('MemberAvatar').length).toBeTruthy();
expect(component.find('OwnBeaconStatus').props()).toEqual({
beacon, displayStatus: BeaconDisplayStatus.Active,
className: 'mx_DialogOwnBeaconStatus_status',
expect(component.find("MemberAvatar").length).toBeTruthy();
expect(component.find("OwnBeaconStatus").props()).toEqual({
beacon,
displayStatus: BeaconDisplayStatus.Active,
className: "mx_DialogOwnBeaconStatus_status",
});
});
it('updates markers on changes to beacons', () => {
it("updates markers on changes to beacons", () => {
const room = setupRoom([defaultEvent]);
const beacon = room.currentState.beacons.get(getBeaconInfoIdentifier(defaultEvent));
beacon.addLocations([location1]);
const component = getComponent();
expect(component.find('BeaconMarker').length).toEqual(1);
expect(component.find("BeaconMarker").length).toEqual(1);
const anotherBeaconEvent = makeBeaconInfoEvent(bobId,
roomId,
{ isLive: true },
'$bob-room1-1',
);
const anotherBeaconEvent = makeBeaconInfoEvent(bobId, roomId, { isLive: true }, "$bob-room1-1");
act(() => {
// emits RoomStateEvent.BeaconLiveness
@ -168,21 +159,17 @@ describe('<BeaconViewDialog />', () => {
component.setProps({});
// two markers now!
expect(component.find('BeaconMarker').length).toEqual(2);
expect(component.find("BeaconMarker").length).toEqual(2);
});
it('does not update bounds or center on changing beacons', () => {
it("does not update bounds or center on changing beacons", () => {
const room = setupRoom([defaultEvent]);
const beacon = room.currentState.beacons.get(getBeaconInfoIdentifier(defaultEvent));
beacon.addLocations([location1]);
const component = getComponent();
expect(component.find('BeaconMarker').length).toEqual(1);
expect(component.find("BeaconMarker").length).toEqual(1);
const anotherBeaconEvent = makeBeaconInfoEvent(bobId,
roomId,
{ isLive: true },
'$bob-room1-1',
);
const anotherBeaconEvent = makeBeaconInfoEvent(bobId, roomId, { isLive: true }, "$bob-room1-1");
act(() => {
// emits RoomStateEvent.BeaconLiveness
@ -196,7 +183,7 @@ describe('<BeaconViewDialog />', () => {
expect(mockMap.fitBounds).toHaveBeenCalledTimes(1);
});
it('renders a fallback when there are no locations', () => {
it("renders a fallback when there are no locations", () => {
// this is a cornercase, should not be a reachable state in UI anymore
const onFinished = jest.fn();
const room = setupRoom([defaultEvent]);
@ -204,30 +191,26 @@ describe('<BeaconViewDialog />', () => {
const component = getComponent({ onFinished });
// map placeholder
expect(findByTestId(component, 'beacon-view-dialog-map-fallback')).toMatchSnapshot();
expect(findByTestId(component, "beacon-view-dialog-map-fallback")).toMatchSnapshot();
act(() => {
findByTestId(component, 'beacon-view-dialog-fallback-close').at(0).simulate('click');
findByTestId(component, "beacon-view-dialog-fallback-close").at(0).simulate("click");
});
expect(onFinished).toHaveBeenCalled();
});
it('renders map without markers when no live beacons remain', () => {
it("renders map without markers when no live beacons remain", () => {
const onFinished = jest.fn();
const room = setupRoom([defaultEvent]);
const beacon = room.currentState.beacons.get(getBeaconInfoIdentifier(defaultEvent));
beacon.addLocations([location1]);
const component = getComponent({ onFinished });
expect(component.find('BeaconMarker').length).toEqual(1);
expect(component.find("BeaconMarker").length).toEqual(1);
// this will replace the defaultEvent
// leading to no more live beacons
const anotherBeaconEvent = makeBeaconInfoEvent(aliceId,
roomId,
{ isLive: false },
'$alice-room1-2',
);
const anotherBeaconEvent = makeBeaconInfoEvent(aliceId, roomId, { isLive: false }, "$alice-room1-2");
expect(mockMap.setCenter).toHaveBeenCalledWith({ lat: 51, lon: 41 });
// reset call counts
@ -242,16 +225,16 @@ describe('<BeaconViewDialog />', () => {
component.setProps({});
// no more avatars
expect(component.find('MemberAvatar').length).toBeFalsy();
expect(component.find("MemberAvatar").length).toBeFalsy();
// map still rendered
expect(component.find('Map').length).toBeTruthy();
expect(component.find("Map").length).toBeTruthy();
// map location unchanged
expect(mockMap.setCenter).not.toHaveBeenCalled();
expect(mockMap.fitBounds).not.toHaveBeenCalled();
});
describe('sidebar', () => {
it('opens sidebar on view list button click', () => {
describe("sidebar", () => {
it("opens sidebar on view list button click", () => {
const room = setupRoom([defaultEvent]);
const beacon = room.currentState.beacons.get(getBeaconInfoIdentifier(defaultEvent));
beacon.addLocations([location1]);
@ -259,10 +242,10 @@ describe('<BeaconViewDialog />', () => {
openSidebar(component);
expect(component.find('DialogSidebar').length).toBeTruthy();
expect(component.find("DialogSidebar").length).toBeTruthy();
});
it('closes sidebar on close button click', () => {
it("closes sidebar on close button click", () => {
const room = setupRoom([defaultEvent]);
const beacon = room.currentState.beacons.get(getBeaconInfoIdentifier(defaultEvent));
beacon.addLocations([location1]);
@ -271,34 +254,35 @@ describe('<BeaconViewDialog />', () => {
// open the sidebar
openSidebar(component);
expect(component.find('DialogSidebar').length).toBeTruthy();
expect(component.find("DialogSidebar").length).toBeTruthy();
// now close it
act(() => {
findByAttr('data-testid')(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();
expect(component.find("DialogSidebar").length).toBeFalsy();
});
});
describe('focused beacons', () => {
const beacon2Event = makeBeaconInfoEvent(bobId,
roomId,
{ isLive: true },
'$bob-room1-2',
);
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 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', () => {
it("opens map with both beacons in view on first load without initialFocusedBeacon", () => {
const [beacon1, beacon2] = makeRoomWithBeacons(
roomId, mockClient, [defaultEvent, beacon2Event], [location1, location2],
roomId,
mockClient,
[defaultEvent, beacon2Event],
[location1, location2],
);
getComponent({ beacons: [beacon1, beacon2] });
@ -308,15 +292,19 @@ describe('<BeaconViewDialog />', () => {
// 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).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', () => {
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],
roomId,
mockClient,
[defaultEvent, beacon2Event],
[location1, location2],
);
getComponent({ beacons: [beacon1, beacon2], initialFocusedBeacon: beacon1 });
@ -326,15 +314,19 @@ describe('<BeaconViewDialog />', () => {
// 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).toHaveBeenCalledWith(
new maplibregl.LngLatBounds([22, 33], [41, 51]),
fitBoundsOptions,
);
expect(mockMap.fitBounds).toHaveBeenCalledTimes(1);
});
it('focuses on beacon location on sidebar list item click', () => {
it("focuses on beacon location on sidebar list item click", () => {
const [beacon1, beacon2] = makeRoomWithBeacons(
roomId, mockClient, [defaultEvent, beacon2Event], [location1, location2],
roomId,
mockClient,
[defaultEvent, beacon2Event],
[location1, location2],
);
const component = getComponent({ beacons: [beacon1, beacon2] });
@ -346,7 +338,7 @@ describe('<BeaconViewDialog />', () => {
act(() => {
// click on the first beacon in the list
component.find(BeaconListItem).at(0).simulate('click');
component.find(BeaconListItem).at(0).simulate("click");
});
// centered on clicked beacon
@ -354,16 +346,20 @@ describe('<BeaconViewDialog />', () => {
// 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).toHaveBeenCalledWith(
new maplibregl.LngLatBounds([41, 51], [41, 51]),
fitBoundsOptions,
);
expect(mockMap.fitBounds).toHaveBeenCalledTimes(1);
});
it('refocuses on same beacon when clicking list item again', () => {
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],
roomId,
mockClient,
[defaultEvent, beacon2Event],
[location1, location2],
);
const component = getComponent({ beacons: [beacon1, beacon2] });
@ -375,19 +371,17 @@ describe('<BeaconViewDialog />', () => {
act(() => {
// click on the second beacon in the list
component.find(BeaconListItem).at(1).simulate('click');
component.find(BeaconListItem).at(1).simulate("click");
});
const expectedBounds = new maplibregl.LngLatBounds(
[22, 33], [22, 33],
);
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);
jest.spyOn(global.Date, "now").mockReturnValue(now + 1);
act(() => {
// click on the second beacon in the list
component.find(BeaconListItem).at(1).simulate('click');
component.find(BeaconListItem).at(1).simulate("click");
});
// centered on clicked beacon

View file

@ -14,21 +14,21 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import React from 'react';
import { fireEvent, render } from '@testing-library/react';
import { act } from 'react-dom/test-utils';
import React from "react";
import { fireEvent, render } from "@testing-library/react";
import { act } from "react-dom/test-utils";
import DialogSidebar from '../../../../src/components/views/beacon/DialogSidebar';
import MatrixClientContext from '../../../../src/contexts/MatrixClientContext';
import DialogSidebar from "../../../../src/components/views/beacon/DialogSidebar";
import MatrixClientContext from "../../../../src/contexts/MatrixClientContext";
import {
getMockClientWithEventEmitter,
makeBeaconEvent,
makeBeaconInfoEvent,
makeRoomWithBeacons,
mockClientMethodsUser,
} from '../../../test-utils';
} from "../../../test-utils";
describe('<DialogSidebar />', () => {
describe("<DialogSidebar />", () => {
const defaultProps = {
beacons: [],
requestClose: jest.fn(),
@ -37,66 +37,66 @@ describe('<DialogSidebar />', () => {
const now = 1647270879403;
const roomId = '!room:server.org';
const aliceId = '@alice:server.org';
const roomId = "!room:server.org";
const aliceId = "@alice:server.org";
const client = getMockClientWithEventEmitter({
...mockClientMethodsUser(aliceId),
getRoom: jest.fn(),
});
const beaconEvent = makeBeaconInfoEvent(aliceId,
roomId,
{ isLive: true, timestamp: now },
'$alice-room1-1',
);
const location1 = makeBeaconEvent(
aliceId, { beaconInfoId: beaconEvent.getId(), geoUri: 'geo:51,41', timestamp: now },
);
const beaconEvent = makeBeaconInfoEvent(aliceId, roomId, { isLive: true, timestamp: now }, "$alice-room1-1");
const location1 = makeBeaconEvent(aliceId, {
beaconInfoId: beaconEvent.getId(),
geoUri: "geo:51,41",
timestamp: now,
});
const getComponent = (props = {}) => (
<MatrixClientContext.Provider value={client}>
<DialogSidebar {...defaultProps} {...props} />);
</MatrixClientContext.Provider>);
<DialogSidebar {...defaultProps} {...props} />
);
</MatrixClientContext.Provider>
);
beforeEach(() => {
// mock now so time based text in snapshots is stable
jest.spyOn(Date, 'now').mockReturnValue(now);
jest.spyOn(Date, "now").mockReturnValue(now);
});
afterAll(() => {
jest.spyOn(Date, 'now').mockRestore();
jest.spyOn(Date, "now").mockRestore();
});
it('renders sidebar correctly without beacons', () => {
it("renders sidebar correctly without beacons", () => {
const { container } = render(getComponent());
expect(container).toMatchSnapshot();
});
it('renders sidebar correctly with beacons', () => {
it("renders sidebar correctly with beacons", () => {
const [beacon] = makeRoomWithBeacons(roomId, client, [beaconEvent], [location1]);
const { container } = render(getComponent({ beacons: [beacon] }));
expect(container).toMatchSnapshot();
});
it('calls on beacon click', () => {
it("calls on beacon click", () => {
const onBeaconClick = jest.fn();
const [beacon] = makeRoomWithBeacons(roomId, client, [beaconEvent], [location1]);
const { container } = render(getComponent({ beacons: [beacon], onBeaconClick }));
act(() => {
const [listItem] = container.getElementsByClassName('mx_BeaconListItem');
const [listItem] = container.getElementsByClassName("mx_BeaconListItem");
fireEvent.click(listItem);
});
expect(onBeaconClick).toHaveBeenCalled();
});
it('closes on close button click', () => {
it("closes on close button click", () => {
const requestClose = jest.fn();
const { getByTestId } = render(getComponent({ requestClose }));
act(() => {
fireEvent.click(getByTestId('dialog-sidebar-close'));
fireEvent.click(getByTestId("dialog-sidebar-close"));
});
expect(requestClose).toHaveBeenCalled();
});

View file

@ -14,19 +14,19 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import React from 'react';
import { mocked } from 'jest-mock';
import React from "react";
import { mocked } from "jest-mock";
import { fireEvent, render } from "@testing-library/react";
import { act } from 'react-dom/test-utils';
import { Beacon, BeaconIdentifier } from 'matrix-js-sdk/src/matrix';
import { act } from "react-dom/test-utils";
import { Beacon, BeaconIdentifier } from "matrix-js-sdk/src/matrix";
import LeftPanelLiveShareWarning from '../../../../src/components/views/beacon/LeftPanelLiveShareWarning';
import { OwnBeaconStore, OwnBeaconStoreEvent } from '../../../../src/stores/OwnBeaconStore';
import { flushPromises, makeBeaconInfoEvent } from '../../../test-utils';
import dispatcher from '../../../../src/dispatcher/dispatcher';
import { Action } from '../../../../src/dispatcher/actions';
import LeftPanelLiveShareWarning from "../../../../src/components/views/beacon/LeftPanelLiveShareWarning";
import { OwnBeaconStore, OwnBeaconStoreEvent } from "../../../../src/stores/OwnBeaconStore";
import { flushPromises, makeBeaconInfoEvent } from "../../../test-utils";
import dispatcher from "../../../../src/dispatcher/dispatcher";
import { Action } from "../../../../src/dispatcher/actions";
jest.mock('../../../../src/stores/OwnBeaconStore', () => {
jest.mock("../../../../src/stores/OwnBeaconStore", () => {
// eslint-disable-next-line @typescript-eslint/no-var-requires
const EventEmitter = require("events");
class MockOwnBeaconStore extends EventEmitter {
@ -38,57 +38,52 @@ jest.mock('../../../../src/stores/OwnBeaconStore', () => {
}
return {
// @ts-ignore
...jest.requireActual('../../../../src/stores/OwnBeaconStore'),
...jest.requireActual("../../../../src/stores/OwnBeaconStore"),
OwnBeaconStore: {
instance: new MockOwnBeaconStore() as unknown as OwnBeaconStore,
},
};
},
);
});
describe('<LeftPanelLiveShareWarning />', () => {
describe("<LeftPanelLiveShareWarning />", () => {
const getComponent = (props = {}) => render(<LeftPanelLiveShareWarning {...props} />);
const roomId1 = '!room1:server';
const roomId2 = '!room2:server';
const aliceId = '@alive:server';
const roomId1 = "!room1:server";
const roomId2 = "!room2:server";
const aliceId = "@alive:server";
const now = 1647270879403;
const HOUR_MS = 3600000;
beforeEach(() => {
jest.spyOn(global.Date, 'now').mockReturnValue(now);
jest.spyOn(dispatcher, 'dispatch').mockClear().mockImplementation(() => { });
jest.spyOn(global.Date, "now").mockReturnValue(now);
jest.spyOn(dispatcher, "dispatch")
.mockClear()
.mockImplementation(() => {});
OwnBeaconStore.instance.beaconUpdateErrors.clear();
});
afterAll(() => {
jest.spyOn(global.Date, 'now').mockRestore();
jest.spyOn(global.Date, "now").mockRestore();
jest.restoreAllMocks();
});
// 12h old, 12h left
const beacon1 = new Beacon(makeBeaconInfoEvent(aliceId,
roomId1,
{ timeout: HOUR_MS * 24, timestamp: now - 12 * HOUR_MS },
'$1',
));
const beacon1 = new Beacon(
makeBeaconInfoEvent(aliceId, roomId1, { timeout: HOUR_MS * 24, timestamp: now - 12 * HOUR_MS }, "$1"),
);
// 10h left
const beacon2 = new Beacon(makeBeaconInfoEvent(aliceId,
roomId2,
{ timeout: HOUR_MS * 10, timestamp: now },
'$2',
));
const beacon2 = new Beacon(makeBeaconInfoEvent(aliceId, roomId2, { timeout: HOUR_MS * 10, timestamp: now }, "$2"));
it('renders nothing when user has no live beacons', () => {
it("renders nothing when user has no live beacons", () => {
const { container } = getComponent();
expect(container.innerHTML).toBeFalsy();
});
describe('when user has live location monitor', () => {
describe("when user has live location monitor", () => {
beforeAll(() => {
mocked(OwnBeaconStore.instance).getBeaconById.mockImplementation(beaconId => {
mocked(OwnBeaconStore.instance).getBeaconById.mockImplementation((beaconId) => {
if (beaconId === beacon1.identifier) {
return beacon1;
}
@ -104,17 +99,17 @@ describe('<LeftPanelLiveShareWarning />', () => {
});
afterAll(() => {
jest.spyOn(document, 'addEventListener').mockRestore();
jest.spyOn(document, "addEventListener").mockRestore();
});
it('renders correctly when not minimized', () => {
it("renders correctly when not minimized", () => {
const { asFragment } = getComponent();
expect(asFragment()).toMatchSnapshot();
});
it('goes to room of latest beacon when clicked', () => {
it("goes to room of latest beacon when clicked", () => {
const { container } = getComponent();
const dispatchSpy = jest.spyOn(dispatcher, 'dispatch');
const dispatchSpy = jest.spyOn(dispatcher, "dispatch");
fireEvent.click(container.querySelector("[role=button]"));
@ -129,25 +124,25 @@ describe('<LeftPanelLiveShareWarning />', () => {
});
});
it('renders correctly when minimized', () => {
it("renders correctly when minimized", () => {
const { asFragment } = getComponent({ isMinimized: true });
expect(asFragment()).toMatchSnapshot();
});
it('renders location publish error', () => {
mocked(OwnBeaconStore.instance).getLiveBeaconIdsWithLocationPublishError.mockReturnValue(
[beacon1.identifier],
);
it("renders location publish error", () => {
mocked(OwnBeaconStore.instance).getLiveBeaconIdsWithLocationPublishError.mockReturnValue([
beacon1.identifier,
]);
const { asFragment } = getComponent();
expect(asFragment()).toMatchSnapshot();
});
it('goes to room of latest beacon with location publish error when clicked', () => {
mocked(OwnBeaconStore.instance).getLiveBeaconIdsWithLocationPublishError.mockReturnValue(
[beacon1.identifier],
);
it("goes to room of latest beacon with location publish error when clicked", () => {
mocked(OwnBeaconStore.instance).getLiveBeaconIdsWithLocationPublishError.mockReturnValue([
beacon1.identifier,
]);
const { container } = getComponent();
const dispatchSpy = jest.spyOn(dispatcher, 'dispatch');
const dispatchSpy = jest.spyOn(dispatcher, "dispatch");
fireEvent.click(container.querySelector("[role=button]"));
@ -162,30 +157,30 @@ describe('<LeftPanelLiveShareWarning />', () => {
});
});
it('goes back to default style when wire errors are cleared', () => {
mocked(OwnBeaconStore.instance).getLiveBeaconIdsWithLocationPublishError.mockReturnValue(
[beacon1.identifier],
);
it("goes back to default style when wire errors are cleared", () => {
mocked(OwnBeaconStore.instance).getLiveBeaconIdsWithLocationPublishError.mockReturnValue([
beacon1.identifier,
]);
const { container, rerender } = getComponent();
// error mode
expect(container.querySelector('.mx_LeftPanelLiveShareWarning').textContent).toEqual(
'An error occurred whilst sharing your live location',
expect(container.querySelector(".mx_LeftPanelLiveShareWarning").textContent).toEqual(
"An error occurred whilst sharing your live location",
);
act(() => {
mocked(OwnBeaconStore.instance).getLiveBeaconIdsWithLocationPublishError.mockReturnValue([]);
OwnBeaconStore.instance.emit(OwnBeaconStoreEvent.LocationPublishError, 'abc');
OwnBeaconStore.instance.emit(OwnBeaconStoreEvent.LocationPublishError, "abc");
});
rerender(<LeftPanelLiveShareWarning />);
// default mode
expect(container.querySelector('.mx_LeftPanelLiveShareWarning').textContent).toEqual(
'You are sharing your live location',
expect(container.querySelector(".mx_LeftPanelLiveShareWarning").textContent).toEqual(
"You are sharing your live location",
);
});
it('removes itself when user stops having live beacons', async () => {
it("removes itself when user stops having live beacons", async () => {
const { container, rerender } = getComponent({ isMinimized: true });
// started out rendered
expect(container.innerHTML).toBeTruthy();
@ -202,14 +197,14 @@ describe('<LeftPanelLiveShareWarning />', () => {
expect(container.innerHTML).toBeFalsy();
});
it('refreshes beacon liveness monitors when pagevisibilty changes to visible', () => {
it("refreshes beacon liveness monitors when pagevisibilty changes to visible", () => {
OwnBeaconStore.instance.beacons.set(beacon1.identifier, beacon1);
OwnBeaconStore.instance.beacons.set(beacon2.identifier, beacon2);
const beacon1MonitorSpy = jest.spyOn(beacon1, 'monitorLiveness');
const beacon2MonitorSpy = jest.spyOn(beacon1, 'monitorLiveness');
const beacon1MonitorSpy = jest.spyOn(beacon1, "monitorLiveness");
const beacon2MonitorSpy = jest.spyOn(beacon1, "monitorLiveness");
jest.spyOn(document, 'addEventListener').mockImplementation(
(_e, listener) => (listener as EventListener)(new Event('')),
jest.spyOn(document, "addEventListener").mockImplementation((_e, listener) =>
(listener as EventListener)(new Event("")),
);
expect(beacon1MonitorSpy).not.toHaveBeenCalled();
@ -220,42 +215,42 @@ describe('<LeftPanelLiveShareWarning />', () => {
expect(beacon2MonitorSpy).toHaveBeenCalled();
});
describe('stopping errors', () => {
it('renders stopping error', () => {
OwnBeaconStore.instance.beaconUpdateErrors.set(beacon2.identifier, new Error('error'));
describe("stopping errors", () => {
it("renders stopping error", () => {
OwnBeaconStore.instance.beaconUpdateErrors.set(beacon2.identifier, new Error("error"));
const { container } = getComponent();
expect(container.textContent).toEqual('An error occurred while stopping your live location');
expect(container.textContent).toEqual("An error occurred while stopping your live location");
});
it('starts rendering stopping error on beaconUpdateError emit', () => {
it("starts rendering stopping error on beaconUpdateError emit", () => {
const { container } = getComponent();
// no error
expect(container.textContent).toEqual('You are sharing your live location');
expect(container.textContent).toEqual("You are sharing your live location");
act(() => {
OwnBeaconStore.instance.beaconUpdateErrors.set(beacon2.identifier, new Error('error'));
OwnBeaconStore.instance.beaconUpdateErrors.set(beacon2.identifier, new Error("error"));
OwnBeaconStore.instance.emit(OwnBeaconStoreEvent.BeaconUpdateError, beacon2.identifier, true);
});
expect(container.textContent).toEqual('An error occurred while stopping your live location');
expect(container.textContent).toEqual("An error occurred while stopping your live location");
});
it('renders stopping error when beacons have stopping and location errors', () => {
mocked(OwnBeaconStore.instance).getLiveBeaconIdsWithLocationPublishError.mockReturnValue(
[beacon1.identifier],
);
OwnBeaconStore.instance.beaconUpdateErrors.set(beacon2.identifier, new Error('error'));
it("renders stopping error when beacons have stopping and location errors", () => {
mocked(OwnBeaconStore.instance).getLiveBeaconIdsWithLocationPublishError.mockReturnValue([
beacon1.identifier,
]);
OwnBeaconStore.instance.beaconUpdateErrors.set(beacon2.identifier, new Error("error"));
const { container } = getComponent();
expect(container.textContent).toEqual('An error occurred while stopping your live location');
expect(container.textContent).toEqual("An error occurred while stopping your live location");
});
it('goes to room of latest beacon with stopping error when clicked', () => {
mocked(OwnBeaconStore.instance).getLiveBeaconIdsWithLocationPublishError.mockReturnValue(
[beacon1.identifier],
);
OwnBeaconStore.instance.beaconUpdateErrors.set(beacon2.identifier, new Error('error'));
it("goes to room of latest beacon with stopping error when clicked", () => {
mocked(OwnBeaconStore.instance).getLiveBeaconIdsWithLocationPublishError.mockReturnValue([
beacon1.identifier,
]);
OwnBeaconStore.instance.beaconUpdateErrors.set(beacon2.identifier, new Error("error"));
const { container } = getComponent();
const dispatchSpy = jest.spyOn(dispatcher, 'dispatch');
const dispatchSpy = jest.spyOn(dispatcher, "dispatch");
fireEvent.click(container.querySelector("[role=button]"));

View file

@ -14,62 +14,61 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import React from 'react';
import React from "react";
// eslint-disable-next-line deprecate/import
import { mount } from 'enzyme';
import { act } from 'react-dom/test-utils';
import { mocked } from 'jest-mock';
import { Beacon } from 'matrix-js-sdk/src/matrix';
import { mount } from "enzyme";
import { act } from "react-dom/test-utils";
import { mocked } from "jest-mock";
import { Beacon } from "matrix-js-sdk/src/matrix";
import OwnBeaconStatus from '../../../../src/components/views/beacon/OwnBeaconStatus';
import { BeaconDisplayStatus } from '../../../../src/components/views/beacon/displayStatus';
import { useOwnLiveBeacons } from '../../../../src/utils/beacon';
import { findByTestId, makeBeaconInfoEvent } from '../../../test-utils';
import OwnBeaconStatus from "../../../../src/components/views/beacon/OwnBeaconStatus";
import { BeaconDisplayStatus } from "../../../../src/components/views/beacon/displayStatus";
import { useOwnLiveBeacons } from "../../../../src/utils/beacon";
import { findByTestId, makeBeaconInfoEvent } from "../../../test-utils";
jest.mock('../../../../src/utils/beacon/useOwnLiveBeacons', () => ({
jest.mock("../../../../src/utils/beacon/useOwnLiveBeacons", () => ({
useOwnLiveBeacons: jest.fn(),
}));
describe('<OwnBeaconStatus />', () => {
describe("<OwnBeaconStatus />", () => {
const defaultProps = {
displayStatus: BeaconDisplayStatus.Loading,
};
const userId = '@user:server';
const roomId = '!room:server';
const userId = "@user:server";
const roomId = "!room:server";
let defaultBeacon;
const getComponent = (props = {}) =>
mount(<OwnBeaconStatus {...defaultProps} {...props} />);
const getComponent = (props = {}) => mount(<OwnBeaconStatus {...defaultProps} {...props} />);
beforeEach(() => {
jest.spyOn(global.Date, 'now').mockReturnValue(123456789);
jest.spyOn(global.Date, "now").mockReturnValue(123456789);
mocked(useOwnLiveBeacons).mockClear().mockReturnValue({});
defaultBeacon = new Beacon(makeBeaconInfoEvent(userId, roomId));
});
it('renders without a beacon instance', () => {
it("renders without a beacon instance", () => {
const component = getComponent();
expect(component).toMatchSnapshot();
});
it('renders loading state correctly', () => {
it("renders loading state correctly", () => {
const component = getComponent();
expect(component.find('BeaconStatus').props()).toBeTruthy();
expect(component.find("BeaconStatus").props()).toBeTruthy();
});
describe('Active state', () => {
it('renders stop button', () => {
describe("Active state", () => {
it("renders stop button", () => {
const displayStatus = BeaconDisplayStatus.Active;
mocked(useOwnLiveBeacons).mockReturnValue({
onStopSharing: jest.fn(),
});
const component = getComponent({ displayStatus, beacon: defaultBeacon });
expect(component.text()).toContain('Live location enabled');
expect(component.text()).toContain("Live location enabled");
expect(findByTestId(component, 'beacon-status-stop-beacon').length).toBeTruthy();
expect(findByTestId(component, "beacon-status-stop-beacon").length).toBeTruthy();
});
it('stops sharing on stop button click', () => {
it("stops sharing on stop button click", () => {
const displayStatus = BeaconDisplayStatus.Active;
const onStopSharing = jest.fn();
mocked(useOwnLiveBeacons).mockReturnValue({
@ -78,37 +77,37 @@ describe('<OwnBeaconStatus />', () => {
const component = getComponent({ displayStatus, beacon: defaultBeacon });
act(() => {
findByTestId(component, 'beacon-status-stop-beacon').at(0).simulate('click');
findByTestId(component, "beacon-status-stop-beacon").at(0).simulate("click");
});
expect(onStopSharing).toHaveBeenCalled();
});
});
describe('errors', () => {
it('renders in error mode when displayStatus is error', () => {
describe("errors", () => {
it("renders in error mode when displayStatus is error", () => {
const displayStatus = BeaconDisplayStatus.Error;
const component = getComponent({ displayStatus });
expect(component.text()).toEqual('Live location error');
expect(component.text()).toEqual("Live location error");
// no actions for plain error
expect(component.find('AccessibleButton').length).toBeFalsy();
expect(component.find("AccessibleButton").length).toBeFalsy();
});
describe('with location publish error', () => {
it('renders in error mode', () => {
describe("with location publish error", () => {
it("renders in error mode", () => {
const displayStatus = BeaconDisplayStatus.Active;
mocked(useOwnLiveBeacons).mockReturnValue({
hasLocationPublishError: true,
onResetLocationPublishError: jest.fn(),
});
const component = getComponent({ displayStatus, beacon: defaultBeacon });
expect(component.text()).toContain('Live location error');
expect(component.text()).toContain("Live location error");
// retry button
expect(findByTestId(component, 'beacon-status-reset-wire-error').length).toBeTruthy();
expect(findByTestId(component, "beacon-status-reset-wire-error").length).toBeTruthy();
});
it('retry button resets location publish error', () => {
it("retry button resets location publish error", () => {
const displayStatus = BeaconDisplayStatus.Active;
const onResetLocationPublishError = jest.fn();
mocked(useOwnLiveBeacons).mockReturnValue({
@ -117,15 +116,15 @@ describe('<OwnBeaconStatus />', () => {
});
const component = getComponent({ displayStatus, beacon: defaultBeacon });
act(() => {
findByTestId(component, 'beacon-status-reset-wire-error').at(0).simulate('click');
findByTestId(component, "beacon-status-reset-wire-error").at(0).simulate("click");
});
expect(onResetLocationPublishError).toHaveBeenCalled();
});
});
describe('with stopping error', () => {
it('renders in error mode', () => {
describe("with stopping error", () => {
it("renders in error mode", () => {
const displayStatus = BeaconDisplayStatus.Active;
mocked(useOwnLiveBeacons).mockReturnValue({
hasLocationPublishError: false,
@ -133,12 +132,12 @@ describe('<OwnBeaconStatus />', () => {
onStopSharing: jest.fn(),
});
const component = getComponent({ displayStatus, beacon: defaultBeacon });
expect(component.text()).toContain('Live location error');
expect(component.text()).toContain("Live location error");
// retry button
expect(findByTestId(component, 'beacon-status-stop-beacon-retry').length).toBeTruthy();
expect(findByTestId(component, "beacon-status-stop-beacon-retry").length).toBeTruthy();
});
it('retry button retries stop sharing', () => {
it("retry button retries stop sharing", () => {
const displayStatus = BeaconDisplayStatus.Active;
const onStopSharing = jest.fn();
mocked(useOwnLiveBeacons).mockReturnValue({
@ -147,7 +146,7 @@ describe('<OwnBeaconStatus />', () => {
});
const component = getComponent({ displayStatus, beacon: defaultBeacon });
act(() => {
findByTestId(component, 'beacon-status-stop-beacon-retry').at(0).simulate('click');
findByTestId(component, "beacon-status-stop-beacon-retry").at(0).simulate("click");
});
expect(onStopSharing).toHaveBeenCalled();
@ -155,7 +154,7 @@ describe('<OwnBeaconStatus />', () => {
});
});
it('renders loading state correctly', () => {
it("renders loading state correctly", () => {
const component = getComponent();
expect(component).toBeTruthy();
});

View file

@ -16,28 +16,12 @@ limitations under the License.
import React from "react";
import { act } from "react-dom/test-utils";
import {
Room,
PendingEventOrdering,
MatrixClient,
RoomMember,
RoomStateEvent,
} from "matrix-js-sdk/src/matrix";
import { Room, PendingEventOrdering, MatrixClient, RoomMember, RoomStateEvent } from "matrix-js-sdk/src/matrix";
import { ClientWidgetApi, Widget } from "matrix-widget-api";
import {
cleanup,
render,
screen,
} from "@testing-library/react";
import { cleanup, render, screen } from "@testing-library/react";
import { mocked, Mocked } from "jest-mock";
import {
mkRoomMember,
MockedCall,
setupAsyncStoreWithClient,
stubClient,
useMockedCalls,
} from "../../../test-utils";
import { mkRoomMember, MockedCall, setupAsyncStoreWithClient, stubClient, useMockedCalls } from "../../../test-utils";
import RoomCallBanner from "../../../../src/components/views/beacon/RoomCallBanner";
import { CallStore } from "../../../../src/stores/CallStore";
import { WidgetMessagingStore } from "../../../../src/stores/widgets/WidgetMessagingStore";
@ -64,13 +48,9 @@ describe("<RoomCallBanner />", () => {
pendingEventOrdering: PendingEventOrdering.Detached,
});
alice = mkRoomMember(room.roomId, "@alice:example.org");
jest.spyOn(room, "getMember").mockImplementation((userId) =>
userId === alice.userId ? alice : null,
);
jest.spyOn(room, "getMember").mockImplementation((userId) => (userId === alice.userId ? alice : null));
client.getRoom.mockImplementation((roomId) =>
roomId === room.roomId ? room : null,
);
client.getRoom.mockImplementation((roomId) => (roomId === room.roomId ? room : null));
client.getRooms.mockReturnValue([room]);
client.reEmitter.reEmit(room, [RoomStateEvent.Events]);
@ -100,7 +80,9 @@ describe("<RoomCallBanner />", () => {
beforeEach(() => {
MockedCall.create(room, "1");
const maybeCall = CallStore.instance.getCall(room.roomId);
if (!(maybeCall instanceof MockedCall)) {throw new Error("Failed to create call");}
if (!(maybeCall instanceof MockedCall)) {
throw new Error("Failed to create call");
}
call = maybeCall;
widget = new Widget(call.widget);

View file

@ -14,15 +14,15 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import React from 'react';
import { act } from 'react-dom/test-utils';
import React from "react";
import { act } from "react-dom/test-utils";
// eslint-disable-next-line deprecate/import
import { mount } from 'enzyme';
import { Room, Beacon, BeaconEvent, getBeaconInfoIdentifier } from 'matrix-js-sdk/src/matrix';
import { logger } from 'matrix-js-sdk/src/logger';
import { mount } from "enzyme";
import { Room, Beacon, BeaconEvent, getBeaconInfoIdentifier } from "matrix-js-sdk/src/matrix";
import { logger } from "matrix-js-sdk/src/logger";
import RoomLiveShareWarning from '../../../../src/components/views/beacon/RoomLiveShareWarning';
import { OwnBeaconStore, OwnBeaconStoreEvent } from '../../../../src/stores/OwnBeaconStore';
import RoomLiveShareWarning from "../../../../src/components/views/beacon/RoomLiveShareWarning";
import { OwnBeaconStore, OwnBeaconStoreEvent } from "../../../../src/stores/OwnBeaconStore";
import {
advanceDateAndTime,
findByTestId,
@ -32,20 +32,20 @@ import {
mockGeolocation,
resetAsyncStoreWithClient,
setupAsyncStoreWithClient,
} from '../../../test-utils';
import defaultDispatcher from '../../../../src/dispatcher/dispatcher';
import { Action } from '../../../../src/dispatcher/actions';
} from "../../../test-utils";
import defaultDispatcher from "../../../../src/dispatcher/dispatcher";
import { Action } from "../../../../src/dispatcher/actions";
jest.useFakeTimers();
describe('<RoomLiveShareWarning />', () => {
const aliceId = '@alice:server.org';
const room1Id = '$room1:server.org';
const room2Id = '$room2:server.org';
const room3Id = '$room3:server.org';
describe("<RoomLiveShareWarning />", () => {
const aliceId = "@alice:server.org";
const room1Id = "$room1:server.org";
const room2Id = "$room2:server.org";
const room3Id = "$room3:server.org";
const mockClient = getMockClientWithEventEmitter({
getVisibleRooms: jest.fn().mockReturnValue([]),
getUserId: jest.fn().mockReturnValue(aliceId),
unstable_setLiveBeacon: jest.fn().mockResolvedValue({ event_id: '1' }),
unstable_setLiveBeacon: jest.fn().mockResolvedValue({ event_id: "1" }),
sendEvent: jest.fn(),
});
@ -54,14 +54,19 @@ describe('<RoomLiveShareWarning />', () => {
const MINUTE_MS = 60000;
const HOUR_MS = 3600000;
// mock the date so events are stable for snapshots etc
jest.spyOn(global.Date, 'now').mockReturnValue(now);
const room1Beacon1 = makeBeaconInfoEvent(aliceId, room1Id, {
isLive: true,
timeout: HOUR_MS,
}, '$0');
const room2Beacon1 = makeBeaconInfoEvent(aliceId, room2Id, { isLive: true, timeout: HOUR_MS }, '$1');
const room2Beacon2 = makeBeaconInfoEvent(aliceId, room2Id, { isLive: true, timeout: HOUR_MS * 12 }, '$2');
const room3Beacon1 = makeBeaconInfoEvent(aliceId, room3Id, { isLive: true, timeout: HOUR_MS }, '$3');
jest.spyOn(global.Date, "now").mockReturnValue(now);
const room1Beacon1 = makeBeaconInfoEvent(
aliceId,
room1Id,
{
isLive: true,
timeout: HOUR_MS,
},
"$0",
);
const room2Beacon1 = makeBeaconInfoEvent(aliceId, room2Id, { isLive: true, timeout: HOUR_MS }, "$1");
const room2Beacon2 = makeBeaconInfoEvent(aliceId, room2Id, { isLive: true, timeout: HOUR_MS * 12 }, "$2");
const room3Beacon1 = makeBeaconInfoEvent(aliceId, room3Id, { isLive: true, timeout: HOUR_MS }, "$3");
// make fresh rooms every time
// as we update room state
@ -96,42 +101,39 @@ describe('<RoomLiveShareWarning />', () => {
return component;
};
const localStorageSpy = jest.spyOn(localStorage.__proto__, 'getItem').mockReturnValue(undefined);
const localStorageSpy = jest.spyOn(localStorage.__proto__, "getItem").mockReturnValue(undefined);
beforeEach(() => {
mockGeolocation();
jest.spyOn(global.Date, 'now').mockReturnValue(now);
mockClient.unstable_setLiveBeacon.mockReset().mockResolvedValue({ event_id: '1' });
jest.spyOn(global.Date, "now").mockReturnValue(now);
mockClient.unstable_setLiveBeacon.mockReset().mockResolvedValue({ event_id: "1" });
// assume all beacons were created on this device
localStorageSpy.mockReturnValue(JSON.stringify([
room1Beacon1.getId(),
room2Beacon1.getId(),
room2Beacon2.getId(),
room3Beacon1.getId(),
]));
localStorageSpy.mockReturnValue(
JSON.stringify([room1Beacon1.getId(), room2Beacon1.getId(), room2Beacon2.getId(), room3Beacon1.getId()]),
);
});
afterEach(async () => {
jest.spyOn(OwnBeaconStore.instance, 'beaconHasLocationPublishError').mockRestore();
jest.spyOn(OwnBeaconStore.instance, "beaconHasLocationPublishError").mockRestore();
await resetAsyncStoreWithClient(OwnBeaconStore.instance);
});
afterAll(() => {
jest.spyOn(global.Date, 'now').mockRestore();
jest.spyOn(global.Date, "now").mockRestore();
localStorageSpy.mockRestore();
jest.spyOn(defaultDispatcher, 'dispatch').mockRestore();
jest.spyOn(defaultDispatcher, "dispatch").mockRestore();
});
const getExpiryText = wrapper => findByTestId(wrapper, 'room-live-share-expiry').text();
const getExpiryText = (wrapper) => findByTestId(wrapper, "room-live-share-expiry").text();
it('renders nothing when user has no live beacons at all', async () => {
it("renders nothing when user has no live beacons at all", async () => {
await makeOwnBeaconStore();
const component = getComponent();
expect(component.html()).toBe(null);
});
it('renders nothing when user has no live beacons in room', async () => {
it("renders nothing when user has no live beacons in room", async () => {
await act(async () => {
await makeRoomsWithStateEvents([room2Beacon1]);
await makeOwnBeaconStore();
@ -140,8 +142,8 @@ describe('<RoomLiveShareWarning />', () => {
expect(component.html()).toBe(null);
});
it('does not render when geolocation is not working', async () => {
jest.spyOn(logger, 'error').mockImplementation(() => { });
it("does not render when geolocation is not working", async () => {
jest.spyOn(logger, "error").mockImplementation(() => {});
// @ts-ignore
navigator.geolocation = undefined;
await act(async () => {
@ -155,7 +157,7 @@ describe('<RoomLiveShareWarning />', () => {
expect(component.html()).toBeNull();
});
describe('when user has live beacons and geolocation is available', () => {
describe("when user has live beacons and geolocation is available", () => {
beforeEach(async () => {
await act(async () => {
await makeRoomsWithStateEvents([room1Beacon1, room2Beacon1, room2Beacon2]);
@ -163,23 +165,23 @@ describe('<RoomLiveShareWarning />', () => {
});
});
it('renders correctly with one live beacon in room', () => {
it("renders correctly with one live beacon in room", () => {
const component = getComponent({ roomId: room1Id });
// beacons have generated ids that break snapshots
// assert on html
expect(component.html()).toMatchSnapshot();
});
it('renders correctly with two live beacons in room', () => {
it("renders correctly with two live beacons in room", () => {
const component = getComponent({ roomId: room2Id });
// beacons have generated ids that break snapshots
// assert on html
expect(component.html()).toMatchSnapshot();
// later expiry displayed
expect(getExpiryText(component)).toEqual('12h left');
expect(getExpiryText(component)).toEqual("12h left");
});
it('removes itself when user stops having live beacons', async () => {
it("removes itself when user stops having live beacons", async () => {
const component = getComponent({ roomId: room1Id });
// started out rendered
expect(component.html()).toBeTruthy();
@ -196,7 +198,7 @@ describe('<RoomLiveShareWarning />', () => {
expect(component.html()).toBe(null);
});
it('removes itself when user stops monitoring live position', async () => {
it("removes itself when user stops monitoring live position", async () => {
const component = getComponent({ roomId: room1Id });
// started out rendered
expect(component.html()).toBeTruthy();
@ -212,7 +214,7 @@ describe('<RoomLiveShareWarning />', () => {
expect(component.html()).toBe(null);
});
it('renders when user adds a live beacon', async () => {
it("renders when user adds a live beacon", async () => {
const component = getComponent({ roomId: room3Id });
// started out not rendered
expect(component.html()).toBeFalsy();
@ -225,40 +227,45 @@ describe('<RoomLiveShareWarning />', () => {
expect(component.html()).toBeTruthy();
});
it('updates beacon time left periodically', () => {
it("updates beacon time left periodically", () => {
const component = getComponent({ roomId: room1Id });
expect(getExpiryText(component)).toEqual('1h left');
expect(getExpiryText(component)).toEqual("1h left");
act(() => {
advanceDateAndTime(MINUTE_MS * 25);
});
expect(getExpiryText(component)).toEqual('35m left');
expect(getExpiryText(component)).toEqual("35m left");
});
it('updates beacon time left when beacon updates', () => {
it("updates beacon time left when beacon updates", () => {
const component = getComponent({ roomId: room1Id });
expect(getExpiryText(component)).toEqual('1h left');
expect(getExpiryText(component)).toEqual("1h left");
expect(getExpiryText(component)).toEqual('1h left');
expect(getExpiryText(component)).toEqual("1h left");
act(() => {
const beacon = OwnBeaconStore.instance.getBeaconById(getBeaconInfoIdentifier(room1Beacon1));
const room1Beacon1Update = makeBeaconInfoEvent(aliceId, room1Id, {
isLive: true,
timeout: 3 * HOUR_MS,
}, '$0');
const room1Beacon1Update = makeBeaconInfoEvent(
aliceId,
room1Id,
{
isLive: true,
timeout: 3 * HOUR_MS,
},
"$0",
);
beacon.update(room1Beacon1Update);
});
// update to expiry of new beacon
expect(getExpiryText(component)).toEqual('3h left');
expect(getExpiryText(component)).toEqual("3h left");
});
it('clears expiry time interval on unmount', () => {
const clearIntervalSpy = jest.spyOn(global, 'clearInterval');
it("clears expiry time interval on unmount", () => {
const clearIntervalSpy = jest.spyOn(global, "clearInterval");
const component = getComponent({ roomId: room1Id });
expect(getExpiryText(component)).toEqual('1h left');
expect(getExpiryText(component)).toEqual("1h left");
act(() => {
component.unmount();
@ -267,12 +274,12 @@ describe('<RoomLiveShareWarning />', () => {
expect(clearIntervalSpy).toHaveBeenCalled();
});
it('navigates to beacon tile on click', () => {
const dispatcherSpy = jest.spyOn(defaultDispatcher, 'dispatch');
it("navigates to beacon tile on click", () => {
const dispatcherSpy = jest.spyOn(defaultDispatcher, "dispatch");
const component = getComponent({ roomId: room1Id });
act(() => {
component.simulate('click');
component.simulate("click");
});
expect(dispatcherSpy).toHaveBeenCalledWith({
@ -285,30 +292,30 @@ describe('<RoomLiveShareWarning />', () => {
});
});
describe('stopping beacons', () => {
it('stops beacon on stop sharing click', () => {
describe("stopping beacons", () => {
it("stops beacon on stop sharing click", () => {
const component = getComponent({ roomId: room2Id });
act(() => {
findByTestId(component, 'room-live-share-primary-button').at(0).simulate('click');
findByTestId(component, "room-live-share-primary-button").at(0).simulate("click");
component.setProps({});
});
expect(mockClient.unstable_setLiveBeacon).toHaveBeenCalled();
expect(component.find('Spinner').length).toBeTruthy();
expect(findByTestId(component, 'room-live-share-primary-button').at(0).props().disabled).toBeTruthy();
expect(component.find("Spinner").length).toBeTruthy();
expect(findByTestId(component, "room-live-share-primary-button").at(0).props().disabled).toBeTruthy();
});
it('displays error when stop sharing fails', async () => {
it("displays error when stop sharing fails", async () => {
const component = getComponent({ roomId: room1Id });
// fail first time
mockClient.unstable_setLiveBeacon
.mockRejectedValueOnce(new Error('oups'))
.mockResolvedValue(({ event_id: '1' }));
.mockRejectedValueOnce(new Error("oups"))
.mockResolvedValue({ event_id: "1" });
await act(async () => {
findByTestId(component, 'room-live-share-primary-button').at(0).simulate('click');
findByTestId(component, "room-live-share-primary-button").at(0).simulate("click");
await flushPromisesWithFakeTimers();
});
component.setProps({});
@ -316,20 +323,20 @@ describe('<RoomLiveShareWarning />', () => {
expect(component.html()).toMatchSnapshot();
act(() => {
findByTestId(component, 'room-live-share-primary-button').at(0).simulate('click');
findByTestId(component, "room-live-share-primary-button").at(0).simulate("click");
component.setProps({});
});
expect(mockClient.unstable_setLiveBeacon).toHaveBeenCalledTimes(2);
});
it('displays again with correct state after stopping a beacon', () => {
it("displays again with correct state after stopping a beacon", () => {
// make sure the loading state is reset correctly after removing a beacon
const component = getComponent({ roomId: room1Id });
// stop the beacon
act(() => {
findByTestId(component, 'room-live-share-primary-button').at(0).simulate('click');
findByTestId(component, "room-live-share-primary-button").at(0).simulate("click");
});
// time travel until room1Beacon1 is expired
act(() => {
@ -345,28 +352,30 @@ describe('<RoomLiveShareWarning />', () => {
});
// button not disabled and expiry time shown
expect(findByTestId(component, 'room-live-share-primary-button').at(0).props().disabled).toBeFalsy();
expect(findByTestId(component, 'room-live-share-expiry').text()).toEqual('1h left');
expect(findByTestId(component, "room-live-share-primary-button").at(0).props().disabled).toBeFalsy();
expect(findByTestId(component, "room-live-share-expiry").text()).toEqual("1h left");
});
});
describe('with location publish errors', () => {
it('displays location publish error when mounted with location publish errors', async () => {
const locationPublishErrorSpy = jest.spyOn(OwnBeaconStore.instance, 'beaconHasLocationPublishError')
describe("with location publish errors", () => {
it("displays location publish error when mounted with location publish errors", async () => {
const locationPublishErrorSpy = jest
.spyOn(OwnBeaconStore.instance, "beaconHasLocationPublishError")
.mockReturnValue(true);
const component = getComponent({ roomId: room2Id });
expect(component).toMatchSnapshot();
expect(locationPublishErrorSpy).toHaveBeenCalledWith(
getBeaconInfoIdentifier(room2Beacon1), 0, [getBeaconInfoIdentifier(room2Beacon1)],
);
expect(locationPublishErrorSpy).toHaveBeenCalledWith(getBeaconInfoIdentifier(room2Beacon1), 0, [
getBeaconInfoIdentifier(room2Beacon1),
]);
});
it(
'displays location publish error when locationPublishError event is emitted' +
' and beacons have errors',
"displays location publish error when locationPublishError event is emitted" +
" and beacons have errors",
async () => {
const locationPublishErrorSpy = jest.spyOn(OwnBeaconStore.instance, 'beaconHasLocationPublishError')
const locationPublishErrorSpy = jest
.spyOn(OwnBeaconStore.instance, "beaconHasLocationPublishError")
.mockReturnValue(false);
const component = getComponent({ roomId: room2Id });
@ -374,20 +383,23 @@ describe('<RoomLiveShareWarning />', () => {
act(() => {
locationPublishErrorSpy.mockReturnValue(true);
OwnBeaconStore.instance.emit(
OwnBeaconStoreEvent.LocationPublishError, getBeaconInfoIdentifier(room2Beacon1),
OwnBeaconStoreEvent.LocationPublishError,
getBeaconInfoIdentifier(room2Beacon1),
);
});
component.setProps({});
// renders wire error ui
expect(component.find('.mx_RoomLiveShareWarning_label').text()).toEqual(
'An error occurred whilst sharing your live location, please try again',
expect(component.find(".mx_RoomLiveShareWarning_label").text()).toEqual(
"An error occurred whilst sharing your live location, please try again",
);
expect(findByTestId(component, 'room-live-share-wire-error-close-button').length).toBeTruthy();
});
expect(findByTestId(component, "room-live-share-wire-error-close-button").length).toBeTruthy();
},
);
it('stops displaying wire error when errors are cleared', async () => {
const locationPublishErrorSpy = jest.spyOn(OwnBeaconStore.instance, 'beaconHasLocationPublishError')
it("stops displaying wire error when errors are cleared", async () => {
const locationPublishErrorSpy = jest
.spyOn(OwnBeaconStore.instance, "beaconHasLocationPublishError")
.mockReturnValue(true);
const component = getComponent({ roomId: room2Id });
@ -395,39 +407,40 @@ describe('<RoomLiveShareWarning />', () => {
act(() => {
locationPublishErrorSpy.mockReturnValue(false);
OwnBeaconStore.instance.emit(
OwnBeaconStoreEvent.LocationPublishError, getBeaconInfoIdentifier(room2Beacon1),
OwnBeaconStoreEvent.LocationPublishError,
getBeaconInfoIdentifier(room2Beacon1),
);
});
component.setProps({});
// renders error-free ui
expect(component.find('.mx_RoomLiveShareWarning_label').text()).toEqual(
'You are sharing your live location',
expect(component.find(".mx_RoomLiveShareWarning_label").text()).toEqual(
"You are sharing your live location",
);
expect(findByTestId(component, 'room-live-share-wire-error-close-button').length).toBeFalsy();
expect(findByTestId(component, "room-live-share-wire-error-close-button").length).toBeFalsy();
});
it('clicking retry button resets location publish errors', async () => {
jest.spyOn(OwnBeaconStore.instance, 'beaconHasLocationPublishError').mockReturnValue(true);
const resetErrorSpy = jest.spyOn(OwnBeaconStore.instance, 'resetLocationPublishError');
it("clicking retry button resets location publish errors", async () => {
jest.spyOn(OwnBeaconStore.instance, "beaconHasLocationPublishError").mockReturnValue(true);
const resetErrorSpy = jest.spyOn(OwnBeaconStore.instance, "resetLocationPublishError");
const component = getComponent({ roomId: room2Id });
act(() => {
findByTestId(component, 'room-live-share-primary-button').at(0).simulate('click');
findByTestId(component, "room-live-share-primary-button").at(0).simulate("click");
});
expect(resetErrorSpy).toHaveBeenCalledWith(getBeaconInfoIdentifier(room2Beacon1));
});
it('clicking close button stops beacons', async () => {
jest.spyOn(OwnBeaconStore.instance, 'beaconHasLocationPublishError').mockReturnValue(true);
const stopBeaconSpy = jest.spyOn(OwnBeaconStore.instance, 'stopBeacon');
it("clicking close button stops beacons", async () => {
jest.spyOn(OwnBeaconStore.instance, "beaconHasLocationPublishError").mockReturnValue(true);
const stopBeaconSpy = jest.spyOn(OwnBeaconStore.instance, "stopBeacon");
const component = getComponent({ roomId: room2Id });
act(() => {
findByTestId(component, 'room-live-share-wire-error-close-button').at(0).simulate('click');
findByTestId(component, "room-live-share-wire-error-close-button").at(0).simulate("click");
});
expect(stopBeaconSpy).toHaveBeenCalledWith(getBeaconInfoIdentifier(room2Beacon1));

View file

@ -14,21 +14,21 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import React from 'react';
import React from "react";
import { fireEvent, render } from "@testing-library/react";
import ShareLatestLocation from '../../../../src/components/views/beacon/ShareLatestLocation';
import { copyPlaintext } from '../../../../src/utils/strings';
import { flushPromises } from '../../../test-utils';
import ShareLatestLocation from "../../../../src/components/views/beacon/ShareLatestLocation";
import { copyPlaintext } from "../../../../src/utils/strings";
import { flushPromises } from "../../../test-utils";
jest.mock('../../../../src/utils/strings', () => ({
jest.mock("../../../../src/utils/strings", () => ({
copyPlaintext: jest.fn().mockResolvedValue(undefined),
}));
describe('<ShareLatestLocation />', () => {
describe("<ShareLatestLocation />", () => {
const defaultProps = {
latestLocationState: {
uri: 'geo:51,42;u=35',
uri: "geo:51,42;u=35",
timestamp: 123,
},
};
@ -38,18 +38,18 @@ describe('<ShareLatestLocation />', () => {
jest.clearAllMocks();
});
it('renders null when no location', () => {
it("renders null when no location", () => {
const { container } = getComponent({ latestLocationState: undefined });
expect(container.innerHTML).toBeFalsy();
});
it('renders share buttons when there is a location', async () => {
it("renders share buttons when there is a location", async () => {
const { container, asFragment } = getComponent();
expect(asFragment()).toMatchSnapshot();
fireEvent.click(container.querySelector('.mx_CopyableText_copyButton'));
fireEvent.click(container.querySelector(".mx_CopyableText_copyButton"));
await flushPromises();
expect(copyPlaintext).toHaveBeenCalledWith('51,42');
expect(copyPlaintext).toHaveBeenCalledWith("51,42");
});
});

View file

@ -14,16 +14,16 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import React from 'react';
import React from "react";
import { render } from "@testing-library/react";
import StyledLiveBeaconIcon from '../../../../src/components/views/beacon/StyledLiveBeaconIcon';
import StyledLiveBeaconIcon from "../../../../src/components/views/beacon/StyledLiveBeaconIcon";
describe('<StyledLiveBeaconIcon />', () => {
describe("<StyledLiveBeaconIcon />", () => {
const defaultProps = {};
const getComponent = (props = {}) => render(<StyledLiveBeaconIcon {...defaultProps} {...props} />);
it('renders', () => {
it("renders", () => {
const { asFragment } = getComponent();
expect(asFragment()).toMatchSnapshot();
});