Files
flipper/desktop/app/src/__tests__/disconnect.node.tsx
Michel Weststrate 740093d0d9 Separate Client in server and client part
Summary: This diff separates the concept of a Client as now on the UI, from the concept of a Client as known on the server, and makes all interactions with client and vice versa async.

Reviewed By: timur-valiev

Differential Revision: D31235682

fbshipit-source-id: 99089e9b390b4c5359f97f6f2b15bf4b182b6cb9
2021-10-06 09:10:19 -07:00

244 lines
7.5 KiB
TypeScript

/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
*/
import {createMockFlipperWithPlugin} from '../test-utils/createMockFlipperWithPlugin';
import {
TestUtils,
_SandyPluginDefinition,
createState,
DevicePluginClient,
PluginClient,
} from 'flipper-plugin';
import {handleClientConnected} from '../dispatcher/flipperServer';
import {TestDevice} from '../test-utils/TestDevice';
test('Devices can disconnect', async () => {
const deviceplugin = new _SandyPluginDefinition(
TestUtils.createMockPluginDetails(),
{
devicePlugin(client: DevicePluginClient) {
const destroy = jest.fn();
client.onDestroy(destroy);
const counter = createState(0);
return {
counter,
destroy,
get isConnected() {
return client.device.isConnected;
},
};
},
supportsDevice() {
return true;
},
Component() {
return null;
},
},
);
const {device} = await createMockFlipperWithPlugin(deviceplugin);
device.sandyPluginStates.get(deviceplugin.id)!.instanceApi.counter.set(1);
expect(
device.sandyPluginStates.get(deviceplugin.id)!.instanceApi.isConnected,
).toBe(true);
expect(device.isArchived).toBe(false);
expect(device.connected.get()).toBe(true);
device.disconnect();
expect(device.isArchived).toBe(false);
expect(device.connected.get()).toBe(false);
const instance = device.sandyPluginStates.get(deviceplugin.id)!;
expect(instance.instanceApi.isConnected).toBe(false);
expect(instance).toBeTruthy();
expect(instance.instanceApi.counter.get()).toBe(1); // state preserved
expect(instance.instanceApi.destroy).toBeCalledTimes(0);
device.destroy();
expect(device.isArchived).toBe(false);
expect(device.connected.get()).toBe(false);
expect(instance.instanceApi.destroy).toBeCalledTimes(1);
expect(device.sandyPluginStates.get(deviceplugin.id)).toBeUndefined();
});
test('New device with same serial removes & cleans the old one', async () => {
const deviceplugin = new _SandyPluginDefinition(
TestUtils.createMockPluginDetails({pluginType: 'device'}),
{
devicePlugin(client: DevicePluginClient) {
const destroy = jest.fn();
client.onDestroy(destroy);
return {
destroy,
};
},
supportsDevice() {
return true;
},
Component() {
return null;
},
},
);
const {device, store} = await createMockFlipperWithPlugin(deviceplugin);
const instance = device.sandyPluginStates.get(deviceplugin.id)!;
expect(device.isArchived).toBe(false);
expect(device.connected.get()).toBe(true);
expect(instance.instanceApi.destroy).toBeCalledTimes(0);
expect(store.getState().connections.devices).toEqual([device]);
// submit a new device with same serial
const device2 = new TestDevice(
device.serial,
'physical',
'MockAndroidDevice',
'Android',
);
expect(() => {
store.dispatch({
type: 'REGISTER_DEVICE',
payload: device2,
});
}).toThrow('still connected');
device.destroy();
store.dispatch({
type: 'REGISTER_DEVICE',
payload: device2,
});
device2.loadDevicePlugins(
store.getState().plugins.devicePlugins,
store.getState().connections.enabledDevicePlugins,
);
expect(device.isArchived).toBe(false);
expect(device.connected.get()).toBe(false);
expect(instance.instanceApi.destroy).toBeCalledTimes(1);
expect(
device2.sandyPluginStates.get(deviceplugin.id)!.instanceApi.destroy,
).toBeCalledTimes(0);
expect(store.getState().connections.devices.length).toBe(1);
expect(store.getState().connections.devices[0]).toBe(device2);
});
test('clients can disconnect but preserve state', async () => {
const plugin = new _SandyPluginDefinition(
TestUtils.createMockPluginDetails(),
{
plugin(client: PluginClient) {
const connect = jest.fn();
const disconnect = jest.fn();
const destroy = jest.fn();
client.onConnect(connect);
client.onDestroy(destroy);
client.onDisconnect(disconnect);
const counter = createState(0);
return {
connect,
disconnect,
counter,
destroy,
get isConnected() {
return client.isConnected;
},
};
},
Component() {
return null;
},
},
);
const {client} = await createMockFlipperWithPlugin(plugin, {
asBackgroundPlugin: true,
});
let instance = client.sandyPluginStates.get(plugin.id)!;
instance.instanceApi.counter.set(1);
expect(instance.instanceApi.destroy).toBeCalledTimes(0);
expect(instance.instanceApi.connect).toBeCalledTimes(1);
expect(instance.instanceApi.disconnect).toBeCalledTimes(0);
expect(instance.instanceApi.isConnected).toBe(true);
expect(client.connected.get()).toBe(true);
client.disconnect();
expect(client.connected.get()).toBe(false);
instance = client.sandyPluginStates.get(plugin.id)!;
expect(instance).toBeTruthy();
expect(instance.instanceApi.counter.get()).toBe(1); // state preserved
expect(instance.instanceApi.isConnected).toBe(false);
expect(instance.instanceApi.destroy).toBeCalledTimes(0);
expect(instance.instanceApi.connect).toBeCalledTimes(1);
expect(instance.instanceApi.disconnect).toBeCalledTimes(1);
client.destroy();
expect(instance.instanceApi.destroy).toBeCalledTimes(1);
expect(instance.instanceApi.connect).toBeCalledTimes(1);
expect(instance.instanceApi.disconnect).toBeCalledTimes(1);
expect(client.sandyPluginStates.get(plugin.id)).toBeUndefined();
});
test('new clients replace old ones', async () => {
const plugin = new _SandyPluginDefinition(
TestUtils.createMockPluginDetails(),
{
plugin(client: PluginClient) {
const connect = jest.fn();
const disconnect = jest.fn();
const destroy = jest.fn();
client.onConnect(connect);
client.onDestroy(destroy);
client.onDisconnect(disconnect);
const counter = createState(0);
return {
connect,
disconnect,
counter,
destroy,
};
},
Component() {
return null;
},
},
);
const {client, store, device, createClient, logger} =
await createMockFlipperWithPlugin(plugin, {
asBackgroundPlugin: true,
});
const instance = client.sandyPluginStates.get(plugin.id)!;
instance.instanceApi.counter.set(1);
expect(instance.instanceApi.destroy).toBeCalledTimes(0);
expect(instance.instanceApi.connect).toBeCalledTimes(1);
expect(instance.instanceApi.disconnect).toBeCalledTimes(0);
const client2 = await createClient(device, 'AnotherApp', client.query, true);
handleClientConnected(null as any, store, logger, client2);
expect(client2.connected.get()).toBe(true);
const instance2 = client2.sandyPluginStates.get(plugin.id)!;
expect(instance2).toBeTruthy();
expect(instance2.instanceApi.counter.get()).toBe(0);
expect(instance2.instanceApi.destroy).toBeCalledTimes(0);
expect(instance2.instanceApi.connect).toBeCalledTimes(1);
expect(instance2.instanceApi.disconnect).toBeCalledTimes(0);
expect(client.connected.get()).toBe(false);
expect(instance.instanceApi.counter.get()).toBe(1);
expect(instance.instanceApi.destroy).toBeCalledTimes(1);
expect(instance.instanceApi.connect).toBeCalledTimes(1);
expect(instance.instanceApi.disconnect).toBeCalledTimes(1);
});