From 5478891444cc60d87449809b9e022ed3fd2554a2 Mon Sep 17 00:00:00 2001 From: rosen-vladimirov Date: Fri, 30 Aug 2019 09:01:05 +0300 Subject: [PATCH] fix: save and remove of user-settings are not working Due to recent changes, trying to save a setting in the user-settings.json or to remove it from there is not working. This breaks all new users and the execution of commands like `tns usage-reporting enable/disable`, `tns error-reporting enable/disable`. The problem is an infinite recursion in the userSettingsService, which should just call jsonFileSettingsService, but instead it calls itself. Fix the recursion and add unit tests for the userSettingsService to ensure it acts as a proxy to jsonFileSettingsService. --- lib/services/user-settings-service.ts | 5 +- test/services/user-settings-service.ts | 82 ++++++++++++++++++++++++++ 2 files changed, 85 insertions(+), 2 deletions(-) create mode 100644 test/services/user-settings-service.ts diff --git a/lib/services/user-settings-service.ts b/lib/services/user-settings-service.ts index c3d39f654e..23e342e9b0 100644 --- a/lib/services/user-settings-service.ts +++ b/lib/services/user-settings-service.ts @@ -5,6 +5,7 @@ export class UserSettingsService implements IUserSettingsService { const userSettingsFilePath = path.join(this.$settingsService.getProfileDir(), "user-settings.json"); return this.$injector.resolve("jsonFileSettingsService", { jsonFileSettingsPath: userSettingsFilePath }); } + constructor(private $injector: IInjector, private $settingsService: ISettingsService) { } @@ -14,7 +15,7 @@ export class UserSettingsService implements IUserSettingsService { } public saveSetting(key: string, value: T, cacheOpts?: IUseCacheOpts): Promise { - return this.saveSetting(key, value, cacheOpts); + return this.$jsonFileSettingsService.saveSetting(key, value, cacheOpts); } public saveSettings(data: IDictionary<{}>, cacheOpts?: IUseCacheOpts): Promise { @@ -22,7 +23,7 @@ export class UserSettingsService implements IUserSettingsService { } public removeSetting(key: string): Promise { - return this.removeSetting(key); + return this.$jsonFileSettingsService.removeSetting(key); } public loadUserSettingsFile(): Promise { diff --git a/test/services/user-settings-service.ts b/test/services/user-settings-service.ts new file mode 100644 index 0000000000..de8d012564 --- /dev/null +++ b/test/services/user-settings-service.ts @@ -0,0 +1,82 @@ +import { Yok } from "../../lib/common/yok"; +import { UserSettingsService } from "../../lib/services/user-settings-service"; +import { assert } from "chai"; +import * as path from "path"; + +class JsonFileSettingsServiceMock { + constructor(public jsonFileSettingsPath: string) { } +} + +describe("userSettingsService", () => { + const profileDir = "my-profile-dir"; + const expectedJsonFileSettingsFilePath = path.join(profileDir, "user-settings.json"); + + const createTestInjector = (): IInjector => { + const testInjector = new Yok(); + testInjector.register("settingsService", { + getProfileDir: () => profileDir + }); + + testInjector.register("jsonFileSettingsService", JsonFileSettingsServiceMock); + testInjector.register("userSettingsService", UserSettingsService); + return testInjector; + }; + + const testCases = [ + { + methodName: "getSettingValue", + input: ["settingName"], + expectedArgs: [ + "settingName", + undefined + ] + }, + { + methodName: "saveSetting", + input: ["settingName", "settingValue"], + expectedArgs: [ + "settingName", + "settingValue", + undefined + ] + }, + { + methodName: "saveSettings", + input: [{ value: { subValue: 1 } }], + expectedArgs: [ + { value: { subValue: 1 } }, + undefined + ] + }, + { + methodName: "removeSetting", + input: ["settingName"], + expectedArgs: [ + "settingName" + ] + }, + { + methodName: "loadUserSettingsFile", + input: [], + expectedArgs: [] + } + ]; + + for (const testCase of testCases) { + it(`calls ${testCase.methodName} method of jsonFileSettingsService with correct args`, async () => { + const testInjector = createTestInjector(); + const dataPassedToJsonFileSettingsService: any[] = []; + const userSettingsService = testInjector.resolve("userSettingsService"); + const jsonFileSettingsService = userSettingsService.$jsonFileSettingsService; + + jsonFileSettingsService[testCase.methodName] = async (...args: any[]): Promise => { + dataPassedToJsonFileSettingsService.push(...args); + }; + + await userSettingsService[testCase.methodName](...testCase.input); + + assert.deepEqual(dataPassedToJsonFileSettingsService, testCase.expectedArgs); + assert.equal(jsonFileSettingsService.jsonFileSettingsPath, expectedJsonFileSettingsFilePath); + }); + } +});