Skip to content
This repository has been archived by the owner on Sep 11, 2024. It is now read-only.

Commit

Permalink
Convert some tests from Enzyme to RTL (#9483)
Browse files Browse the repository at this point in the history
  • Loading branch information
t3chguy authored Oct 24, 2022
1 parent 9eb4f8d commit 913af09
Show file tree
Hide file tree
Showing 14 changed files with 311 additions and 448 deletions.
2 changes: 1 addition & 1 deletion src/components/views/beacon/ShareLatestLocation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ const ShareLatestLocation: React.FC<Props> = ({ latestLocationState }) => {
return <>
<TooltipTarget label={_t('Open in OpenStreetMap')}>
<a
data-test-id='open-location-in-osm'
data-testid='open-location-in-osm'
href={mapLink}
target='_blank'
rel='noreferrer noopener'
Expand Down
67 changes: 30 additions & 37 deletions test/components/views/beacon/BeaconListItem-test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,7 @@ limitations under the License.
*/

import React from 'react';
// eslint-disable-next-line deprecate/import
import { mount } from 'enzyme';
import { fireEvent, render } from "@testing-library/react";
import {
Beacon,
RoomMember,
Expand All @@ -28,7 +27,6 @@ import { act } from 'react-dom/test-utils';
import BeaconListItem from '../../../../src/components/views/beacon/BeaconListItem';
import MatrixClientContext from '../../../../src/contexts/MatrixClientContext';
import {
findByTestId,
getMockClientWithEventEmitter,
makeBeaconEvent,
makeBeaconInfoEvent,
Expand Down Expand Up @@ -76,11 +74,9 @@ describe('<BeaconListItem />', () => {
beacon: new Beacon(aliceBeaconEvent),
};

const getComponent = (props = {}) =>
mount(<BeaconListItem {...defaultProps} {...props} />, {
wrappingComponent: MatrixClientContext.Provider,
wrappingComponentProps: { value: mockClient },
});
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);
Expand All @@ -104,95 +100,92 @@ describe('<BeaconListItem />', () => {
{ isLive: false },
);
const [beacon] = setupRoomWithBeacons([notLiveBeacon]);
const component = getComponent({ beacon });
expect(component.html()).toBeNull();
const { container } = getComponent({ beacon });
expect(container.innerHTML).toBeFalsy();
});

it('renders null when beacon has no location', () => {
const [beacon] = setupRoomWithBeacons([aliceBeaconEvent]);
const component = getComponent({ beacon });
expect(component.html()).toBeNull();
const { container } = getComponent({ beacon });
expect(container.innerHTML).toBeFalsy();
});

describe('when a beacon is live and has locations', () => {
it('renders beacon info', () => {
const [beacon] = setupRoomWithBeacons([alicePinBeaconEvent], [aliceLocation1]);
const component = getComponent({ beacon });
expect(component.html()).toMatchSnapshot();
const { asFragment } = getComponent({ beacon });
expect(asFragment()).toMatchSnapshot();
});

describe('non-self beacons', () => {
it('uses beacon description as beacon name', () => {
const [beacon] = setupRoomWithBeacons([alicePinBeaconEvent], [aliceLocation1]);
const component = getComponent({ beacon });
expect(component.find('BeaconStatus').props().label).toEqual("Alice's car");
const { container } = getComponent({ beacon });
expect(container.querySelector('.mx_BeaconStatus_label')).toHaveTextContent("Alice's car");
});

it('uses beacon owner mxid as beacon name for a beacon without description', () => {
const [beacon] = setupRoomWithBeacons([pinBeaconWithoutDescription], [aliceLocation1]);
const component = getComponent({ beacon });
expect(component.find('BeaconStatus').props().label).toEqual(aliceId);
const { container } = getComponent({ beacon });
expect(container.querySelector('.mx_BeaconStatus_label')).toHaveTextContent(aliceId);
});

it('renders location icon', () => {
const [beacon] = setupRoomWithBeacons([alicePinBeaconEvent], [aliceLocation1]);
const component = getComponent({ beacon });
expect(component.find('StyledLiveBeaconIcon').length).toBeTruthy();
const { container } = getComponent({ beacon });
expect(container.querySelector('.mx_StyledLiveBeaconIcon')).toBeTruthy();
});
});

describe('self locations', () => {
it('renders beacon owner avatar', () => {
const [beacon] = setupRoomWithBeacons([aliceBeaconEvent], [aliceLocation1]);
const component = getComponent({ beacon });
expect(component.find('MemberAvatar').length).toBeTruthy();
const { container } = getComponent({ beacon });
expect(container.querySelector('.mx_BaseAvatar')).toBeTruthy();
});

it('uses beacon owner name as beacon name', () => {
const [beacon] = setupRoomWithBeacons([aliceBeaconEvent], [aliceLocation1]);
const component = getComponent({ beacon });
expect(component.find('BeaconStatus').props().label).toEqual('Alice');
const { container } = getComponent({ beacon });
expect(container.querySelector('.mx_BeaconStatus_label')).toHaveTextContent("Alice");
});
});

describe('on location updates', () => {
it('updates last updated time on location updated', () => {
const [beacon] = setupRoomWithBeacons([aliceBeaconEvent], [aliceLocation2]);
const component = getComponent({ beacon });
const { container } = getComponent({ beacon });

expect(component.find('.mx_BeaconListItem_lastUpdated').text()).toEqual('Updated 9 minutes ago');
expect(container.querySelector('.mx_BeaconListItem_lastUpdated'))
.toHaveTextContent('Updated 9 minutes ago');

// update to a newer location
act(() => {
beacon.addLocations([aliceLocation1]);
component.setProps({});
});

expect(component.find('.mx_BeaconListItem_lastUpdated').text()).toEqual('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', () => {
const [beacon] = setupRoomWithBeacons([alicePinBeaconEvent], [aliceLocation1]);
const onClick = jest.fn();
const component = getComponent({ beacon, onClick });
const { getByTestId } = getComponent({ beacon, onClick });

act(() => {
findByTestId(component, 'open-location-in-osm').at(0).simulate('click');
});
fireEvent.click(getByTestId('open-location-in-osm'));
expect(onClick).not.toHaveBeenCalled();
});

it('calls onClick handler when clicking outside of share buttons', () => {
const [beacon] = setupRoomWithBeacons([alicePinBeaconEvent], [aliceLocation1]);
const onClick = jest.fn();
const component = getComponent({ beacon, onClick });
const { container } = getComponent({ beacon, onClick });

act(() => {
// click the beacon name
component.find('.mx_BeaconStatus_description').simulate('click');
});
// click the beacon name
fireEvent.click(container.querySelector(".mx_BeaconStatus_description"));
expect(onClick).toHaveBeenCalled();
});
});
Expand Down
71 changes: 31 additions & 40 deletions test/components/views/beacon/LeftPanelLiveShareWarning-test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,7 @@ limitations under the License.

import React from 'react';
import { mocked } from 'jest-mock';
// eslint-disable-next-line deprecate/import
import { mount } from 'enzyme';
import { fireEvent, render } from "@testing-library/react";
import { act } from 'react-dom/test-utils';
import { Beacon, BeaconIdentifier } from 'matrix-js-sdk/src/matrix';

Expand Down Expand Up @@ -48,9 +47,7 @@ jest.mock('../../../../src/stores/OwnBeaconStore', () => {
);

describe('<LeftPanelLiveShareWarning />', () => {
const defaultProps = {};
const getComponent = (props = {}) =>
mount(<LeftPanelLiveShareWarning {...defaultProps} {...props} />);
const getComponent = (props = {}) => render(<LeftPanelLiveShareWarning {...props} />);

const roomId1 = '!room1:server';
const roomId2 = '!room2:server';
Expand Down Expand Up @@ -85,8 +82,8 @@ describe('<LeftPanelLiveShareWarning />', () => {
));

it('renders nothing when user has no live beacons', () => {
const component = getComponent();
expect(component.html()).toBe(null);
const { container } = getComponent();
expect(container.innerHTML).toBeFalsy();
});

describe('when user has live location monitor', () => {
Expand All @@ -110,17 +107,15 @@ describe('<LeftPanelLiveShareWarning />', () => {
});

it('renders correctly when not minimized', () => {
const component = getComponent();
expect(component).toMatchSnapshot();
const { asFragment } = getComponent();
expect(asFragment()).toMatchSnapshot();
});

it('goes to room of latest beacon when clicked', () => {
const component = getComponent();
const { container } = getComponent();
const dispatchSpy = jest.spyOn(dispatcher, 'dispatch');

act(() => {
component.simulate('click');
});
fireEvent.click(container.querySelector("[role=button]"));

expect(dispatchSpy).toHaveBeenCalledWith({
action: Action.ViewRoom,
Expand All @@ -134,28 +129,26 @@ describe('<LeftPanelLiveShareWarning />', () => {
});

it('renders correctly when minimized', () => {
const component = getComponent({ isMinimized: true });
expect(component).toMatchSnapshot();
const { asFragment } = getComponent({ isMinimized: true });
expect(asFragment()).toMatchSnapshot();
});

it('renders location publish error', () => {
mocked(OwnBeaconStore.instance).getLiveBeaconIdsWithLocationPublishError.mockReturnValue(
[beacon1.identifier],
);
const component = getComponent();
expect(component).toMatchSnapshot();
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],
);
const component = getComponent();
const { container } = getComponent();
const dispatchSpy = jest.spyOn(dispatcher, 'dispatch');

act(() => {
component.simulate('click');
});
fireEvent.click(container.querySelector("[role=button]"));

expect(dispatchSpy).toHaveBeenCalledWith({
action: Action.ViewRoom,
Expand All @@ -172,9 +165,9 @@ describe('<LeftPanelLiveShareWarning />', () => {
mocked(OwnBeaconStore.instance).getLiveBeaconIdsWithLocationPublishError.mockReturnValue(
[beacon1.identifier],
);
const component = getComponent();
const { container, rerender } = getComponent();
// error mode
expect(component.find('.mx_LeftPanelLiveShareWarning').at(0).text()).toEqual(
expect(container.querySelector('.mx_LeftPanelLiveShareWarning').textContent).toEqual(
'An error occurred whilst sharing your live location',
);

Expand All @@ -183,28 +176,28 @@ describe('<LeftPanelLiveShareWarning />', () => {
OwnBeaconStore.instance.emit(OwnBeaconStoreEvent.LocationPublishError, 'abc');
});

component.setProps({});
rerender(<LeftPanelLiveShareWarning />);

// default mode
expect(component.find('.mx_LeftPanelLiveShareWarning').at(0).text()).toEqual(
expect(container.querySelector('.mx_LeftPanelLiveShareWarning').textContent).toEqual(
'You are sharing your live location',
);
});

it('removes itself when user stops having live beacons', async () => {
const component = getComponent({ isMinimized: true });
const { container, rerender } = getComponent({ isMinimized: true });
// started out rendered
expect(component.html()).toBeTruthy();
expect(container.innerHTML).toBeTruthy();

act(() => {
mocked(OwnBeaconStore.instance).isMonitoringLiveLocation = false;
OwnBeaconStore.instance.emit(OwnBeaconStoreEvent.MonitoringLivePosition);
});

await flushPromises();
component.setProps({});
rerender(<LeftPanelLiveShareWarning />);

expect(component.html()).toBe(null);
expect(container.innerHTML).toBeFalsy();
});

it('refreshes beacon liveness monitors when pagevisibilty changes to visible', () => {
Expand All @@ -228,43 +221,41 @@ describe('<LeftPanelLiveShareWarning />', () => {
describe('stopping errors', () => {
it('renders stopping error', () => {
OwnBeaconStore.instance.beaconUpdateErrors.set(beacon2.identifier, new Error('error'));
const component = getComponent();
expect(component.text()).toEqual('An error occurred while stopping your live location');
const { container } = getComponent();
expect(container.textContent).toEqual('An error occurred while stopping your live location');
});

it('starts rendering stopping error on beaconUpdateError emit', () => {
const component = getComponent();
const { container } = getComponent();
// no error
expect(component.text()).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.emit(OwnBeaconStoreEvent.BeaconUpdateError, beacon2.identifier, true);
});

expect(component.text()).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'));
const component = getComponent();
expect(component.text()).toEqual('An error occurred while stopping your live location');
const { container } = getComponent();
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'));
const component = getComponent();
const { container } = getComponent();
const dispatchSpy = jest.spyOn(dispatcher, 'dispatch');

act(() => {
component.simulate('click');
});
fireEvent.click(container.querySelector("[role=button]"));

expect(dispatchSpy).toHaveBeenCalledWith({
action: Action.ViewRoom,
Expand Down
21 changes: 8 additions & 13 deletions test/components/views/beacon/ShareLatestLocation-test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,7 @@ limitations under the License.
*/

import React from 'react';
// eslint-disable-next-line deprecate/import
import { mount } from 'enzyme';
import { act } from 'react-dom/test-utils';
import { fireEvent, render } from "@testing-library/react";

import ShareLatestLocation from '../../../../src/components/views/beacon/ShareLatestLocation';
import { copyPlaintext } from '../../../../src/utils/strings';
Expand All @@ -34,26 +32,23 @@ describe('<ShareLatestLocation />', () => {
timestamp: 123,
},
};
const getComponent = (props = {}) =>
mount(<ShareLatestLocation {...defaultProps} {...props} />);
const getComponent = (props = {}) => render(<ShareLatestLocation {...defaultProps} {...props} />);

beforeEach(() => {
jest.clearAllMocks();
});

it('renders null when no location', () => {
const component = getComponent({ latestLocationState: undefined });
expect(component.html()).toBeNull();
const { container } = getComponent({ latestLocationState: undefined });
expect(container.innerHTML).toBeFalsy();
});

it('renders share buttons when there is a location', async () => {
const component = getComponent();
expect(component).toMatchSnapshot();
const { container, asFragment } = getComponent();
expect(asFragment()).toMatchSnapshot();

await act(async () => {
component.find('.mx_CopyableText_copyButton').at(0).simulate('click');
await flushPromises();
});
fireEvent.click(container.querySelector('.mx_CopyableText_copyButton'));
await flushPromises();

expect(copyPlaintext).toHaveBeenCalledWith('51,42');
});
Expand Down
Loading

0 comments on commit 913af09

Please sign in to comment.