Device manager - current session context menu (#9386)

* add destructive option and close on interaction options

* add kebab context menu wrapper

* use kebab context menu in current device section

* use named export

* lint

* sessionman tests
This commit is contained in:
Kerry 2022-10-13 09:07:34 +02:00 committed by GitHub
parent 8b54be6f48
commit 776ffa4764
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 468 additions and 108 deletions

View file

@ -285,47 +285,6 @@ describe('<SessionManagerTab />', () => {
expect(queryByTestId('device-detail-metadata-application')).toBeFalsy();
});
it('renders current session section with an unverified session', async () => {
mockClient.getDevices.mockResolvedValue({ devices: [alicesDevice, alicesMobileDevice] });
const { getByTestId } = render(getComponent());
await act(async () => {
await flushPromisesWithFakeTimers();
});
expect(getByTestId('current-session-section')).toMatchSnapshot();
});
it('opens encryption setup dialog when verifiying current session', async () => {
mockClient.getDevices.mockResolvedValue({ devices: [alicesDevice, alicesMobileDevice] });
const { getByTestId } = render(getComponent());
const modalSpy = jest.spyOn(Modal, 'createDialog');
await act(async () => {
await flushPromisesWithFakeTimers();
});
// click verify button from current session section
fireEvent.click(getByTestId(`verification-status-button-${alicesDevice.device_id}`));
expect(modalSpy).toHaveBeenCalled();
});
it('renders current session section with a verified session', async () => {
mockClient.getDevices.mockResolvedValue({ devices: [alicesDevice, alicesMobileDevice] });
mockClient.getStoredDevice.mockImplementation(() => new DeviceInfo(alicesDevice.device_id));
mockCrossSigningInfo.checkDeviceTrust
.mockReturnValue(new DeviceTrustLevel(true, true, false, false));
const { getByTestId } = render(getComponent());
await act(async () => {
await flushPromisesWithFakeTimers();
});
expect(getByTestId('current-session-section')).toMatchSnapshot();
});
it('does not render other sessions section when user has only one device', async () => {
mockClient.getDevices.mockResolvedValue({ devices: [alicesDevice] });
const { queryByTestId } = render(getComponent());
@ -367,6 +326,64 @@ describe('<SessionManagerTab />', () => {
expect(container.querySelector('.mx_FilteredDeviceListHeader')).toMatchSnapshot();
});
describe('current session section', () => {
it('disables current session context menu while devices are loading', () => {
const { getByTestId } = render(getComponent());
expect(getByTestId('current-session-menu').getAttribute('aria-disabled')).toBeTruthy();
});
it('disables current session context menu when there is no current device', async () => {
mockClient.getDevices.mockResolvedValue({ devices: [] });
const { getByTestId } = render(getComponent());
await act(async () => {
await flushPromisesWithFakeTimers();
});
expect(getByTestId('current-session-menu').getAttribute('aria-disabled')).toBeTruthy();
});
it('renders current session section with an unverified session', async () => {
mockClient.getDevices.mockResolvedValue({ devices: [alicesDevice, alicesMobileDevice] });
const { getByTestId } = render(getComponent());
await act(async () => {
await flushPromisesWithFakeTimers();
});
expect(getByTestId('current-session-section')).toMatchSnapshot();
});
it('opens encryption setup dialog when verifiying current session', async () => {
mockClient.getDevices.mockResolvedValue({ devices: [alicesDevice, alicesMobileDevice] });
const { getByTestId } = render(getComponent());
const modalSpy = jest.spyOn(Modal, 'createDialog');
await act(async () => {
await flushPromisesWithFakeTimers();
});
// click verify button from current session section
fireEvent.click(getByTestId(`verification-status-button-${alicesDevice.device_id}`));
expect(modalSpy).toHaveBeenCalled();
});
it('renders current session section with a verified session', async () => {
mockClient.getDevices.mockResolvedValue({ devices: [alicesDevice, alicesMobileDevice] });
mockClient.getStoredDevice.mockImplementation(() => new DeviceInfo(alicesDevice.device_id));
mockCrossSigningInfo.checkDeviceTrust
.mockReturnValue(new DeviceTrustLevel(true, true, false, false));
const { getByTestId } = render(getComponent());
await act(async () => {
await flushPromisesWithFakeTimers();
});
expect(getByTestId('current-session-section')).toMatchSnapshot();
});
});
describe('device detail expansion', () => {
it('renders no devices expanded by default', async () => {
mockClient.getDevices.mockResolvedValue({
@ -520,6 +537,53 @@ describe('<SessionManagerTab />', () => {
expect(modalSpy).toHaveBeenCalledWith(LogoutDialog, {}, undefined, false, true);
});
it('Signs out of current device from kebab menu', async () => {
const modalSpy = jest.spyOn(Modal, 'createDialog');
mockClient.getDevices.mockResolvedValue({ devices: [alicesDevice] });
const { getByTestId, getByLabelText } = render(getComponent());
await act(async () => {
await flushPromisesWithFakeTimers();
});
fireEvent.click(getByTestId('current-session-menu'));
fireEvent.click(getByLabelText('Sign out'));
// logout dialog opened
expect(modalSpy).toHaveBeenCalledWith(LogoutDialog, {}, undefined, false, true);
});
it('does not render sign out other devices option when only one device', async () => {
mockClient.getDevices.mockResolvedValue({ devices: [alicesDevice] });
const { getByTestId, queryByLabelText } = render(getComponent());
await act(async () => {
await flushPromisesWithFakeTimers();
});
fireEvent.click(getByTestId('current-session-menu'));
expect(queryByLabelText('Sign out all other sessions')).toBeFalsy();
});
it('signs out of all other devices from current session context menu', async () => {
mockClient.getDevices.mockResolvedValue({ devices: [
alicesDevice, alicesMobileDevice, alicesOlderMobileDevice,
] });
const { getByTestId, getByLabelText } = render(getComponent());
await act(async () => {
await flushPromisesWithFakeTimers();
});
fireEvent.click(getByTestId('current-session-menu'));
fireEvent.click(getByLabelText('Sign out all other sessions'));
// other devices deleted, excluding current device
expect(mockClient.deleteMultipleDevices).toHaveBeenCalledWith([
alicesMobileDevice.device_id, alicesOlderMobileDevice.device_id,
], undefined);
});
describe('other devices', () => {
const interactiveAuthError = { httpStatus: 401, data: { flows: [{ stages: ["m.login.password"] }] } };