Skip to content

Commit b72bdbc

Browse files
Fix stopLiveSync method
Currently stopLiveSync method does not emit correct events in some cases. For example, when there's only one attached device and its identifier is passed to `stopLiveSync` method, we do not emit `liveSyncStopped` event. Fix the code and add unit tests to assure `liveSyncStopped` event is raised correctly.
1 parent ff5d1e5 commit b72bdbc

File tree

2 files changed

+151
-7
lines changed

2 files changed

+151
-7
lines changed

lib/services/livesync/livesync-service.ts

+4-7
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ const LiveSyncEvents = {
1717

1818
export class LiveSyncService extends EventEmitter implements ILiveSyncService {
1919
// key is projectDir
20-
private liveSyncProcessesInfo: IDictionary<ILiveSyncProcessInfo> = {};
20+
protected liveSyncProcessesInfo: IDictionary<ILiveSyncProcessInfo> = {};
2121

2222
constructor(protected $platformService: IPlatformService,
2323
private $projectDataService: IProjectDataService,
@@ -48,12 +48,10 @@ export class LiveSyncService extends EventEmitter implements ILiveSyncService {
4848
// so we cannot await it as this will cause infinite loop.
4949
const shouldAwaitPendingOperation = !stopOptions || stopOptions.shouldAwaitAllActions;
5050

51-
let removedDeviceIdentifiers: string[] = deviceIdentifiers || [];
51+
const deviceIdentifiersToRemove = deviceIdentifiers || _.map(liveSyncProcessInfo.deviceDescriptors, d => d.identifier);
5252

53-
_.each(deviceIdentifiers, deviceId => {
54-
removedDeviceIdentifiers = _.remove(liveSyncProcessInfo.deviceDescriptors, descriptor => descriptor.identifier === deviceId)
55-
.map(deviceDescriptor => deviceDescriptor.identifier);
56-
});
53+
const removedDeviceIdentifiers = _.remove(liveSyncProcessInfo.deviceDescriptors, descriptor => _.indexOf(deviceIdentifiersToRemove, descriptor.identifier) !== -1)
54+
.map(descriptor => descriptor.identifier);
5755

5856
// In case deviceIdentifiers are not passed, we should stop the whole LiveSync.
5957
if (!deviceIdentifiers || !deviceIdentifiers.length || !liveSyncProcessInfo.deviceDescriptors || !liveSyncProcessInfo.deviceDescriptors.length) {
@@ -72,7 +70,6 @@ export class LiveSyncService extends EventEmitter implements ILiveSyncService {
7270
await liveSyncProcessInfo.actionsChain;
7371
}
7472

75-
removedDeviceIdentifiers = _.map(liveSyncProcessInfo.deviceDescriptors, d => d.identifier);
7673
liveSyncProcessInfo.deviceDescriptors = [];
7774

7875
// Kill typescript watcher

test/services/livesync-service.ts

+147
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
import { Yok } from "../../lib/common/yok";
2+
import { assert } from "chai";
3+
import { LiveSyncService } from "../../lib/services/livesync/livesync-service";
4+
import { LoggerStub } from "../stubs";
5+
6+
const createTestInjector = (): IInjector => {
7+
const testInjector = new Yok();
8+
9+
testInjector.register("platformService", {});
10+
testInjector.register("projectDataService", {
11+
getProjectData: (projectDir: string): IProjectData => (<any>{})
12+
});
13+
14+
testInjector.register("devicesService", {});
15+
testInjector.register("mobileHelper", {});
16+
testInjector.register("devicePlatformsConstants", {});
17+
testInjector.register("nodeModulesDependenciesBuilder", {});
18+
testInjector.register("logger", LoggerStub);
19+
testInjector.register("processService", {});
20+
testInjector.register("hooksService", {
21+
executeAfterHooks: (commandName: string, hookArguments?: IDictionary<any>): Promise<void> => Promise.resolve()
22+
});
23+
24+
testInjector.register("pluginsService", {});
25+
testInjector.register("injector", testInjector);
26+
27+
return testInjector;
28+
};
29+
30+
class LiveSyncServiceInheritor extends LiveSyncService {
31+
constructor($platformService: IPlatformService,
32+
$projectDataService: IProjectDataService,
33+
$devicesService: Mobile.IDevicesService,
34+
$mobileHelper: Mobile.IMobileHelper,
35+
$devicePlatformsConstants: Mobile.IDevicePlatformsConstants,
36+
$nodeModulesDependenciesBuilder: INodeModulesDependenciesBuilder,
37+
$logger: ILogger,
38+
$processService: IProcessService,
39+
$hooksService: IHooksService,
40+
$pluginsService: IPluginsService,
41+
$injector: IInjector) {
42+
43+
super(
44+
$platformService,
45+
$projectDataService,
46+
$devicesService,
47+
$mobileHelper,
48+
$devicePlatformsConstants,
49+
$nodeModulesDependenciesBuilder,
50+
$logger,
51+
$processService,
52+
$hooksService,
53+
$pluginsService,
54+
$injector
55+
);
56+
}
57+
58+
public liveSyncProcessesInfo: IDictionary<ILiveSyncProcessInfo> = {};
59+
}
60+
61+
interface IStopLiveSyncTestCase {
62+
name: string;
63+
currentDeviceIdentifiers: string[];
64+
expectedDeviceIdentifiers: string[];
65+
deviceIdentifiersToBeStopped?: string[];
66+
}
67+
68+
describe("liveSyncService", () => {
69+
describe("stopLiveSync", () => {
70+
const getLiveSyncProcessInfo = (): ILiveSyncProcessInfo => ({
71+
actionsChain: Promise.resolve(),
72+
currentSyncAction: Promise.resolve(),
73+
isStopped: false,
74+
timer: setTimeout(() => undefined, 1000),
75+
watcherInfo: {
76+
watcher: <any>{
77+
close: (): any => undefined
78+
},
79+
pattern: "pattern"
80+
},
81+
deviceDescriptors: []
82+
});
83+
84+
const getDeviceDescriptor = (identifier: string): ILiveSyncDeviceInfo => ({
85+
identifier,
86+
outputPath: "",
87+
skipNativePrepare: false,
88+
platformSpecificOptions: null,
89+
buildAction: () => Promise.resolve("")
90+
});
91+
92+
const testCases: IStopLiveSyncTestCase[] = [
93+
{
94+
name: "stops LiveSync operation for all devices and emits liveSyncStopped for all of them when stopLiveSync is called without deviceIdentifiers",
95+
currentDeviceIdentifiers: ["device1", "device2", "device3"],
96+
expectedDeviceIdentifiers: ["device1", "device2", "device3"]
97+
},
98+
{
99+
name: "stops LiveSync operation for all devices and emits liveSyncStopped for all of them when stopLiveSync is called without deviceIdentifiers (when a single device is attached)",
100+
currentDeviceIdentifiers: ["device1"],
101+
expectedDeviceIdentifiers: ["device1"]
102+
},
103+
{
104+
name: "stops LiveSync operation for specified devices and emits liveSyncStopped for each of them (when a single device is attached)",
105+
currentDeviceIdentifiers: ["device1"],
106+
expectedDeviceIdentifiers: ["device1"],
107+
deviceIdentifiersToBeStopped: ["device1"]
108+
},
109+
{
110+
name: "stops LiveSync operation for specified devices and emits liveSyncStopped for each of them",
111+
currentDeviceIdentifiers: ["device1", "device2", "device3"],
112+
expectedDeviceIdentifiers: ["device1", "device3"],
113+
deviceIdentifiersToBeStopped: ["device1", "device3"]
114+
},
115+
{
116+
name: "does not raise liveSyncStopped event for device, which is not currently being liveSynced",
117+
currentDeviceIdentifiers: ["device1", "device2", "device3"],
118+
expectedDeviceIdentifiers: ["device1"],
119+
deviceIdentifiersToBeStopped: ["device1", "device4"]
120+
}
121+
];
122+
123+
for (const testCase of testCases) {
124+
it(testCase.name, async () => {
125+
const testInjector = createTestInjector();
126+
const liveSyncService = testInjector.resolve<LiveSyncServiceInheritor>(LiveSyncServiceInheritor);
127+
const projectDir = "projectDir";
128+
const emittedDeviceIdentifiersForLiveSyncStoppedEvent: string[] = [];
129+
liveSyncService.on("liveSyncStopped", (data: { projectDir: string, deviceIdentifier: string }) => {
130+
assert.equal(data.projectDir, projectDir);
131+
emittedDeviceIdentifiersForLiveSyncStoppedEvent.push(data.deviceIdentifier);
132+
});
133+
134+
// Setup liveSyncProcessesInfo for current test
135+
liveSyncService.liveSyncProcessesInfo[projectDir] = getLiveSyncProcessInfo();
136+
const deviceDescriptors = testCase.currentDeviceIdentifiers.map(d => getDeviceDescriptor(d));
137+
liveSyncService.liveSyncProcessesInfo[projectDir].deviceDescriptors.push(...deviceDescriptors);
138+
139+
await liveSyncService.stopLiveSync(projectDir, testCase.deviceIdentifiersToBeStopped);
140+
141+
assert.deepEqual(emittedDeviceIdentifiersForLiveSyncStoppedEvent, testCase.expectedDeviceIdentifiers);
142+
});
143+
}
144+
145+
});
146+
147+
});

0 commit comments

Comments
 (0)