Merge remote-tracking branch 'origin/develop' into feat/add-message-edition-wysiwyg-composer
This commit is contained in:
commit
de86221c72
55 changed files with 1551 additions and 668 deletions
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -104,71 +100,72 @@ 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');
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -176,23 +173,19 @@ describe('<BeaconListItem />', () => {
|
|||
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();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -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';
|
||||
|
||||
|
@ -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';
|
||||
|
@ -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', () => {
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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',
|
||||
);
|
||||
|
||||
|
@ -183,18 +176,18 @@ 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;
|
||||
|
@ -202,9 +195,9 @@ describe('<LeftPanelLiveShareWarning />', () => {
|
|||
});
|
||||
|
||||
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', () => {
|
||||
|
@ -228,21 +221,21 @@ 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', () => {
|
||||
|
@ -250,8 +243,8 @@ describe('<LeftPanelLiveShareWarning />', () => {
|
|||
[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', () => {
|
||||
|
@ -259,12 +252,10 @@ describe('<LeftPanelLiveShareWarning />', () => {
|
|||
[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,
|
||||
|
|
|
@ -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';
|
||||
|
@ -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');
|
||||
});
|
||||
|
|
|
@ -15,18 +15,16 @@ limitations under the License.
|
|||
*/
|
||||
|
||||
import React from 'react';
|
||||
// eslint-disable-next-line deprecate/import
|
||||
import { mount } from 'enzyme';
|
||||
import { render } from "@testing-library/react";
|
||||
|
||||
import StyledLiveBeaconIcon from '../../../../src/components/views/beacon/StyledLiveBeaconIcon';
|
||||
|
||||
describe('<StyledLiveBeaconIcon />', () => {
|
||||
const defaultProps = {};
|
||||
const getComponent = (props = {}) =>
|
||||
mount(<StyledLiveBeaconIcon {...defaultProps} {...props} />);
|
||||
const getComponent = (props = {}) => render(<StyledLiveBeaconIcon {...defaultProps} {...props} />);
|
||||
|
||||
it('renders', () => {
|
||||
const component = getComponent();
|
||||
expect(component).toBeTruthy();
|
||||
const { asFragment } = getComponent();
|
||||
expect(asFragment()).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,3 +1,68 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`<BeaconListItem /> when a beacon is live and has locations renders beacon info 1`] = `"<li class=\\"mx_BeaconListItem\\"><div class=\\"mx_StyledLiveBeaconIcon mx_BeaconListItem_avatarIcon\\"></div><div class=\\"mx_BeaconListItem_info\\"><div class=\\"mx_BeaconStatus mx_BeaconStatus_Active mx_BeaconListItem_status\\"><div class=\\"mx_BeaconStatus_description\\"><span class=\\"mx_BeaconStatus_label\\">Alice's car</span><span class=\\"mx_BeaconStatus_expiryTime\\">Live until 16:04</span></div><div class=\\"mx_BeaconListItem_interactions\\"><div tabindex=\\"0\\"><a data-test-id=\\"open-location-in-osm\\" href=\\"https://www.openstreetmap.org/?mlat=51&mlon=41#map=16/51/41\\" target=\\"_blank\\" rel=\\"noreferrer noopener\\"><div class=\\"mx_ShareLatestLocation_icon\\"></div></a></div><div class=\\"mx_CopyableText mx_ShareLatestLocation_copy\\"><div aria-label=\\"Copy\\" role=\\"button\\" tabindex=\\"0\\" class=\\"mx_AccessibleButton mx_CopyableText_copyButton\\"></div></div></div></div><span class=\\"mx_BeaconListItem_lastUpdated\\">Updated a few seconds ago</span></div></li>"`;
|
||||
exports[`<BeaconListItem /> when a beacon is live and has locations renders beacon info 1`] = `
|
||||
<DocumentFragment>
|
||||
<li
|
||||
class="mx_BeaconListItem"
|
||||
>
|
||||
<div
|
||||
class="mx_StyledLiveBeaconIcon mx_BeaconListItem_avatarIcon"
|
||||
/>
|
||||
<div
|
||||
class="mx_BeaconListItem_info"
|
||||
>
|
||||
<div
|
||||
class="mx_BeaconStatus mx_BeaconStatus_Active mx_BeaconListItem_status"
|
||||
>
|
||||
<div
|
||||
class="mx_BeaconStatus_description"
|
||||
>
|
||||
<span
|
||||
class="mx_BeaconStatus_label"
|
||||
>
|
||||
Alice's car
|
||||
</span>
|
||||
<span
|
||||
class="mx_BeaconStatus_expiryTime"
|
||||
>
|
||||
Live until 16:04
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="mx_BeaconListItem_interactions"
|
||||
>
|
||||
<div
|
||||
tabindex="0"
|
||||
>
|
||||
<a
|
||||
data-testid="open-location-in-osm"
|
||||
href="https://www.openstreetmap.org/?mlat=51&mlon=41#map=16/51/41"
|
||||
rel="noreferrer noopener"
|
||||
target="_blank"
|
||||
>
|
||||
<div
|
||||
class="mx_ShareLatestLocation_icon"
|
||||
/>
|
||||
</a>
|
||||
</div>
|
||||
<div
|
||||
class="mx_CopyableText mx_ShareLatestLocation_copy"
|
||||
>
|
||||
<div
|
||||
aria-label="Copy"
|
||||
class="mx_AccessibleButton mx_CopyableText_copyButton"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<span
|
||||
class="mx_BeaconListItem_lastUpdated"
|
||||
>
|
||||
Updated a few seconds ago
|
||||
</span>
|
||||
</div>
|
||||
</li>
|
||||
</DocumentFragment>
|
||||
`;
|
||||
|
|
|
@ -75,7 +75,7 @@ exports[`<DialogSidebar /> renders sidebar correctly with beacons 1`] = `
|
|||
tabindex="0"
|
||||
>
|
||||
<a
|
||||
data-test-id="open-location-in-osm"
|
||||
data-testid="open-location-in-osm"
|
||||
href="https://www.openstreetmap.org/?mlat=51&mlon=41#map=16/51/41"
|
||||
rel="noreferrer noopener"
|
||||
target="_blank"
|
||||
|
|
|
@ -1,76 +1,40 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`<LeftPanelLiveShareWarning /> when user has live location monitor renders correctly when minimized 1`] = `
|
||||
<LeftPanelLiveShareWarning
|
||||
isMinimized={true}
|
||||
>
|
||||
<AccessibleButton
|
||||
className="mx_LeftPanelLiveShareWarning mx_LeftPanelLiveShareWarning__minimized"
|
||||
element="div"
|
||||
onClick={[Function]}
|
||||
<DocumentFragment>
|
||||
<div
|
||||
class="mx_AccessibleButton mx_LeftPanelLiveShareWarning mx_LeftPanelLiveShareWarning__minimized"
|
||||
role="button"
|
||||
tabIndex={0}
|
||||
tabindex="0"
|
||||
title="You are sharing your live location"
|
||||
>
|
||||
<div
|
||||
className="mx_AccessibleButton mx_LeftPanelLiveShareWarning mx_LeftPanelLiveShareWarning__minimized"
|
||||
onClick={[Function]}
|
||||
onKeyDown={[Function]}
|
||||
onKeyUp={[Function]}
|
||||
role="button"
|
||||
tabIndex={0}
|
||||
title="You are sharing your live location"
|
||||
>
|
||||
<div
|
||||
height={10}
|
||||
/>
|
||||
</div>
|
||||
</AccessibleButton>
|
||||
</LeftPanelLiveShareWarning>
|
||||
height="10"
|
||||
/>
|
||||
</div>
|
||||
</DocumentFragment>
|
||||
`;
|
||||
|
||||
exports[`<LeftPanelLiveShareWarning /> when user has live location monitor renders correctly when not minimized 1`] = `
|
||||
<LeftPanelLiveShareWarning>
|
||||
<AccessibleButton
|
||||
className="mx_LeftPanelLiveShareWarning"
|
||||
element="div"
|
||||
onClick={[Function]}
|
||||
<DocumentFragment>
|
||||
<div
|
||||
class="mx_AccessibleButton mx_LeftPanelLiveShareWarning"
|
||||
role="button"
|
||||
tabIndex={0}
|
||||
tabindex="0"
|
||||
>
|
||||
<div
|
||||
className="mx_AccessibleButton mx_LeftPanelLiveShareWarning"
|
||||
onClick={[Function]}
|
||||
onKeyDown={[Function]}
|
||||
onKeyUp={[Function]}
|
||||
role="button"
|
||||
tabIndex={0}
|
||||
>
|
||||
You are sharing your live location
|
||||
</div>
|
||||
</AccessibleButton>
|
||||
</LeftPanelLiveShareWarning>
|
||||
You are sharing your live location
|
||||
</div>
|
||||
</DocumentFragment>
|
||||
`;
|
||||
|
||||
exports[`<LeftPanelLiveShareWarning /> when user has live location monitor renders location publish error 1`] = `
|
||||
<LeftPanelLiveShareWarning>
|
||||
<AccessibleButton
|
||||
className="mx_LeftPanelLiveShareWarning mx_LeftPanelLiveShareWarning__error"
|
||||
element="div"
|
||||
onClick={[Function]}
|
||||
<DocumentFragment>
|
||||
<div
|
||||
class="mx_AccessibleButton mx_LeftPanelLiveShareWarning mx_LeftPanelLiveShareWarning__error"
|
||||
role="button"
|
||||
tabIndex={0}
|
||||
tabindex="0"
|
||||
>
|
||||
<div
|
||||
className="mx_AccessibleButton mx_LeftPanelLiveShareWarning mx_LeftPanelLiveShareWarning__error"
|
||||
onClick={[Function]}
|
||||
onKeyDown={[Function]}
|
||||
onKeyUp={[Function]}
|
||||
role="button"
|
||||
tabIndex={0}
|
||||
>
|
||||
An error occurred whilst sharing your live location
|
||||
</div>
|
||||
</AccessibleButton>
|
||||
</LeftPanelLiveShareWarning>
|
||||
An error occurred whilst sharing your live location
|
||||
</div>
|
||||
</DocumentFragment>
|
||||
`;
|
||||
|
|
|
@ -1,79 +1,30 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`<ShareLatestLocation /> renders share buttons when there is a location 1`] = `
|
||||
<ShareLatestLocation
|
||||
latestLocationState={
|
||||
Object {
|
||||
"timestamp": 123,
|
||||
"uri": "geo:51,42;u=35",
|
||||
}
|
||||
}
|
||||
>
|
||||
<TooltipTarget
|
||||
label="Open in OpenStreetMap"
|
||||
<DocumentFragment>
|
||||
<div
|
||||
tabindex="0"
|
||||
>
|
||||
<a
|
||||
data-testid="open-location-in-osm"
|
||||
href="https://www.openstreetmap.org/?mlat=51&mlon=42#map=16/51/42"
|
||||
rel="noreferrer noopener"
|
||||
target="_blank"
|
||||
>
|
||||
<div
|
||||
class="mx_ShareLatestLocation_icon"
|
||||
/>
|
||||
</a>
|
||||
</div>
|
||||
<div
|
||||
class="mx_CopyableText mx_ShareLatestLocation_copy"
|
||||
>
|
||||
<div
|
||||
onBlur={[Function]}
|
||||
onFocus={[Function]}
|
||||
onMouseLeave={[Function]}
|
||||
onMouseMove={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
tabIndex={0}
|
||||
>
|
||||
<a
|
||||
data-test-id="open-location-in-osm"
|
||||
href="https://www.openstreetmap.org/?mlat=51&mlon=42#map=16/51/42"
|
||||
rel="noreferrer noopener"
|
||||
target="_blank"
|
||||
>
|
||||
<div
|
||||
className="mx_ShareLatestLocation_icon"
|
||||
/>
|
||||
</a>
|
||||
</div>
|
||||
</TooltipTarget>
|
||||
<CopyableText
|
||||
border={false}
|
||||
className="mx_ShareLatestLocation_copy"
|
||||
getTextToCopy={[Function]}
|
||||
>
|
||||
<div
|
||||
className="mx_CopyableText mx_ShareLatestLocation_copy"
|
||||
>
|
||||
<AccessibleTooltipButton
|
||||
className="mx_CopyableText_copyButton"
|
||||
onClick={[Function]}
|
||||
onHideTooltip={[Function]}
|
||||
title="Copy"
|
||||
>
|
||||
<AccessibleButton
|
||||
aria-label="Copy"
|
||||
className="mx_CopyableText_copyButton"
|
||||
element="div"
|
||||
onBlur={[Function]}
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
onMouseLeave={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
role="button"
|
||||
tabIndex={0}
|
||||
>
|
||||
<div
|
||||
aria-label="Copy"
|
||||
className="mx_AccessibleButton mx_CopyableText_copyButton"
|
||||
onBlur={[Function]}
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
onKeyDown={[Function]}
|
||||
onKeyUp={[Function]}
|
||||
onMouseLeave={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
role="button"
|
||||
tabIndex={0}
|
||||
/>
|
||||
</AccessibleButton>
|
||||
</AccessibleTooltipButton>
|
||||
</div>
|
||||
</CopyableText>
|
||||
</ShareLatestLocation>
|
||||
aria-label="Copy"
|
||||
class="mx_AccessibleButton mx_CopyableText_copyButton"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
/>
|
||||
</div>
|
||||
</DocumentFragment>
|
||||
`;
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`<StyledLiveBeaconIcon /> renders 1`] = `
|
||||
<DocumentFragment>
|
||||
<div
|
||||
class="mx_StyledLiveBeaconIcon"
|
||||
/>
|
||||
</DocumentFragment>
|
||||
`;
|
|
@ -16,6 +16,7 @@ limitations under the License.
|
|||
|
||||
import React from "react";
|
||||
import { render, screen } from "@testing-library/react";
|
||||
import { RoomType } from "matrix-js-sdk/src/@types/event";
|
||||
|
||||
import InviteDialog from "../../../../src/components/views/dialogs/InviteDialog";
|
||||
import { KIND_INVITE } from "../../../../src/components/views/dialogs/InviteDialogTypes";
|
||||
|
@ -74,6 +75,7 @@ describe("InviteDialog", () => {
|
|||
|
||||
it("should label with space name", () => {
|
||||
mockClient.getRoom(roomId).isSpaceRoom = jest.fn().mockReturnValue(true);
|
||||
mockClient.getRoom(roomId).getType = jest.fn().mockReturnValue(RoomType.Space);
|
||||
mockClient.getRoom(roomId).name = "Space";
|
||||
render((
|
||||
<InviteDialog
|
||||
|
|
|
@ -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 StyledRadioGroup from "../../../../src/components/views/elements/StyledRadioGroup";
|
||||
|
||||
|
@ -44,16 +42,16 @@ describe('<StyledRadioGroup />', () => {
|
|||
definitions: defaultDefinitions,
|
||||
onChange: jest.fn(),
|
||||
};
|
||||
const getComponent = (props = {}) => mount(<StyledRadioGroup {...defaultProps} {...props} />);
|
||||
const getComponent = (props = {}) => render(<StyledRadioGroup {...defaultProps} {...props} />);
|
||||
|
||||
const getInputByValue = (component, value) => component.find(`input[value="${value}"]`);
|
||||
const getCheckedInput = component => component.find('input[checked=true]');
|
||||
const getInputByValue = (component, value) => component.container.querySelector(`input[value="${value}"]`);
|
||||
const getCheckedInput = component => component.container.querySelector('input[checked]');
|
||||
|
||||
it('renders radios correctly when no value is provided', () => {
|
||||
const component = getComponent();
|
||||
|
||||
expect(component).toMatchSnapshot();
|
||||
expect(getCheckedInput(component).length).toBeFalsy();
|
||||
expect(component.asFragment()).toMatchSnapshot();
|
||||
expect(getCheckedInput(component)).toBeFalsy();
|
||||
});
|
||||
|
||||
it('selects correct button when value is provided', () => {
|
||||
|
@ -61,7 +59,7 @@ describe('<StyledRadioGroup />', () => {
|
|||
value: optionC.value,
|
||||
});
|
||||
|
||||
expect(getCheckedInput(component).at(0).props().value).toEqual(optionC.value);
|
||||
expect(getCheckedInput(component).value).toEqual(optionC.value);
|
||||
});
|
||||
|
||||
it('selects correct buttons when definitions have checked prop', () => {
|
||||
|
@ -74,10 +72,10 @@ describe('<StyledRadioGroup />', () => {
|
|||
value: optionC.value, definitions,
|
||||
});
|
||||
|
||||
expect(getInputByValue(component, optionA.value).props().checked).toBeTruthy();
|
||||
expect(getInputByValue(component, optionB.value).props().checked).toBeFalsy();
|
||||
expect(getInputByValue(component, optionA.value)).toBeChecked();
|
||||
expect(getInputByValue(component, optionB.value)).not.toBeChecked();
|
||||
// optionC.checked = false overrides value matching
|
||||
expect(getInputByValue(component, optionC.value).props().checked).toBeFalsy();
|
||||
expect(getInputByValue(component, optionC.value)).not.toBeChecked();
|
||||
});
|
||||
|
||||
it('disables individual buttons based on definition.disabled', () => {
|
||||
|
@ -87,16 +85,16 @@ describe('<StyledRadioGroup />', () => {
|
|||
{ ...optionC, disabled: true },
|
||||
];
|
||||
const component = getComponent({ definitions });
|
||||
expect(getInputByValue(component, optionA.value).props().disabled).toBeFalsy();
|
||||
expect(getInputByValue(component, optionB.value).props().disabled).toBeTruthy();
|
||||
expect(getInputByValue(component, optionC.value).props().disabled).toBeTruthy();
|
||||
expect(getInputByValue(component, optionA.value)).not.toBeDisabled();
|
||||
expect(getInputByValue(component, optionB.value)).toBeDisabled();
|
||||
expect(getInputByValue(component, optionC.value)).toBeDisabled();
|
||||
});
|
||||
|
||||
it('disables all buttons with disabled prop', () => {
|
||||
const component = getComponent({ disabled: true });
|
||||
expect(getInputByValue(component, optionA.value).props().disabled).toBeTruthy();
|
||||
expect(getInputByValue(component, optionB.value).props().disabled).toBeTruthy();
|
||||
expect(getInputByValue(component, optionC.value).props().disabled).toBeTruthy();
|
||||
expect(getInputByValue(component, optionA.value)).toBeDisabled();
|
||||
expect(getInputByValue(component, optionB.value)).toBeDisabled();
|
||||
expect(getInputByValue(component, optionC.value)).toBeDisabled();
|
||||
});
|
||||
|
||||
it('calls onChange on click', () => {
|
||||
|
@ -106,9 +104,7 @@ describe('<StyledRadioGroup />', () => {
|
|||
onChange,
|
||||
});
|
||||
|
||||
act(() => {
|
||||
getInputByValue(component, optionB.value).simulate('change');
|
||||
});
|
||||
fireEvent.click(getInputByValue(component, optionB.value));
|
||||
|
||||
expect(onChange).toHaveBeenCalledWith(optionB.value);
|
||||
});
|
||||
|
|
|
@ -1,152 +1,83 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`<StyledRadioGroup /> renders radios correctly when no value is provided 1`] = `
|
||||
<StyledRadioGroup
|
||||
className="test-class"
|
||||
definitions={
|
||||
Array [
|
||||
Object {
|
||||
"className": "a-class",
|
||||
"description": "anteater description",
|
||||
"label": <span>
|
||||
Anteater label
|
||||
</span>,
|
||||
"value": "Anteater",
|
||||
},
|
||||
Object {
|
||||
"label": <span>
|
||||
Badger label
|
||||
</span>,
|
||||
"value": "Badger",
|
||||
},
|
||||
Object {
|
||||
"description": <span>
|
||||
Canary description
|
||||
</span>,
|
||||
"label": <span>
|
||||
Canary label
|
||||
</span>,
|
||||
"value": "Canary",
|
||||
},
|
||||
]
|
||||
}
|
||||
name="test"
|
||||
onChange={[MockFunction]}
|
||||
>
|
||||
<StyledRadioButton
|
||||
aria-describedby="test-Anteater-description"
|
||||
checked={false}
|
||||
childrenInLabel={true}
|
||||
className="test-class a-class"
|
||||
id="test-Anteater"
|
||||
name="test"
|
||||
onChange={[Function]}
|
||||
value="Anteater"
|
||||
<DocumentFragment>
|
||||
<label
|
||||
class="mx_StyledRadioButton test-class a-class mx_StyledRadioButton_enabled"
|
||||
>
|
||||
<label
|
||||
className="mx_StyledRadioButton test-class a-class mx_StyledRadioButton_enabled"
|
||||
<input
|
||||
aria-describedby="test-Anteater-description"
|
||||
id="test-Anteater"
|
||||
name="test"
|
||||
type="radio"
|
||||
value="Anteater"
|
||||
/>
|
||||
<div>
|
||||
<div />
|
||||
</div>
|
||||
<div
|
||||
class="mx_StyledRadioButton_content"
|
||||
>
|
||||
<input
|
||||
aria-describedby="test-Anteater-description"
|
||||
checked={false}
|
||||
id="test-Anteater"
|
||||
name="test"
|
||||
onChange={[Function]}
|
||||
type="radio"
|
||||
value="Anteater"
|
||||
/>
|
||||
<div>
|
||||
<div />
|
||||
</div>
|
||||
<div
|
||||
className="mx_StyledRadioButton_content"
|
||||
>
|
||||
<span>
|
||||
Anteater label
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
className="mx_StyledRadioButton_spacer"
|
||||
/>
|
||||
</label>
|
||||
</StyledRadioButton>
|
||||
<span>
|
||||
Anteater label
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="mx_StyledRadioButton_spacer"
|
||||
/>
|
||||
</label>
|
||||
<span
|
||||
id="test-Anteater-description"
|
||||
>
|
||||
anteater description
|
||||
</span>
|
||||
<StyledRadioButton
|
||||
checked={false}
|
||||
childrenInLabel={true}
|
||||
className="test-class"
|
||||
id="test-Badger"
|
||||
name="test"
|
||||
onChange={[Function]}
|
||||
value="Badger"
|
||||
<label
|
||||
class="mx_StyledRadioButton test-class mx_StyledRadioButton_enabled"
|
||||
>
|
||||
<label
|
||||
className="mx_StyledRadioButton test-class mx_StyledRadioButton_enabled"
|
||||
<input
|
||||
id="test-Badger"
|
||||
name="test"
|
||||
type="radio"
|
||||
value="Badger"
|
||||
/>
|
||||
<div>
|
||||
<div />
|
||||
</div>
|
||||
<div
|
||||
class="mx_StyledRadioButton_content"
|
||||
>
|
||||
<input
|
||||
checked={false}
|
||||
id="test-Badger"
|
||||
name="test"
|
||||
onChange={[Function]}
|
||||
type="radio"
|
||||
value="Badger"
|
||||
/>
|
||||
<div>
|
||||
<div />
|
||||
</div>
|
||||
<div
|
||||
className="mx_StyledRadioButton_content"
|
||||
>
|
||||
<span>
|
||||
Badger label
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
className="mx_StyledRadioButton_spacer"
|
||||
/>
|
||||
</label>
|
||||
</StyledRadioButton>
|
||||
<StyledRadioButton
|
||||
aria-describedby="test-Canary-description"
|
||||
checked={false}
|
||||
childrenInLabel={true}
|
||||
className="test-class"
|
||||
id="test-Canary"
|
||||
name="test"
|
||||
onChange={[Function]}
|
||||
value="Canary"
|
||||
<span>
|
||||
Badger label
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="mx_StyledRadioButton_spacer"
|
||||
/>
|
||||
</label>
|
||||
<label
|
||||
class="mx_StyledRadioButton test-class mx_StyledRadioButton_enabled"
|
||||
>
|
||||
<label
|
||||
className="mx_StyledRadioButton test-class mx_StyledRadioButton_enabled"
|
||||
<input
|
||||
aria-describedby="test-Canary-description"
|
||||
id="test-Canary"
|
||||
name="test"
|
||||
type="radio"
|
||||
value="Canary"
|
||||
/>
|
||||
<div>
|
||||
<div />
|
||||
</div>
|
||||
<div
|
||||
class="mx_StyledRadioButton_content"
|
||||
>
|
||||
<input
|
||||
aria-describedby="test-Canary-description"
|
||||
checked={false}
|
||||
id="test-Canary"
|
||||
name="test"
|
||||
onChange={[Function]}
|
||||
type="radio"
|
||||
value="Canary"
|
||||
/>
|
||||
<div>
|
||||
<div />
|
||||
</div>
|
||||
<div
|
||||
className="mx_StyledRadioButton_content"
|
||||
>
|
||||
<span>
|
||||
Canary label
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
className="mx_StyledRadioButton_spacer"
|
||||
/>
|
||||
</label>
|
||||
</StyledRadioButton>
|
||||
<span>
|
||||
Canary label
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="mx_StyledRadioButton_spacer"
|
||||
/>
|
||||
</label>
|
||||
<span
|
||||
id="test-Canary-description"
|
||||
>
|
||||
|
@ -154,5 +85,5 @@ exports[`<StyledRadioGroup /> renders radios correctly when no value is provided
|
|||
Canary description
|
||||
</span>
|
||||
</span>
|
||||
</StyledRadioGroup>
|
||||
</DocumentFragment>
|
||||
`;
|
||||
|
|
97
test/components/views/right_panel/RoomHeaderButtons-test.tsx
Normal file
97
test/components/views/right_panel/RoomHeaderButtons-test.tsx
Normal file
|
@ -0,0 +1,97 @@
|
|||
/*
|
||||
Copyright 2022 The Matrix.org Foundation C.I.C.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import { render } from "@testing-library/react";
|
||||
import { MatrixClient, PendingEventOrdering } from "matrix-js-sdk/src/client";
|
||||
import { NotificationCountType, Room } from "matrix-js-sdk/src/models/room";
|
||||
import React from "react";
|
||||
|
||||
import RoomHeaderButtons from "../../../../src/components/views/right_panel/RoomHeaderButtons";
|
||||
import { MatrixClientPeg } from "../../../../src/MatrixClientPeg";
|
||||
import SettingsStore from "../../../../src/settings/SettingsStore";
|
||||
import { stubClient } from "../../../test-utils";
|
||||
|
||||
describe("RoomHeaderButtons-test.tsx", function() {
|
||||
const ROOM_ID = "!roomId:example.org";
|
||||
let room: Room;
|
||||
let client: MatrixClient;
|
||||
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
|
||||
stubClient();
|
||||
client = MatrixClientPeg.get();
|
||||
room = new Room(ROOM_ID, client, client.getUserId(), {
|
||||
pendingEventOrdering: PendingEventOrdering.Detached,
|
||||
});
|
||||
|
||||
jest.spyOn(SettingsStore, "getValue").mockImplementation((name: string) => {
|
||||
if (name === "feature_thread") return true;
|
||||
});
|
||||
});
|
||||
|
||||
function getComponent(room: Room) {
|
||||
return render(<RoomHeaderButtons
|
||||
room={room}
|
||||
excludedRightPanelPhaseButtons={[]}
|
||||
/>);
|
||||
}
|
||||
|
||||
function getThreadButton(container) {
|
||||
return container.querySelector(".mx_RightPanel_threadsButton");
|
||||
}
|
||||
|
||||
function isIndicatorOfType(container, type: "red" | "gray") {
|
||||
return container.querySelector(".mx_RightPanel_threadsButton .mx_Indicator")
|
||||
.className
|
||||
.includes(type);
|
||||
}
|
||||
|
||||
it("shows the thread button", () => {
|
||||
const { container } = getComponent(room);
|
||||
expect(getThreadButton(container)).not.toBeNull();
|
||||
});
|
||||
|
||||
it("hides the thread button", () => {
|
||||
jest.spyOn(SettingsStore, "getValue").mockReset().mockReturnValue(false);
|
||||
const { container } = getComponent(room);
|
||||
expect(getThreadButton(container)).toBeNull();
|
||||
});
|
||||
|
||||
it("room wide notification does not change the thread button", () => {
|
||||
room.setUnreadNotificationCount(NotificationCountType.Highlight, 1);
|
||||
room.setUnreadNotificationCount(NotificationCountType.Total, 1);
|
||||
|
||||
const { container } = getComponent(room);
|
||||
|
||||
expect(container.querySelector(".mx_RightPanel_threadsButton .mx_Indicator")).toBeNull();
|
||||
});
|
||||
|
||||
it("room wide notification does not change the thread button", () => {
|
||||
const { container } = getComponent(room);
|
||||
|
||||
room.setThreadUnreadNotificationCount("$123", NotificationCountType.Total, 1);
|
||||
expect(isIndicatorOfType(container, "gray")).toBe(true);
|
||||
|
||||
room.setThreadUnreadNotificationCount("$123", NotificationCountType.Highlight, 1);
|
||||
expect(isIndicatorOfType(container, "red")).toBe(true);
|
||||
|
||||
room.setThreadUnreadNotificationCount("$123", NotificationCountType.Total, 0);
|
||||
room.setThreadUnreadNotificationCount("$123", NotificationCountType.Highlight, 0);
|
||||
|
||||
expect(container.querySelector(".mx_RightPanel_threadsButton .mx_Indicator")).toBeNull();
|
||||
});
|
||||
});
|
|
@ -140,6 +140,7 @@ describe('<UserInfo />', () => {
|
|||
describe('with a room', () => {
|
||||
const room = {
|
||||
roomId: '!fkfk',
|
||||
getType: jest.fn().mockReturnValue(undefined),
|
||||
isSpaceRoom: jest.fn().mockReturnValue(false),
|
||||
getMember: jest.fn().mockReturnValue(undefined),
|
||||
getMxcAvatarUrl: jest.fn().mockReturnValue('mock-avatar-url'),
|
||||
|
|
112
test/components/views/rooms/EventTile-test.tsx
Normal file
112
test/components/views/rooms/EventTile-test.tsx
Normal file
|
@ -0,0 +1,112 @@
|
|||
/*
|
||||
Copyright 2022 The Matrix.org Foundation C.I.C.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import { act, render } from "@testing-library/react";
|
||||
import { MatrixClient, PendingEventOrdering } from "matrix-js-sdk/src/client";
|
||||
import { MatrixEvent } from "matrix-js-sdk/src/models/event";
|
||||
import { NotificationCountType, Room } from "matrix-js-sdk/src/models/room";
|
||||
import React from "react";
|
||||
|
||||
import EventTile, { EventTileProps } from "../../../../src/components/views/rooms/EventTile";
|
||||
import RoomContext, { TimelineRenderingType } from "../../../../src/contexts/RoomContext";
|
||||
import { MatrixClientPeg } from "../../../../src/MatrixClientPeg";
|
||||
import { getRoomContext, mkMessage, stubClient } from "../../../test-utils";
|
||||
import { mkThread } from "../../../test-utils/threads";
|
||||
|
||||
describe("EventTile", () => {
|
||||
const ROOM_ID = "!roomId:example.org";
|
||||
let mxEvent: MatrixEvent;
|
||||
let room: Room;
|
||||
let client: MatrixClient;
|
||||
// let changeEvent: (event: MatrixEvent) => void;
|
||||
|
||||
function TestEventTile(props: Partial<EventTileProps>) {
|
||||
// const [event] = useState(mxEvent);
|
||||
// Give a way for a test to update the event prop.
|
||||
// changeEvent = setEvent;
|
||||
|
||||
return <EventTile
|
||||
mxEvent={mxEvent}
|
||||
{...props}
|
||||
/>;
|
||||
}
|
||||
|
||||
function getComponent(
|
||||
overrides: Partial<EventTileProps> = {},
|
||||
renderingType: TimelineRenderingType = TimelineRenderingType.Room,
|
||||
) {
|
||||
const context = getRoomContext(room, {
|
||||
timelineRenderingType: renderingType,
|
||||
});
|
||||
return render(
|
||||
<RoomContext.Provider value={context}>
|
||||
<TestEventTile {...overrides} />
|
||||
</RoomContext.Provider>,
|
||||
);
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
|
||||
stubClient();
|
||||
client = MatrixClientPeg.get();
|
||||
|
||||
room = new Room(ROOM_ID, client, client.getUserId(), {
|
||||
pendingEventOrdering: PendingEventOrdering.Detached,
|
||||
});
|
||||
|
||||
jest.spyOn(client, "getRoom").mockReturnValue(room);
|
||||
|
||||
mxEvent = mkMessage({
|
||||
room: room.roomId,
|
||||
user: "@alice:example.org",
|
||||
msg: "Hello world!",
|
||||
event: true,
|
||||
});
|
||||
});
|
||||
|
||||
describe("EventTile renderingType: ThreadsList", () => {
|
||||
beforeEach(() => {
|
||||
const { rootEvent } = mkThread({
|
||||
room,
|
||||
client,
|
||||
authorId: "@alice:example.org",
|
||||
participantUserIds: ["@alice:example.org"],
|
||||
});
|
||||
mxEvent = rootEvent;
|
||||
});
|
||||
|
||||
it("shows an unread notification bage", () => {
|
||||
const { container } = getComponent({}, TimelineRenderingType.ThreadsList);
|
||||
|
||||
expect(container.getElementsByClassName("mx_NotificationBadge")).toHaveLength(0);
|
||||
|
||||
act(() => {
|
||||
room.setThreadUnreadNotificationCount(mxEvent.getId(), NotificationCountType.Total, 3);
|
||||
});
|
||||
|
||||
expect(container.getElementsByClassName("mx_NotificationBadge")).toHaveLength(1);
|
||||
expect(container.getElementsByClassName("mx_NotificationBadge_highlighted")).toHaveLength(0);
|
||||
|
||||
act(() => {
|
||||
room.setThreadUnreadNotificationCount(mxEvent.getId(), NotificationCountType.Highlight, 1);
|
||||
});
|
||||
|
||||
expect(container.getElementsByClassName("mx_NotificationBadge")).toHaveLength(1);
|
||||
expect(container.getElementsByClassName("mx_NotificationBadge_highlighted")).toHaveLength(1);
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
Copyright 2022 The Matrix.org Foundation C.I.C.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import { fireEvent, render } from "@testing-library/react";
|
||||
import React from "react";
|
||||
|
||||
import {
|
||||
StatelessNotificationBadge,
|
||||
} from "../../../../../src/components/views/rooms/NotificationBadge/StatelessNotificationBadge";
|
||||
import { NotificationColor } from "../../../../../src/stores/notifications/NotificationColor";
|
||||
|
||||
describe("NotificationBadge", () => {
|
||||
describe("StatelessNotificationBadge", () => {
|
||||
it("lets you click it", () => {
|
||||
const cb = jest.fn();
|
||||
|
||||
const { container } = render(<StatelessNotificationBadge
|
||||
symbol=""
|
||||
color={NotificationColor.Red}
|
||||
count={5}
|
||||
onClick={cb}
|
||||
onMouseOver={cb}
|
||||
onMouseLeave={cb}
|
||||
/>);
|
||||
|
||||
fireEvent.click(container.firstChild);
|
||||
expect(cb).toHaveBeenCalledTimes(1);
|
||||
|
||||
fireEvent.mouseEnter(container.firstChild);
|
||||
expect(cb).toHaveBeenCalledTimes(2);
|
||||
|
||||
fireEvent.mouseLeave(container.firstChild);
|
||||
expect(cb).toHaveBeenCalledTimes(3);
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,132 @@
|
|||
/*
|
||||
Copyright 2022 The Matrix.org Foundation C.I.C.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import React from "react";
|
||||
import "jest-mock";
|
||||
import { screen, act, render } from "@testing-library/react";
|
||||
import { MatrixClient, PendingEventOrdering } from "matrix-js-sdk/src/client";
|
||||
import { NotificationCountType, Room } from "matrix-js-sdk/src/models/room";
|
||||
import { mocked } from "jest-mock";
|
||||
import { EventStatus } from "matrix-js-sdk/src/models/event-status";
|
||||
|
||||
import {
|
||||
UnreadNotificationBadge,
|
||||
} from "../../../../../src/components/views/rooms/NotificationBadge/UnreadNotificationBadge";
|
||||
import { mkMessage, stubClient } from "../../../../test-utils/test-utils";
|
||||
import { MatrixClientPeg } from "../../../../../src/MatrixClientPeg";
|
||||
import * as RoomNotifs from "../../../../../src/RoomNotifs";
|
||||
|
||||
jest.mock("../../../../../src/RoomNotifs");
|
||||
jest.mock('../../../../../src/RoomNotifs', () => ({
|
||||
...(jest.requireActual('../../../../../src/RoomNotifs') as Object),
|
||||
getRoomNotifsState: jest.fn(),
|
||||
}));
|
||||
|
||||
const ROOM_ID = "!roomId:example.org";
|
||||
let THREAD_ID;
|
||||
|
||||
describe("UnreadNotificationBadge", () => {
|
||||
let mockClient: MatrixClient;
|
||||
let room: Room;
|
||||
|
||||
function getComponent(threadId?: string) {
|
||||
return <UnreadNotificationBadge room={room} threadId={threadId} />;
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
|
||||
stubClient();
|
||||
mockClient = mocked(MatrixClientPeg.get());
|
||||
|
||||
room = new Room(ROOM_ID, mockClient, mockClient.getUserId() ?? "", {
|
||||
pendingEventOrdering: PendingEventOrdering.Detached,
|
||||
});
|
||||
room.setUnreadNotificationCount(NotificationCountType.Total, 1);
|
||||
room.setUnreadNotificationCount(NotificationCountType.Highlight, 0);
|
||||
|
||||
room.setThreadUnreadNotificationCount(THREAD_ID, NotificationCountType.Total, 1);
|
||||
room.setThreadUnreadNotificationCount(THREAD_ID, NotificationCountType.Highlight, 0);
|
||||
|
||||
jest.spyOn(RoomNotifs, "getRoomNotifsState").mockReturnValue(RoomNotifs.RoomNotifState.AllMessages);
|
||||
});
|
||||
|
||||
it("renders unread notification badge", () => {
|
||||
const { container } = render(getComponent());
|
||||
|
||||
expect(container.querySelector(".mx_NotificationBadge_visible")).toBeTruthy();
|
||||
expect(container.querySelector(".mx_NotificationBadge_highlighted")).toBeFalsy();
|
||||
|
||||
act(() => {
|
||||
room.setUnreadNotificationCount(NotificationCountType.Highlight, 1);
|
||||
});
|
||||
|
||||
expect(container.querySelector(".mx_NotificationBadge_highlighted")).toBeTruthy();
|
||||
});
|
||||
|
||||
it("renders unread thread notification badge", () => {
|
||||
const { container } = render(getComponent(THREAD_ID));
|
||||
|
||||
expect(container.querySelector(".mx_NotificationBadge_visible")).toBeTruthy();
|
||||
expect(container.querySelector(".mx_NotificationBadge_highlighted")).toBeFalsy();
|
||||
|
||||
act(() => {
|
||||
room.setThreadUnreadNotificationCount(THREAD_ID, NotificationCountType.Highlight, 1);
|
||||
});
|
||||
|
||||
expect(container.querySelector(".mx_NotificationBadge_highlighted")).toBeTruthy();
|
||||
});
|
||||
|
||||
it("hides unread notification badge", () => {
|
||||
act(() => {
|
||||
room.setThreadUnreadNotificationCount(THREAD_ID, NotificationCountType.Total, 0);
|
||||
room.setThreadUnreadNotificationCount(THREAD_ID, NotificationCountType.Highlight, 0);
|
||||
const { container } = render(getComponent(THREAD_ID));
|
||||
expect(container.querySelector(".mx_NotificationBadge_visible")).toBeFalsy();
|
||||
});
|
||||
});
|
||||
|
||||
it("adds a warning for unsent messages", () => {
|
||||
const evt = mkMessage({
|
||||
room: room.roomId,
|
||||
user: "@alice:example.org",
|
||||
msg: "Hello world!",
|
||||
event: true,
|
||||
});
|
||||
evt.status = EventStatus.NOT_SENT;
|
||||
|
||||
room.addPendingEvent(evt, "123");
|
||||
|
||||
render(getComponent());
|
||||
|
||||
expect(screen.queryByText("!")).not.toBeNull();
|
||||
});
|
||||
|
||||
it("adds a warning for invites", () => {
|
||||
jest.spyOn(room, "getMyMembership").mockReturnValue("invite");
|
||||
render(getComponent());
|
||||
expect(screen.queryByText("!")).not.toBeNull();
|
||||
});
|
||||
|
||||
it("hides counter for muted rooms", () => {
|
||||
jest.spyOn(RoomNotifs, "getRoomNotifsState")
|
||||
.mockReset()
|
||||
.mockReturnValue(RoomNotifs.RoomNotifState.Mute);
|
||||
|
||||
const { container } = render(getComponent());
|
||||
expect(container.querySelector(".mx_NotificationBadge")).toBeNull();
|
||||
});
|
||||
});
|
|
@ -15,18 +15,14 @@ limitations under the License.
|
|||
*/
|
||||
|
||||
import React from 'react';
|
||||
import {
|
||||
renderIntoDocument,
|
||||
Simulate,
|
||||
findRenderedDOMComponentWithClass,
|
||||
act,
|
||||
} from 'react-dom/test-utils';
|
||||
import { render, fireEvent, RenderResult, waitFor } from "@testing-library/react";
|
||||
import { Room, RoomMember, MatrixError, IContent } from 'matrix-js-sdk/src/matrix';
|
||||
|
||||
import { stubClient } from '../../../test-utils';
|
||||
import { MatrixClientPeg } from '../../../../src/MatrixClientPeg';
|
||||
import DMRoomMap from '../../../../src/utils/DMRoomMap';
|
||||
import RoomPreviewBar from '../../../../src/components/views/rooms/RoomPreviewBar';
|
||||
import defaultDispatcher from "../../../../src/dispatcher/dispatcher";
|
||||
|
||||
jest.mock('../../../../src/IdentityAuthClient', () => {
|
||||
return jest.fn().mockImplementation(() => {
|
||||
|
@ -79,19 +75,18 @@ describe('<RoomPreviewBar />', () => {
|
|||
const defaultProps = {
|
||||
room: createRoom(roomId, userId),
|
||||
};
|
||||
const wrapper = renderIntoDocument<React.Component>(
|
||||
<RoomPreviewBar {...defaultProps} {...props} />,
|
||||
) as React.Component;
|
||||
return findRenderedDOMComponentWithClass(wrapper, 'mx_RoomPreviewBar') as HTMLDivElement;
|
||||
return render(<RoomPreviewBar {...defaultProps} {...props} />);
|
||||
};
|
||||
|
||||
const isSpinnerRendered = (element: Element) => !!element.querySelector('.mx_Spinner');
|
||||
const getMessage = (element: Element) => element.querySelector<HTMLDivElement>('.mx_RoomPreviewBar_message');
|
||||
const getActions = (element: Element) => element.querySelector<HTMLDivElement>('.mx_RoomPreviewBar_actions');
|
||||
const getPrimaryActionButton = (element: Element) =>
|
||||
getActions(element).querySelector('.mx_AccessibleButton_kind_primary');
|
||||
const getSecondaryActionButton = (element: Element) =>
|
||||
getActions(element).querySelector('.mx_AccessibleButton_kind_secondary');
|
||||
const isSpinnerRendered = (wrapper: RenderResult) => !!wrapper.container.querySelector('.mx_Spinner');
|
||||
const getMessage = (wrapper: RenderResult) =>
|
||||
wrapper.container.querySelector<HTMLDivElement>('.mx_RoomPreviewBar_message');
|
||||
const getActions = (wrapper: RenderResult) =>
|
||||
wrapper.container.querySelector<HTMLDivElement>('.mx_RoomPreviewBar_actions');
|
||||
const getPrimaryActionButton = (wrapper: RenderResult) =>
|
||||
getActions(wrapper).querySelector('.mx_AccessibleButton_kind_primary');
|
||||
const getSecondaryActionButton = (wrapper: RenderResult) =>
|
||||
getActions(wrapper).querySelector('.mx_AccessibleButton_kind_secondary');
|
||||
|
||||
beforeEach(() => {
|
||||
stubClient();
|
||||
|
@ -128,6 +123,36 @@ describe('<RoomPreviewBar />', () => {
|
|||
expect(getMessage(component).textContent).toEqual('Join the conversation with an account');
|
||||
});
|
||||
|
||||
it("should send room oob data to start login", async () => {
|
||||
MatrixClientPeg.get().isGuest = jest.fn().mockReturnValue(true);
|
||||
const component = getComponent({
|
||||
oobData: {
|
||||
name: "Room Name",
|
||||
avatarUrl: "mxc://foo/bar",
|
||||
inviterName: "Charlie",
|
||||
},
|
||||
});
|
||||
|
||||
const dispatcherSpy = jest.fn();
|
||||
const dispatcherRef = defaultDispatcher.register(dispatcherSpy);
|
||||
|
||||
expect(getMessage(component).textContent).toEqual('Join the conversation with an account');
|
||||
fireEvent.click(getPrimaryActionButton(component));
|
||||
|
||||
await waitFor(() => expect(dispatcherSpy).toHaveBeenCalledWith(expect.objectContaining({
|
||||
screenAfterLogin: {
|
||||
screen: 'room',
|
||||
params: expect.objectContaining({
|
||||
room_name: "Room Name",
|
||||
room_avatar_url: "mxc://foo/bar",
|
||||
inviter_name: "Charlie",
|
||||
}),
|
||||
},
|
||||
})));
|
||||
|
||||
defaultDispatcher.unregister(dispatcherRef);
|
||||
});
|
||||
|
||||
it('renders kicked message', () => {
|
||||
const room = createRoom(roomId, otherUserId);
|
||||
jest.spyOn(room, 'getMember').mockReturnValue(makeMockRoomMember({ isKicked: true }));
|
||||
|
@ -233,18 +258,14 @@ describe('<RoomPreviewBar />', () => {
|
|||
|
||||
it('joins room on primary button click', () => {
|
||||
const component = getComponent({ inviterName, room, onJoinClick, onRejectClick });
|
||||
act(() => {
|
||||
Simulate.click(getPrimaryActionButton(component));
|
||||
});
|
||||
fireEvent.click(getPrimaryActionButton(component));
|
||||
|
||||
expect(onJoinClick).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('rejects invite on secondary button click', () => {
|
||||
const component = getComponent({ inviterName, room, onJoinClick, onRejectClick });
|
||||
act(() => {
|
||||
Simulate.click(getSecondaryActionButton(component));
|
||||
});
|
||||
fireEvent.click(getSecondaryActionButton(component));
|
||||
|
||||
expect(onRejectClick).toHaveBeenCalled();
|
||||
});
|
||||
|
@ -296,9 +317,7 @@ describe('<RoomPreviewBar />', () => {
|
|||
await new Promise(setImmediate);
|
||||
expect(getPrimaryActionButton(component)).toBeTruthy();
|
||||
expect(getSecondaryActionButton(component)).toBeFalsy();
|
||||
act(() => {
|
||||
Simulate.click(getPrimaryActionButton(component));
|
||||
});
|
||||
fireEvent.click(getPrimaryActionButton(component));
|
||||
expect(onJoinClick).toHaveBeenCalled();
|
||||
};
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue