From e0bc1cb2f65262765fb2fdf6092da2c80f0ae1ee Mon Sep 17 00:00:00 2001 From: rosen-vladimirov Date: Fri, 23 Jun 2017 17:29:29 +0300 Subject: [PATCH 1/6] Fix starting of emulator on `tns debug ` when device is not attached `tns debug ` command should start emulator in case device is not attached. The current command does not start emulator as we have passed `skipInferPlatform` - when this option is used, devicesService does not know for which platform to start the emulator. Fix this by passing correct options. --- lib/commands/debug.ts | 6 +----- lib/common | 2 +- lib/services/ios-project-service.ts | 2 +- 3 files changed, 3 insertions(+), 7 deletions(-) diff --git a/lib/commands/debug.ts b/lib/commands/debug.ts index 1a9a79e12b..4d2217c508 100644 --- a/lib/commands/debug.ts +++ b/lib/commands/debug.ts @@ -29,9 +29,6 @@ this.$config.debugLivesync = true; - await this.$devicesService.initialize({ - - }); await this.$devicesService.detectCurrentlyAttachedDevices(); const devices = this.$devicesService.getDeviceInstances(); @@ -86,8 +83,7 @@ platform: this.platform, deviceId: this.$options.device, emulator: this.$options.emulator, - skipDeviceDetectionInterval: true, - skipInferPlatform: true + skipDeviceDetectionInterval: true }); // Start emulator if --emulator is selected or no devices found. if (this.$options.emulator || this.$devicesService.deviceCount === 0) { diff --git a/lib/common b/lib/common index f906af7e73..2a6d178e57 160000 --- a/lib/common +++ b/lib/common @@ -1 +1 @@ -Subproject commit f906af7e73171ca839a8313f4d33f8e6a0ae88ee +Subproject commit 2a6d178e5722486e03c70ea721f1be512952f102 diff --git a/lib/services/ios-project-service.ts b/lib/services/ios-project-service.ts index deec5de691..2d6d966e00 100644 --- a/lib/services/ios-project-service.ts +++ b/lib/services/ios-project-service.ts @@ -338,7 +338,7 @@ export class IOSProjectService extends projectServiceBaseLib.PlatformProjectServ if (!buildConfig.release && !buildConfig.architectures) { await this.$devicesService.initialize({ platform: this.$devicePlatformsConstants.iOS.toLowerCase(), deviceId: buildConfig.device, - isBuildForDevice: true + skipEmulatorStart: true }); let instances = this.$devicesService.getDeviceInstances(); let devicesArchitectures = _(instances) From a0c637983abb9bb7003607623f22daf64fad786b Mon Sep 17 00:00:00 2001 From: rosen-vladimirov Date: Fri, 23 Jun 2017 18:14:35 +0300 Subject: [PATCH 2/6] Fix asking for user email on postinstall On postinstall CLI asks the users if they want to subscribe for NativeScript's newsletter. This check has been broken in 3.0.0 because of incorrect await. In order to add tests for this functionality, introduce a new service that handles the check and sending of information about the user's mail. Add the following tests: - ensure postinstall.js calls correct CLI command - ensure the post-install-cli command calls the new service - ensure the new service works correctly --- lib/bootstrap.ts | 1 + lib/commands/post-install.ts | 62 +---- lib/constants.ts | 1 + lib/definitions/subscription-service.d.ts | 11 + lib/services/subscription-service.ts | 73 ++++++ postinstall.js | 5 +- test/commands/post-install.ts | 59 +++++ test/post-install.ts | 35 +++ test/services/subscription-service.ts | 286 ++++++++++++++++++++++ 9 files changed, 471 insertions(+), 62 deletions(-) create mode 100644 lib/definitions/subscription-service.d.ts create mode 100644 lib/services/subscription-service.ts create mode 100644 test/commands/post-install.ts create mode 100644 test/post-install.ts create mode 100644 test/services/subscription-service.ts diff --git a/lib/bootstrap.ts b/lib/bootstrap.ts index 0ebcc14815..ef4717e4eb 100644 --- a/lib/bootstrap.ts +++ b/lib/bootstrap.ts @@ -139,3 +139,4 @@ $injector.requireCommand("extension|uninstall", "./commands/extensibility/uninst $injector.requirePublic("extensibilityService", "./services/extensibility-service"); $injector.require("nodeModulesDependenciesBuilder", "./tools/node-modules/node-modules-dependencies-builder"); +$injector.require("subscriptionService", "./services/subscription-service"); diff --git a/lib/commands/post-install.ts b/lib/commands/post-install.ts index 87263def0c..779703e5c3 100644 --- a/lib/commands/post-install.ts +++ b/lib/commands/post-install.ts @@ -1,15 +1,8 @@ import { PostInstallCommand } from "../common/commands/post-install"; -import * as emailValidator from "email-validator"; -import * as queryString from "querystring"; -import * as helpers from "../common/helpers"; export class PostInstallCliCommand extends PostInstallCommand { - private logger: ILogger; - constructor($fs: IFileSystem, - private $httpClient: Server.IHttpClient, - private $prompter: IPrompter, - private $userSettingsService: IUserSettingsService, + private $subscriptionService: ISubscriptionService, $staticConfig: Config.IStaticConfig, $commandsService: ICommandsService, $htmlHelpService: IHtmlHelpService, @@ -18,63 +11,12 @@ export class PostInstallCliCommand extends PostInstallCommand { $analyticsService: IAnalyticsService, $logger: ILogger) { super($fs, $staticConfig, $commandsService, $htmlHelpService, $options, $doctorService, $analyticsService, $logger); - this.logger = $logger; } public async execute(args: string[]): Promise { await super.execute(args); - if (await this.shouldAskForEmail()) { - this.logger.out("Leave your e-mail address here to subscribe for NativeScript newsletter and product updates, tips and tricks:"); - let email = await this.getEmail("(press Enter for blank)"); - await this.$userSettingsService.saveSetting("EMAIL_REGISTERED", true); - await this.sendEmail(email); - } - } - - private async shouldAskForEmail(): Promise { - return helpers.isInteractive() && await process.env.CLI_NOPROMPT !== "1" && !this.$userSettingsService.getSettingValue("EMAIL_REGISTERED"); - } - - private async getEmail(prompt: string, options?: IPrompterOptions): Promise { - let schema: IPromptSchema = { - message: prompt, - type: "input", - name: "inputEmail", - validate: (value: any) => { - if (value === "" || emailValidator.validate(value)) { - return true; - } - return "Please provide a valid e-mail or simply leave it blank."; - }, - default: options && options.defaultAction - }; - - let result = await this.$prompter.get([schema]); - return result.inputEmail; - } - - private async sendEmail(email: string): Promise { - if (email) { - let postData = queryString.stringify({ - 'elqFormName': "dev_uins_cli", - 'elqSiteID': '1325', - 'emailAddress': email, - 'elqCookieWrite': '0' - }); - - let options = { - url: 'https://s1325.t.eloqua.com/e/f2', - method: 'POST', - headers: { - 'Content-Type': 'application/x-www-form-urlencoded', - 'Content-Length': postData.length - }, - body: postData - }; - - await this.$httpClient.httpRequest(options); - } + await this.$subscriptionService.subscribeForNewsletter(); } } diff --git a/lib/constants.ts b/lib/constants.ts index 984accc309..7da59a05a0 100644 --- a/lib/constants.ts +++ b/lib/constants.ts @@ -86,3 +86,4 @@ export const BUILD_OUTPUT_EVENT_NAME = "buildOutput"; export const CONNECTION_ERROR_EVENT_NAME = "connectionError"; export const VERSION_STRING = "version"; export const INSPECTOR_CACHE_DIRNAME = "ios-inspector"; +export const POST_INSTALL_COMMAND_NAME = "post-install-cli"; diff --git a/lib/definitions/subscription-service.d.ts b/lib/definitions/subscription-service.d.ts new file mode 100644 index 0000000000..4e4d0e79d1 --- /dev/null +++ b/lib/definitions/subscription-service.d.ts @@ -0,0 +1,11 @@ +/** + * Describes methods for subscribing to different NativeScript campaigns. + */ +interface ISubscriptionService { + /** + * Subscribes users for NativeScript's newsletter by asking them for their email. + * In case we've already asked the user for his email, this method will do nothing. + * @returns {Promise} + */ + subscribeForNewsletter(): Promise; +} diff --git a/lib/services/subscription-service.ts b/lib/services/subscription-service.ts new file mode 100644 index 0000000000..8a9e18a6cf --- /dev/null +++ b/lib/services/subscription-service.ts @@ -0,0 +1,73 @@ +import * as emailValidator from "email-validator"; +import * as queryString from "querystring"; +import * as helpers from "../common/helpers"; + +export class SubscriptionService implements ISubscriptionService { + constructor(private $httpClient: Server.IHttpClient, + private $prompter: IPrompter, + private $userSettingsService: IUserSettingsService, + private $logger: ILogger) { + } + + public async subscribeForNewsletter(): Promise { + if (await this.shouldAskForEmail()) { + this.$logger.out("Leave your e-mail address here to subscribe for NativeScript newsletter and product updates, tips and tricks:"); + let email = await this.getEmail("(press Enter for blank)"); + await this.$userSettingsService.saveSetting("EMAIL_REGISTERED", true); + await this.sendEmail(email); + } + } + + /** + * Checks whether we should ask the current user if they want to subscribe to NativeScript newsletter. + * NOTE: This method is protected, not private, only because of our unit tests. + * @returns {Promise} + */ + protected async shouldAskForEmail(): Promise { + return helpers.isInteractive() && process.env.CLI_NOPROMPT !== "1" && !(await this.$userSettingsService.getSettingValue("EMAIL_REGISTERED")); + } + + private async getEmail(prompt: string, options?: IPrompterOptions): Promise { + let schema: IPromptSchema = { + message: prompt, + type: "input", + name: "inputEmail", + validate: (value: any) => { + if (value === "" || emailValidator.validate(value)) { + return true; + } + + return "Please provide a valid e-mail or simply leave it blank."; + } + }; + + let result = await this.$prompter.get([schema]); + return result.inputEmail; + } + + private async sendEmail(email: string): Promise { + if (email) { + let postData = queryString.stringify({ + 'elqFormName': "dev_uins_cli", + 'elqSiteID': '1325', + 'emailAddress': email, + 'elqCookieWrite': '0' + }); + + let options = { + url: 'https://s1325.t.eloqua.com/e/f2', + method: 'POST', + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + 'Content-Length': postData.length + }, + body: postData + }; + + await this.$httpClient.httpRequest(options); + } + } + +} + +$injector.register("subscriptionService", SubscriptionService); diff --git a/postinstall.js b/postinstall.js index a5bb15e6a1..8c3a76fab2 100644 --- a/postinstall.js +++ b/postinstall.js @@ -1,8 +1,9 @@ "use strict"; var child_process = require("child_process"); -var commandArgs = ["bin/tns", "post-install-cli"]; var path = require("path"); +var constants = require(path.join(__dirname, "lib", "constants")); +var commandArgs = [path.join(__dirname, "bin", "tns"), constants.POST_INSTALL_COMMAND_NAME]; var nodeArgs = require(path.join(__dirname, "lib", "common", "scripts", "node-args")).getNodeArgs(); -child_process.spawn(process.argv[0], nodeArgs.concat(commandArgs), {stdio: "inherit"}); +child_process.spawn(process.argv[0], nodeArgs.concat(commandArgs), { stdio: "inherit" }); diff --git a/test/commands/post-install.ts b/test/commands/post-install.ts new file mode 100644 index 0000000000..5cadda5c0b --- /dev/null +++ b/test/commands/post-install.ts @@ -0,0 +1,59 @@ +import { Yok } from "../../lib/common/yok"; +import { assert } from "chai"; +import { PostInstallCliCommand } from "../../lib/commands/post-install"; + +const createTestInjector = (): IInjector => { + const testInjector = new Yok(); + testInjector.register("fs", { + setCurrentUserAsOwner: async (path: string, owner: string): Promise => undefined + }); + + testInjector.register("subscriptionService", { + subscribeForNewsletter: async (): Promise => undefined + }); + + testInjector.register("staticConfig", {}); + + testInjector.register("commandsService", { + tryExecuteCommand: async (commandName: string, commandArguments: string[]): Promise => undefined + }); + + testInjector.register("htmlHelpService", { + generateHtmlPages: async (): Promise => undefined + }); + + testInjector.register("options", {}); + + testInjector.register("doctorService", { + printWarnings: async (configOptions?: { trackResult: boolean }): Promise => undefined + }); + + testInjector.register("analyticsService", { + checkConsent: async (): Promise => undefined, + track: async (featureName: string, featureValue: string): Promise => undefined + }); + + testInjector.register("logger", { + out: (formatStr?: any, ...args: any[]): void => undefined, + printMarkdown: (...args: any[]): void => undefined + }); + + testInjector.registerCommand("post-install-cli", PostInstallCliCommand); + + return testInjector; +}; + +describe("post-install command", () => { + it("calls subscriptionService.subscribeForNewsletter method", async () => { + const testInjector = createTestInjector(); + const subscriptionService = testInjector.resolve("subscriptionService"); + let isSubscribeForNewsletterCalled = false; + subscriptionService.subscribeForNewsletter = async (): Promise => { + isSubscribeForNewsletterCalled = true; + }; + const postInstallCommand = testInjector.resolveCommand("post-install-cli"); + + await postInstallCommand.execute([]); + assert.isTrue(isSubscribeForNewsletterCalled, "post-install-cli command must call subscriptionService.subscribeForNewsletter"); + }); +}); diff --git a/test/post-install.ts b/test/post-install.ts new file mode 100644 index 0000000000..2df08117b8 --- /dev/null +++ b/test/post-install.ts @@ -0,0 +1,35 @@ +import { assert } from "chai"; + +// Use require instead of import in order to replace the `spawn` method of child_process +let childProcess = require("child_process"); + +import { SpawnOptions, ChildProcess } from "child_process"; +import * as path from "path"; +import { POST_INSTALL_COMMAND_NAME } from "../lib/constants"; + +describe("postinstall.js", () => { + it("calls post-install-cli command of CLI", () => { + const originalSpawn = childProcess.spawn; + let isSpawnCalled = false; + let argsPassedToSpawn: string[] = []; + childProcess.spawn = (command: string, args?: string[], options?: SpawnOptions): ChildProcess => { + isSpawnCalled = true; + argsPassedToSpawn = args; + + return null; + }; + + require(path.join(__dirname, "..", "postinstall")); + + childProcess.spawn = originalSpawn; + + assert.isTrue(isSpawnCalled, "child_process.spawn must be called from postinstall.js"); + + const expectedPathToCliExecutable = path.join(__dirname, "..", "bin", "tns"); + + assert.isTrue(argsPassedToSpawn.indexOf(expectedPathToCliExecutable) !== -1, `The spawned args must contain path to TNS. + Expected path is: ${expectedPathToCliExecutable}, current args are: ${argsPassedToSpawn}.`); + assert.isTrue(argsPassedToSpawn.indexOf(POST_INSTALL_COMMAND_NAME) !== -1, `The spawned args must contain the name of the post-install command. + Expected path is: ${expectedPathToCliExecutable}, current args are: ${argsPassedToSpawn}.`); + }); +}); diff --git a/test/services/subscription-service.ts b/test/services/subscription-service.ts new file mode 100644 index 0000000000..ba4e9df083 --- /dev/null +++ b/test/services/subscription-service.ts @@ -0,0 +1,286 @@ +import { Yok } from "../../lib/common/yok"; +import { assert } from "chai"; +import { SubscriptionService } from "../../lib/services/subscription-service"; +import { LoggerStub } from "../stubs"; +import { stringify } from "querystring"; +let helpers = require("../../lib/common/helpers"); + +interface IValidateTestData { + name: string; + valuePassedToValidate: string; + expectedResult: boolean | string; +}; + +const createTestInjector = (): IInjector => { + const testInjector = new Yok(); + testInjector.register("logger", LoggerStub); + + testInjector.register("userSettingsService", { + getSettingValue: async (value: string) => true, + saveSetting: async (key: string, value: any): Promise => undefined + }); + + testInjector.register("prompter", { + get: async (schemas: IPromptSchema[]): Promise => ({ + inputEmail: "SomeEmail" + }) + }); + + testInjector.register("httpClient", { + httpRequest: async (options: any, proxySettings?: IProxySettings): Promise => undefined + }); + + return testInjector; +}; + +class SubscriptionServiceTester extends SubscriptionService { + public shouldAskForEmailResult: boolean = null; + + constructor($httpClient: Server.IHttpClient, + $prompter: IPrompter, + $userSettingsService: IUserSettingsService, + $logger: ILogger) { + super($httpClient, $prompter, $userSettingsService, $logger); + } + + public async shouldAskForEmail(): Promise { + if (this.shouldAskForEmailResult !== null) { + return this.shouldAskForEmailResult; + } + + return super.shouldAskForEmail(); + } +} + +describe("subscriptionService", () => { + describe("shouldAskForEmail", () => { + describe("returns false", () => { + it("when terminal is not interactive", async () => { + const originalIsInteractive = helpers.isInteractive; + helpers.isInteractive = () => false; + + const testInjector = createTestInjector(); + const subscriptionService = testInjector.resolve(SubscriptionServiceTester); + const shouldAskForEmailResult = await subscriptionService.shouldAskForEmail(); + + helpers.isInteractive = originalIsInteractive; + + assert.isFalse(shouldAskForEmailResult, "When console is not interactive, we should not ask for email."); + }); + + it("when environment variable CLI_NOPROMPT is set to 1", async () => { + const originalIsInteractive = helpers.isInteractive; + helpers.isInteractive = () => true; + + const originalCliNoPrompt = process.env.CLI_NOPROMPT; + process.env.CLI_NOPROMPT = "1"; + + const testInjector = createTestInjector(); + const subscriptionService = testInjector.resolve(SubscriptionServiceTester); + const shouldAskForEmailResult = await subscriptionService.shouldAskForEmail(); + + helpers.isInteractive = originalIsInteractive; + process.env.CLI_NOPROMPT = originalCliNoPrompt; + + assert.isFalse(shouldAskForEmailResult, "When the environment variable CLI_NOPROMPT is set to 1, we should not ask for email."); + }); + + it("when user had already been asked for mail", async () => { + const originalIsInteractive = helpers.isInteractive; + helpers.isInteractive = () => true; + + const originalCliNoPrompt = process.env.CLI_NOPROMPT; + process.env.CLI_NOPROMPT = "random_value"; + + const testInjector = createTestInjector(); + const subscriptionService = testInjector.resolve(SubscriptionServiceTester); + const shouldAskForEmailResult = await subscriptionService.shouldAskForEmail(); + + helpers.isInteractive = originalIsInteractive; + process.env.CLI_NOPROMPT = originalCliNoPrompt; + + assert.isFalse(shouldAskForEmailResult, "When the user had already been asked for mail, we should not ask for email."); + }); + }); + + describe("returns true", () => { + it("when console is interactive, CLI_NOPROMPT is not 1 and we have not asked user before that", async () => { + const originalIsInteractive = helpers.isInteractive; + helpers.isInteractive = () => true; + + const originalCliNoPrompt = process.env.CLI_NOPROMPT; + process.env.CLI_NOPROMPT = "random_value"; + + const testInjector = createTestInjector(); + const userSettingsService = testInjector.resolve("userSettingsService"); + userSettingsService.getSettingValue = async (settingName: string): Promise => false; + + const subscriptionService = testInjector.resolve(SubscriptionServiceTester); + const shouldAskForEmailResult = await subscriptionService.shouldAskForEmail(); + + helpers.isInteractive = originalIsInteractive; + process.env.CLI_NOPROMPT = originalCliNoPrompt; + + assert.isTrue(shouldAskForEmailResult, "When the user had already been asked for mail, we should not ask for email."); + }); + }); + }); + + describe("subscribeForNewsletter", () => { + it("does nothing when shouldAskForEmail returns false", async () => { + const testInjector = createTestInjector(); + const subscriptionService = testInjector.resolve(SubscriptionServiceTester); + subscriptionService.shouldAskForEmailResult = false; + const logger = testInjector.resolve("logger"); + let loggerOutput = ""; + logger.out = (...args: string[]): void => { + loggerOutput += args.join(" "); + }; + + await subscriptionService.subscribeForNewsletter(); + assert.deepEqual(loggerOutput, ""); + }); + + it("shows message that asks for e-mail address", async () => { + const testInjector = createTestInjector(); + const subscriptionService = testInjector.resolve(SubscriptionServiceTester); + subscriptionService.shouldAskForEmailResult = true; + + const logger = testInjector.resolve("logger"); + let loggerOutput = ""; + + logger.out = (...args: string[]): void => { + loggerOutput += args.join(" "); + }; + + await subscriptionService.subscribeForNewsletter(); + + assert.equal(loggerOutput, "Leave your e-mail address here to subscribe for NativeScript newsletter and product updates, tips and tricks:"); + }); + + const expectedMessageInPrompter = "(press Enter for blank)"; + it(`calls prompter with specific message - ${expectedMessageInPrompter}`, async () => { + const testInjector = createTestInjector(); + const subscriptionService = testInjector.resolve(SubscriptionServiceTester); + subscriptionService.shouldAskForEmailResult = true; + const prompter = testInjector.resolve("prompter"); + let schemasPassedToPromter: IPromptSchema[] = null; + prompter.get = async (schemas: IPromptSchema[]): Promise => { + schemasPassedToPromter = schemas; + + return { inputEmail: "SomeEmail" }; + }; + + await subscriptionService.subscribeForNewsletter(); + + assert.isNotNull(schemasPassedToPromter, "Prompter should have been called."); + assert.equal(schemasPassedToPromter.length, 1, "A single schema should have been passed to schemas."); + + assert.equal(schemasPassedToPromter[0].message, expectedMessageInPrompter); + }); + + describe("calls prompter with validate method", () => { + const testData: IValidateTestData[] = [ + { + name: "returning true when empty string is passed", + valuePassedToValidate: "", + expectedResult: true + }, + { + name: "returning true when passing valid email", + valuePassedToValidate: "abc@def.gh", + expectedResult: true + }, + { + name: "returning specific message when invalid email is passed", + valuePassedToValidate: "abcdef.gh", + expectedResult: "Please provide a valid e-mail or simply leave it blank." + } + ]; + + _.each(testData, testCase => { + it(testCase.name, async () => { + const testInjector = createTestInjector(); + const subscriptionService = testInjector.resolve(SubscriptionServiceTester); + subscriptionService.shouldAskForEmailResult = true; + const prompter = testInjector.resolve("prompter"); + let schemasPassedToPromter: IPromptSchema[] = null; + prompter.get = async (schemas: IPromptSchema[]): Promise => { + schemasPassedToPromter = schemas; + return { inputEmail: "SomeEmail" }; + }; + + await subscriptionService.subscribeForNewsletter(); + + const schemaPassedToPromter = schemasPassedToPromter[0]; + const resultOfValidateMethod = schemaPassedToPromter.validate(testCase.valuePassedToValidate); + assert.equal(resultOfValidateMethod, testCase.expectedResult); + }); + }); + + }); + + const emailRegisteredKey = "EMAIL_REGISTERED"; + it(`persists ${emailRegisteredKey} setting with value true in user settings`, async () => { + const testInjector = createTestInjector(); + const subscriptionService = testInjector.resolve(SubscriptionServiceTester); + subscriptionService.shouldAskForEmailResult = true; + const userSettingsService = testInjector.resolve("userSettingsService"); + let keyPassedToSaveSetting: string = null; + let valuePassedToSaveSetting: boolean = null; + userSettingsService.saveSetting = async (key: string, value: any): Promise => { + keyPassedToSaveSetting = key; + valuePassedToSaveSetting = value; + }; + + await subscriptionService.subscribeForNewsletter(); + + assert.deepEqual(keyPassedToSaveSetting, emailRegisteredKey); + assert.deepEqual(valuePassedToSaveSetting, true); + }); + + it("calls httpRequest with concrete data", async () => { + const email = "abc@def.gh"; + + const postData = stringify({ + 'elqFormName': "dev_uins_cli", + 'elqSiteID': '1325', + 'emailAddress': email, + 'elqCookieWrite': '0' + }); + + const expectedOptions = { + url: 'https://s1325.t.eloqua.com/e/f2', + method: 'POST', + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + 'Content-Length': postData.length + }, + body: postData + }; + + const testInjector = createTestInjector(); + + const prompter = testInjector.resolve("prompter"); + let schemasPassedToPromter: IPromptSchema[] = null; + prompter.get = async (schemas: IPromptSchema[]): Promise => { + schemasPassedToPromter = schemas; + return { inputEmail: email }; + }; + + const httpClient = testInjector.resolve("httpClient"); + let optionsPassedToHttpRequest: any = null; + httpClient.httpRequest = async (options: any, proxySettings?: IProxySettings): Promise => { + optionsPassedToHttpRequest = options; + return null; + }; + + const subscriptionService = testInjector.resolve(SubscriptionServiceTester); + subscriptionService.shouldAskForEmailResult = true; + + await subscriptionService.subscribeForNewsletter(); + + assert.deepEqual(optionsPassedToHttpRequest, expectedOptions); + }); + }); +}); From 6c089b25fdd78dae875da010995288db816f6dd4 Mon Sep 17 00:00:00 2001 From: rosen-vladimirov Date: Fri, 23 Jun 2017 18:32:29 +0300 Subject: [PATCH 3/6] Update .travis.yml --- .travis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index 26b0021abb..30a1f019ab 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,6 +8,8 @@ node_js: - '6' git: submodules: true +install: +- npm install --ignore-scripts before_script: - gem install xcodeproj - gem install cocoapods From e5ba743082d2bb4f24882030eddc2bd090e8f3eb Mon Sep 17 00:00:00 2001 From: rosen-vladimirov Date: Mon, 26 Jun 2017 08:54:26 +0300 Subject: [PATCH 4/6] Update ios-device-lib to 0.4.7 Update ios-device-lib to 0.4.7, which will fix livesync of `.css` files on iOS Device after application has been restarted. --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index ed70bb2d90..4166b8cdee 100644 --- a/package.json +++ b/package.json @@ -42,7 +42,7 @@ "glob": "^7.0.3", "iconv-lite": "0.4.11", "inquirer": "0.9.0", - "ios-device-lib": "0.4.6", + "ios-device-lib": "0.4.7", "ios-mobileprovision-finder": "1.0.9", "ios-sim-portable": "~3.0.0", "lockfile": "1.0.1", From b525faaa005a54c8fd4d57d684ce59f5ae6b65a6 Mon Sep 17 00:00:00 2001 From: rosen-vladimirov Date: Mon, 26 Jun 2017 12:03:22 +0300 Subject: [PATCH 5/6] Update to latest common lib --- lib/common | 2 +- test/services/subscription-service.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/common b/lib/common index 2a6d178e57..d5e8675ed3 160000 --- a/lib/common +++ b/lib/common @@ -1 +1 @@ -Subproject commit 2a6d178e5722486e03c70ea721f1be512952f102 +Subproject commit d5e8675ed30da6f096643ff1aac4c6d2ec18b46f diff --git a/test/services/subscription-service.ts b/test/services/subscription-service.ts index ba4e9df083..da01584f13 100644 --- a/test/services/subscription-service.ts +++ b/test/services/subscription-service.ts @@ -121,7 +121,7 @@ describe("subscriptionService", () => { helpers.isInteractive = originalIsInteractive; process.env.CLI_NOPROMPT = originalCliNoPrompt; - assert.isTrue(shouldAskForEmailResult, "When the user had already been asked for mail, we should not ask for email."); + assert.isTrue(shouldAskForEmailResult, "We should ask the user for email when console is interactiv, CLI_NOPROMPT is not 1 and we have never asked the user before."); }); }); }); From ca2e5dec3394bfefc90d0b8b38fb95168690ed8b Mon Sep 17 00:00:00 2001 From: rosen-vladimirov Date: Mon, 26 Jun 2017 12:07:41 +0300 Subject: [PATCH 6/6] Set version to 3.1.1 and prepare CHANGELOG --- CHANGELOG.md | 41 +++++++++++++++++++++++++---------------- package.json | 2 +- 2 files changed, 26 insertions(+), 17 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f72a4fa158..2a994e9ea7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,14 @@ NativeScript CLI Changelog ================ +3.1.1 (2017, June 28) +== + +### Fixed +* [Fixed #2879](https://github.com/NativeScript/nativescript-cli/issues/2879): Livesync does not apply changes in CSS files on physical iOS devices +* [Fixed #2892](https://github.com/NativeScript/nativescript-cli/issues/2892): Not copying the CFBundleURLTypes from the plist file to the project +* [Fixed #2916](https://github.com/NativeScript/nativescript-cli/issues/2916): If no device or emulator is attached `tns debug android` kills the commandline process and doesn't start an emulator +* [Fixed #2923](https://github.com/NativeScript/nativescript-cli/issues/2923): Fix asking for user email on postinstall + 3.1.0 (2017, June 22) == @@ -66,7 +75,7 @@ NativeScript CLI Changelog * [Fixed #2661](https://github.com/NativeScript/nativescript-cli/issues/2661): Adding new files during livesync doesn't succeed on iOS Devices * [Fixed #2650](https://github.com/NativeScript/nativescript-cli/issues/2650): Release Build Android error: gradlew.bat failed with exit code 1 When Path contains Space * [Fixed #2125](https://github.com/NativeScript/nativescript-cli/issues/2125): NativeScript setup script fails on Mac -* [Fixed #2697](https://github.com/NativeScript/nativescript-cli/issues/2697): App_Resources being copied into app RAW +* [Fixed #2697](https://github.com/NativeScript/nativescript-cli/issues/2697): App_Resources being copied into app RAW 3.0.0-RC.1 (2017, March 29) == @@ -76,19 +85,19 @@ NativeScript CLI Changelog * [Implemented #2170](https://github.com/NativeScript/nativescript-cli/issues/2170): CLI should report adb install errors * [Implemented #2204](https://github.com/NativeScript/nativescript-cli/issues/2204): Remove fibers from CLI and use async/await * [Implemented #2349](https://github.com/NativeScript/nativescript-cli/issues/2349): Command "emulate" and options "--emulator/--device/--avd" are a bit confusing to use -* [Implemented #2513](https://github.com/NativeScript/nativescript-cli/issues/2513): Allow templates to omit App_Resources +* [Implemented #2513](https://github.com/NativeScript/nativescript-cli/issues/2513): Allow templates to omit App_Resources * [Implemented #2633](https://github.com/NativeScript/nativescript-cli/issues/2633): Deprecate `tns livesync` command ### Fixed -* [Fixed #2225](https://github.com/NativeScript/nativescript-cli/issues/2225): The tns debug ios command hangs on launch screen +* [Fixed #2225](https://github.com/NativeScript/nativescript-cli/issues/2225): The tns debug ios command hangs on launch screen * [Fixed #2357](https://github.com/NativeScript/nativescript-cli/issues/2357): --copy-to option is broken * [Fixed #2446](https://github.com/NativeScript/nativescript-cli/issues/2446): tns emulate --device NonexistentName retunrs different messages for ios and android * [Fixed #2486](https://github.com/NativeScript/nativescript-cli/issues/2486): tns run android (without started emulator/connected device) fails to start app * [Fixed #2487](https://github.com/NativeScript/nativescript-cli/issues/2487): Exception: The plugin tns-android@2.5.0 is already installed * [Fixed #2496](https://github.com/NativeScript/nativescript-cli/issues/2496): `tns platform clean android` does not maintain the same version of the runtimes * [Fixed #2511](https://github.com/NativeScript/nativescript-cli/issues/2511): Second run of `tns run android --release` does not respect changes in application code -* [Fixed #2557](https://github.com/NativeScript/nativescript-cli/issues/2557): 2.5.1 iOS incremental build generates inconsistent binary +* [Fixed #2557](https://github.com/NativeScript/nativescript-cli/issues/2557): 2.5.1 iOS incremental build generates inconsistent binary * [Fixed #2559](https://github.com/NativeScript/nativescript-cli/issues/2559): `tns init` fails, `ins init --force` produce invalid app * [Fixed #2560](https://github.com/NativeScript/nativescript-cli/issues/2560): `tns run` should do full prepare/rebuild if something in App_Resources is changes * [Fixed #2561](https://github.com/NativeScript/nativescript-cli/issues/2561): Fix prepare process terminates if passing too many arguments to a new node process @@ -116,8 +125,8 @@ NativeScript CLI Changelog ### Fixed * [Fixed #2476](https://github.com/NativeScript/nativescript-cli/issues/2476): `tns run ios` unable to sync files on iOS Simulator -* [Fixed #2491](https://github.com/NativeScript/nativescript-cli/issues/2491): "ERROR Error: Could not find module" after 2.5 upgrade -* [Fixed #2472](https://github.com/NativeScript/nativescript-cli/issues/2472): Livesync watches .DS_Store files +* [Fixed #2491](https://github.com/NativeScript/nativescript-cli/issues/2491): "ERROR Error: Could not find module" after 2.5 upgrade +* [Fixed #2472](https://github.com/NativeScript/nativescript-cli/issues/2472): Livesync watches .DS_Store files * [Fixed #2469](https://github.com/NativeScript/nativescript-cli/issues/2469): `tns run` can get stuck in a loop since 2.5 * [Fixed #2512](https://github.com/NativeScript/nativescript-cli/issues/2512): Run should not watch hidden files * [Fixed #2521](https://github.com/NativeScript/nativescript-cli/issues/2521): Enable requesting user input during plugin installation @@ -130,7 +139,7 @@ NativeScript CLI Changelog * [Implemented #2276](https://github.com/NativeScript/nativescript-cli/issues/2276): Support plugin development when using the watch option * [Implemented #2260]( https://github.com/NativeScript/nativescript-cli/issues/2260): Deprecate support for Node.js 4.x feature * [Implemented #2112]( https://github.com/NativeScript/nativescript-cli/issues/2112): Update webpack plugin to run as a npm script feature -* [Implemented #1906]( https://github.com/NativeScript/nativescript-cli/issues/1906): TNS Doctor Android tools detection feature +* [Implemented #1906]( https://github.com/NativeScript/nativescript-cli/issues/1906): TNS Doctor Android tools detection feature * [Implemented #1845](https://github.com/NativeScript/nativescript-cli/issues/1845): Remove NPM as a dependency, use the NPM installed on users' machine feature ### Fixed @@ -138,7 +147,7 @@ NativeScript CLI Changelog **Install and setup issues** * [Fixed #2302](https://github.com/NativeScript/nativescript-cli/issues/2302): App runs in Xcode and CLI but not on test flight -* [Fixed #1922](https://github.com/NativeScript/nativescript-cli/issues/1922): TNS doctor does not detect if JDK is not installed and throws an error +* [Fixed #1922](https://github.com/NativeScript/nativescript-cli/issues/1922): TNS doctor does not detect if JDK is not installed and throws an error * [Fixed #2312](https://github.com/NativeScript/nativescript-cli/issues/2312): Creating app w/ nativescript@next is not deploying App_Resources folder * [Fixed #2308](https://github.com/NativeScript/nativescript-cli/issues/2308): Using nativescript@next brings multiple libraries into node_modules * [Fixed #2301](https://github.com/NativeScript/nativescript-cli/issues/2301): Rework logic of handling 2 package.json files after tns create @@ -149,8 +158,8 @@ NativeScript CLI Changelog * [Fixed #2213](https://github.com/NativeScript/nativescript-cli/issues/2213): When switching build configurations plugin platform files are copied into assets * [Fixed #2177](https://github.com/NativeScript/nativescript-cli/issues/2177): Prepare does not flatten scoped dependencies -* [Fixed #2150](https://github.com/NativeScript/nativescript-cli/issues/2150): TNS run command broken with using --watch -* [Fixed #1740](https://github.com/NativeScript/nativescript-cli/issues/1740): Dev Dependencies (like Gulp, etc) getting built and build is failing because of which Gulp * [Fixed #](): integration is not working currently. +* [Fixed #2150](https://github.com/NativeScript/nativescript-cli/issues/2150): TNS run command broken with using --watch +* [Fixed #1740](https://github.com/NativeScript/nativescript-cli/issues/1740): Dev Dependencies (like Gulp, etc) getting built and build is failing because of which Gulp * [Fixed #](): integration is not working currently. * [Fixed #2270](https://github.com/NativeScript/nativescript-cli/issues/2270): App is not rebuilt after removing plugin with native dependencies bug * [Fixed #2253](https://github.com/NativeScript/nativescript-cli/issues/2253): Prepare command with bundle option doesn't copy files @@ -163,7 +172,7 @@ NativeScript CLI Changelog **Emulate/ Device issues** -* [Fixed #1522](https://github.com/NativeScript/nativescript-cli/issues/1522): Cannot specify emulator device while debugging +* [Fixed #1522](https://github.com/NativeScript/nativescript-cli/issues/1522): Cannot specify emulator device while debugging * [Fixed #2345](https://github.com/NativeScript/nativescript-cli/issues/2345): Option --device {DeviceName} not working for emulate/run/debug/deploy bug * [Fixed #2344](https://github.com/NativeScript/nativescript-cli/issues/2344): Emulate command not working for iOS @@ -186,18 +195,18 @@ NativeScript CLI Changelog * [Fixed #2228](https://github.com/NativeScript/nativescript-cli/issues/2228): Homebrew as root is no longer supported * [Fixed #2227]( https://github.com/NativeScript/nativescript-cli/issues/2227): Remove use of lib/iOS folder for native plugins * [Fixed #282]( https://github.com/NativeScript/nativescript-cli/issues/282): "tns platform add android --path TNSApp --symlink" does not work on Windows -* [Fixed #1802](https://github.com/NativeScript/nativescript-cli/issues/1802): semver copied to platforms/android even though it's a dev dependency +* [Fixed #1802](https://github.com/NativeScript/nativescript-cli/issues/1802): semver copied to platforms/android even though it's a dev dependency 2.4.2 (2016, December 8) == ### Fixed -* [Fixed #2332](https://github.com/NativeScript/nativescript-cli/pull/2332): Fixed email registration process +* [Fixed #2332](https://github.com/NativeScript/nativescript-cli/pull/2332): Fixed email registration process 2.4.1 (2016, December 4) == ### Fixed -* [Fixed #2200](https://github.com/NativeScript/nativescript-cli/pull/2200): TypeScript files don't show in {N} debugger. -* [Fixed #2273](https://github.com/NativeScript/nativescript-cli/pull/2273): Livesync should continue to work after app crash +* [Fixed #2200](https://github.com/NativeScript/nativescript-cli/pull/2200): TypeScript files don't show in {N} debugger. +* [Fixed #2273](https://github.com/NativeScript/nativescript-cli/pull/2273): Livesync should continue to work after app crash 2.4.0 (2016, November 16) == @@ -260,7 +269,7 @@ NativeScript CLI Changelog ### New * [Implemented #1959](https://github.com/NativeScript/nativescript-cli/issues/1959): XCode8/iOS10 support -* [Implemented #1948](https://github.com/NativeScript/nativescript-cli/issues/1948): npm WARN deprecated minimatch@0.2.14: Please update to minimatch 3.0.2 or higher to avoid a RegExp DoS issue +* [Implemented #1948](https://github.com/NativeScript/nativescript-cli/issues/1948): npm WARN deprecated minimatch@0.2.14: Please update to minimatch 3.0.2 or higher to avoid a RegExp DoS issue * [Implemented #1944](https://github.com/NativeScript/nativescript-cli/issues/1944): Enhancement: tns plugin INSTALL alias * [Implemented #1565](https://github.com/NativeScript/nativescript-cli/issues/1565): Livesync debugging support * [Implemented #526](https://github.com/NativeScript/nativescript-cli/issues/526): Update plugin command diff --git a/package.json b/package.json index 4166b8cdee..44623ea456 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "nativescript", "preferGlobal": true, - "version": "3.1.0", + "version": "3.1.1", "author": "Telerik ", "description": "Command-line interface for building NativeScript projects", "bin": {