Skip to content

Release 5.0.1 #4089

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 26 commits into from
Nov 3, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
6ba68be
fix(preview): skip check if local plugin version is invalid
sis0k0 Oct 19, 2018
6fd316a
fix: remove persisted emulator's data on deviceLost event
Fatme Oct 24, 2018
1d12b64
fix: doesn't await for AppLaunching notification when CLI retries to …
Fatme Oct 19, 2018
4565404
fix: don't show "TypeError: Invalid Version: null" error in sidekick …
Fatme Oct 24, 2018
ef91626
refactor: move the private method after the public methods
Fatme Oct 24, 2018
b332669
fix: stop making a full rebuild on livesync when the --clean flag is set
DimitarTachev Oct 24, 2018
1ab8e0b
fix: validate params passed to preview command
Fatme Oct 24, 2018
a3320f0
fix: improve the message when not able to start an emulator so it can…
Fatme Oct 25, 2018
7cefe21
fix: update an old Xcode warning as now its applicable for all suppor…
DimitarTachev Oct 26, 2018
77785d3
fix: reset errors when fallback to list avds from directory
Fatme Oct 29, 2018
5761f74
fix: show correct messages on `tns test init` command
Fatme Oct 29, 2018
4f67566
fix: fix unit tests
Fatme Oct 30, 2018
75b777d
refactor: move the private method after the public
Fatme Oct 25, 2018
2bfae7c
refactor: extract preview sync hook to separate method
Fatme Oct 25, 2018
f47f81e
feat(preview): add api for deviceFound and deviceLost for preview dev…
Fatme Nov 1, 2018
ef016cf
test(preview): add unit tests for previewDevicesService
Fatme Nov 1, 2018
2ab6781
fix(preview-unit-tests): inject previewDevicesService in order to fix…
Fatme Nov 1, 2018
fcd6c4c
chore(preview): handle PR comments
Fatme Nov 1, 2018
7d78af9
fix(unit-testing): add correct files pattern in karma.conf.js when th…
Fatme Nov 1, 2018
e6b7968
fix(debug-ios): start log process on `tns debug ios --justlaunch` com…
Fatme Oct 29, 2018
bb04c99
refactor(preview): rename playgroundQrCodeGenerator to previewQrCodeS…
Fatme Nov 2, 2018
8d55d27
refactor(preview): rename method generateQrCode to printLiveSyncQrCode
Fatme Nov 2, 2018
7ad0018
feat(preview-api): expose public method for getting qr code of playgr…
Fatme Nov 2, 2018
bd66302
refactor(preview): rename IGenerateQrCodeOptions to IPrintLiveSyncOpt…
Fatme Nov 2, 2018
59f2ed3
fix: install the latest compatible v2 templates in stead of the lates…
DimitarTachev Nov 2, 2018
2e45034
fix: fix: install the latest compatible v2 templates in stead of the …
DimitarTachev Nov 2, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion lib/bootstrap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,8 @@ $injector.require("usbLiveSyncService", "./services/livesync/livesync-service");
$injector.require("previewAppLiveSyncService", "./services/livesync/playground/preview-app-livesync-service");
$injector.require("previewAppPluginsService", "./services/livesync/playground/preview-app-plugins-service");
$injector.require("previewSdkService", "./services/livesync/playground/preview-sdk-service");
$injector.require("playgroundQrCodeGenerator", "./services/livesync/playground/qr-code-generator");
$injector.requirePublicClass("previewDevicesService", "./services/livesync/playground/devices/preview-devices-service");
$injector.requirePublic("previewQrCodeService", "./services/livesync/playground/preview-qr-code-service");
$injector.requirePublic("sysInfo", "./sys-info");

$injector.require("iOSNotificationService", "./services/ios-notification-service");
Expand Down
9 changes: 7 additions & 2 deletions lib/commands/preview.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@ export class PreviewCommand implements ICommand {
private static MIN_SUPPORTED_WEBPACK_VERSION = "0.17.0";

constructor(private $bundleValidatorHelper: IBundleValidatorHelper,
private $errors: IErrors,
private $liveSyncService: ILiveSyncService,
private $networkConnectivityValidator: INetworkConnectivityValidator,
private $projectData: IProjectData,
private $options: IOptions,
private $playgroundQrCodeGenerator: IPlaygroundQrCodeGenerator) { }
private $previewQrCodeService: IPreviewQrCodeService) { }

public async execute(): Promise<void> {
await this.$liveSyncService.liveSync([], {
Expand All @@ -23,10 +24,14 @@ export class PreviewCommand implements ICommand {
useHotModuleReload: this.$options.hmr
});

await this.$playgroundQrCodeGenerator.generateQrCode({ useHotModuleReload: this.$options.hmr, link: this.$options.link });
await this.$previewQrCodeService.printLiveSyncQrCode({ useHotModuleReload: this.$options.hmr, link: this.$options.link });
}

public async canExecute(args: string[]): Promise<boolean> {
if (args && args.length) {
this.$errors.fail(`The arguments '${args.join(" ")}' are not valid for the preview command.`);
}

await this.$networkConnectivityValidator.validate();
this.$bundleValidatorHelper.validate(PreviewCommand.MIN_SUPPORTED_WEBPACK_VERSION);
return true;
Expand Down
10 changes: 6 additions & 4 deletions lib/commands/test-init.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,9 +93,10 @@ class TestInitCommand implements ICommand {
await this.$pluginsService.add('nativescript-unit-test-runner', this.$projectData);

const testsDir = path.join(this.$projectData.appDirectoryPath, 'tests');
const relativeTestsDir = path.relative(this.$projectData.projectDir, testsDir);
let shouldCreateSampleTests = true;
if (this.$fs.exists(testsDir)) {
this.$logger.info('app/tests/ directory already exists, will not create an example test project.');
this.$logger.info(`${relativeTestsDir} directory already exists, will not create an example test project.`);
shouldCreateSampleTests = false;
}

Expand All @@ -104,18 +105,19 @@ class TestInitCommand implements ICommand {
const frameworks = [frameworkToInstall].concat(this.karmaConfigAdditionalFrameworks[frameworkToInstall] || [])
.map(fw => `'${fw}'`)
.join(', ');
const testFiles = `'${relativeTestsDir}/**/*.js'`;
const karmaConfTemplate = this.$resources.readText('test/karma.conf.js');
const karmaConf = _.template(karmaConfTemplate)({ frameworks });
const karmaConf = _.template(karmaConfTemplate)({ frameworks, testFiles });

this.$fs.writeFile(path.join(projectDir, 'karma.conf.js'), karmaConf);

const exampleFilePath = this.$resources.resolvePath(`test/example.${frameworkToInstall}.js`);

if (shouldCreateSampleTests && this.$fs.exists(exampleFilePath)) {
this.$fs.copyFile(exampleFilePath, path.join(testsDir, 'example.js'));
this.$logger.info('\nExample test file created in app/tests/'.yellow);
this.$logger.info(`\nExample test file created in ${relativeTestsDir}`.yellow);
} else {
this.$logger.info('\nPlace your test files under app/tests/'.yellow);
this.$logger.info(`\nPlace your test files under ${relativeTestsDir}`.yellow);
}

this.$logger.info('Run your tests using the "$ tns test <platform>" command.'.yellow);
Expand Down
2 changes: 1 addition & 1 deletion lib/common/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -155,5 +155,5 @@ export class AndroidVirtualDevice {
static TIMEOUT_SECONDS = 120;
static GENYMOTION_DEFAULT_STDERR_STRING = "Logging activities to file";

static UNABLE_TO_START_EMULATOR_MESSAGE = "Cannot run your app in the native emulator. Increase the timeout of the operation with the --timeout option or try to restart your adb server with 'adb kill-server' command. Alternatively, run the Android Virtual Device manager and increase the allocated RAM for the virtual device.";
static UNABLE_TO_START_EMULATOR_MESSAGE = "Cannot run the app in the selected native emulator. Try to restart the adb server by running the `adb kill-server` command in the Command Prompt, or increase the allocated RAM of the virtual device through the Android Virtual Device manager. NativeScript CLI users can try to increase the timeout of the operation by adding the `--timeout` flag.";
}
15 changes: 15 additions & 0 deletions lib/common/declarations.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -969,6 +969,21 @@ interface IQrCodeGenerator {
generateDataUri(data: string): Promise<string>;
}

interface IQrCodeImageData {
/**
* The original URL used for generating QR code image.
*/
originalUrl: string;
/**
* The shorten URL used for generating QR code image.
*/
shortenUrl: string;
/**
* Base64 encoded data used for generating QR code image.
*/
imageData: string;
}

interface IDynamicHelpProvider {
/**
* Checks if current project's framework is one of the specified as arguments.
Expand Down
28 changes: 23 additions & 5 deletions lib/common/definitions/mobile.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -143,10 +143,6 @@ declare module Mobile {
--predicate 'eventType == logEvent and subsystem contains "com.example.my_subsystem"'
*/
predicate?: string;
/**
* If set to true, device's log will not be displayed on the console.
*/
muted?: boolean;
}

interface IDeviceAppData extends IPlatform, IConnectTimeoutOption {
Expand Down Expand Up @@ -221,12 +217,18 @@ declare module Mobile {
* @param {string} projectName The project name of the currently running application for which we need the logs.
*/
setProjectNameForDevice(deviceIdentifier: string, projectName: string): void;

/**
* Disables logs on the specified device and does not print any logs on the console.
* @param {string} deviceIdentifier The unique identifier of the device.
*/
muteLogsForDevice(deviceIdentifier: string): void;
}

/**
* Describes different options for filtering device logs.
*/
interface IDeviceLogOptions extends IStringDictionary {
interface IDeviceLogOptions extends IDictionary<string | boolean> {
/**
* Process id of the application on the device.
*/
Expand All @@ -241,6 +243,11 @@ declare module Mobile {
* The project name.
*/
projectName?: string;

/**
* Specifies if the logs will be printed on the console.
*/
muteLogs?: boolean;
}

/**
Expand Down Expand Up @@ -730,6 +737,12 @@ declare module Mobile {
* @returns {Promise<IStartEmulatorOutput>} Starts the emulator and returns the errors if some error occurs.
*/
startEmulator(options: Mobile.IStartEmulatorOptions): Promise<IStartEmulatorOutput>;

/**
* Called when emulator is lost. Its purpose is to clean any resources used by the instance.
* @returns {void}
*/
detach?(deviceInfo: Mobile.IDeviceInfo): void;
}

interface IStartEmulatorOutput {
Expand Down Expand Up @@ -772,6 +785,11 @@ declare module Mobile {
* @param imageIdentifier - The imagerIdentifier of the emulator.
*/
startEmulatorArgs(imageIdentifier: string): string[];
/**
* Called when emulator is lost. Its purpose is to clean any resources used by the instance.
* @returns {void}
*/
detach?(deviceInfo: Mobile.IDeviceInfo): void;
}

interface IVirtualBoxService {
Expand Down
6 changes: 6 additions & 0 deletions lib/common/mobile/android/android-device.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,12 @@ export class AndroidDevice implements Mobile.IAndroidDevice {
}
}

public detach(): void {
if (this.isEmulator) {
this.$androidEmulatorServices.detach(this.deviceInfo);
}
}

private async getDeviceDetails(shellCommandArgs: string[]): Promise<IAndroidDeviceDetails> {
const parsedDetails: any = {};

Expand Down
4 changes: 4 additions & 0 deletions lib/common/mobile/android/android-emulator-services.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,10 @@ export class AndroidEmulatorServices implements Mobile.IEmulatorPlatformService
};
}

public detach(deviceInfo: Mobile.IDeviceInfo) {
this.$androidVirtualDeviceService.detach(deviceInfo);
}

private async startEmulatorCore(options: Mobile.IAndroidStartEmulatorOptions): Promise<{runningEmulator: Mobile.IDeviceInfo, errors: string[], endTimeEpoch: number}> {
const timeout = options.timeout || AndroidVirtualDevice.TIMEOUT_SECONDS;
const endTimeEpoch = getCurrentEpochTime() + this.$utils.getMilliSecondsTimeout(timeout);
Expand Down
10 changes: 9 additions & 1 deletion lib/common/mobile/android/android-virtual-device-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -142,9 +142,16 @@ export class AndroidVirtualDeviceService implements Mobile.IAndroidVirtualDevice
});
}

public detach(deviceInfo: Mobile.IDeviceInfo) {
if (this.mapEmulatorIdToImageIdentifier[deviceInfo.identifier]) {
delete this.mapEmulatorIdToImageIdentifier[deviceInfo.identifier];
}
}

private async getEmulatorImagesCore(): Promise<Mobile.IEmulatorImagesOutput> {
let result: ISpawnResult = null;
let devices: Mobile.IDeviceInfo[] = [];
let errors: string[] = [];

if (this.pathToAvdManagerExecutable && this.$fs.exists(this.pathToAvdManagerExecutable)) {
result = await this.$childProcess.trySpawnFromCloseEvent(this.pathToAvdManagerExecutable, ["list", "avds"]);
Expand All @@ -154,11 +161,12 @@ export class AndroidVirtualDeviceService implements Mobile.IAndroidVirtualDevice

if (result && result.stdout) {
devices = this.parseListAvdsOutput(result.stdout);
errors = result && result.stderr ? [result.stderr] : [];
} else {
devices = this.listAvdsFromDirectory();
}

return { devices, errors: result && result.stderr ? [result.stderr] : [] };
return { devices, errors };
}

private async getRunningEmulatorData(runningEmulatorId: string, availableEmulators: Mobile.IDeviceInfo[]): Promise<Mobile.IDeviceInfo> {
Expand Down
28 changes: 14 additions & 14 deletions lib/common/mobile/android/logcat-helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,20 +58,6 @@ export class LogcatHelper implements Mobile.ILogcatHelper {
}
}

private async getLogcatStream(deviceIdentifier: string, pid?: string) {
const device = await this.$devicesService.getDevice(deviceIdentifier);
const minAndroidWithLogcatPidSupport = "7.0.0";
const isLogcatPidSupported = semver.gte(semver.coerce(device.deviceInfo.version), minAndroidWithLogcatPidSupport);
const adb: Mobile.IDeviceAndroidDebugBridge = this.$injector.resolve(DeviceAndroidDebugBridge, { identifier: deviceIdentifier });
const logcatCommand = ["logcat"];

if (pid && isLogcatPidSupported) {
logcatCommand.push(`--pid=${pid}`);
}
const logcatStream = await adb.executeCommand(logcatCommand, { returnChildProcess: true });
return logcatStream;
}

public async dump(deviceIdentifier: string): Promise<void> {
const adb: Mobile.IDeviceAndroidDebugBridge = this.$injector.resolve(DeviceAndroidDebugBridge, { identifier: deviceIdentifier });
const logcatDumpStream = await adb.executeCommand(["logcat", "-d"], { returnChildProcess: true });
Expand Down Expand Up @@ -101,6 +87,20 @@ export class LogcatHelper implements Mobile.ILogcatHelper {
delete this.mapDevicesLoggingData[deviceIdentifier];
}
}

private async getLogcatStream(deviceIdentifier: string, pid?: string) {
const device = await this.$devicesService.getDevice(deviceIdentifier);
const minAndroidWithLogcatPidSupport = "7.0.0";
const isLogcatPidSupported = !!device.deviceInfo.version && semver.gte(semver.coerce(device.deviceInfo.version), minAndroidWithLogcatPidSupport);
const adb: Mobile.IDeviceAndroidDebugBridge = this.$injector.resolve(DeviceAndroidDebugBridge, { identifier: deviceIdentifier });
const logcatCommand = ["logcat"];

if (pid && isLogcatPidSupported) {
logcatCommand.push(`--pid=${pid}`);
}
const logcatStream = await adb.executeCommand(logcatCommand, { returnChildProcess: true });
return logcatStream;
}
}

$injector.register("logcatHelper", LogcatHelper);
6 changes: 5 additions & 1 deletion lib/common/mobile/device-log-provider-base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ export abstract class DeviceLogProviderBase extends EventEmitter implements Mobi
this.setLogLevel(logLevel, deviceIdentifier);
}

public muteLogsForDevice(deviceIdentifier: string): void {
this.setDeviceLogOptionsProperty(deviceIdentifier, (deviceLogOptions: Mobile.IDeviceLogOptions) => deviceLogOptions.muteLogs, true);
}

protected getApplicationPidForDevice(deviceIdentifier: string): string {
return this.devicesLogOptions[deviceIdentifier] && this.devicesLogOptions[deviceIdentifier].applicationPid;
}
Expand All @@ -39,7 +43,7 @@ export abstract class DeviceLogProviderBase extends EventEmitter implements Mobi
return this.devicesLogOptions[deviceIdentifier];
}

protected setDeviceLogOptionsProperty(deviceIdentifier: string, propNameFunction: Function, propertyValue: string): void {
protected setDeviceLogOptionsProperty(deviceIdentifier: string, propNameFunction: Function, propertyValue: string | boolean): void {
const propertyName = getPropertyName(propNameFunction);

if (propertyName) {
Expand Down
8 changes: 7 additions & 1 deletion lib/common/mobile/device-log-provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,19 @@ export class DeviceLogProvider extends DeviceLogProviderBase {
const loggingOptions = this.getDeviceLogOptionsForDevice(deviceIdentifier);
const data = this.$logFilter.filterData(platform, lineText, loggingOptions);
if (data) {
this.$logger.write(data);
this.logDataCore(data, loggingOptions);
this.emit(DEVICE_LOG_EVENT_NAME, lineText, deviceIdentifier, platform);
}
}

public setLogLevel(logLevel: string, deviceIdentifier?: string): void {
this.$logFilter.loggingLevel = logLevel.toUpperCase();
}

private logDataCore(data: string, loggingOptions: Mobile.IDeviceLogOptions): void {
if (!loggingOptions || (loggingOptions && !loggingOptions.muteLogs)) {
this.$logger.write(data);
}
}
}
$injector.register("deviceLogProvider", DeviceLogProvider);
Original file line number Diff line number Diff line change
Expand Up @@ -176,14 +176,13 @@ describe("androidVirtualDeviceService", () => {
assert.deepEqual(result.devices, []);
assert.deepEqual(result.errors, []);
});
it("should return an empty array when `avdmanager list avds` command fails", async () => {
it("should return an empty array and no errors when `avdmanager list avds` command fails", async () => {
const avdManagerError = "some error while executing avdmanager list avds";
const avdService = mockAvdService({ avdManagerError });
const result = await avdService.getEmulatorImages([]);
assert.lengthOf(result.devices, 0);
assert.deepEqual(result.devices, []);
assert.lengthOf(result.errors, 1);
assert.deepEqual(result.errors, [avdManagerError]);
assert.lengthOf(result.errors, 0);
});
it("should return all emulators when there are available emulators and no running emulators", async () => {
const avdService = mockAvdService({
Expand Down Expand Up @@ -214,6 +213,24 @@ describe("androidVirtualDeviceService", () => {
assert.deepEqual(result[1], getAvailableEmulatorData({ displayName: "Nexus_5X_API_28", imageIdentifier: "Nexus_5X_API_28", version: "9.0.0", model: "Nexus 5X" }));
assert.deepEqual(result[2], getAvailableEmulatorData({ displayName: "Nexus_6P_API_28", imageIdentifier: "Nexus_6P_API_28", version: "9.0.0", model: "Nexus 6P" }));
});
// In this case we should fallback to list avd directory and should't report errors from avdmanager
it("should return devices and no errors when there is an error on avdmanager's stderr", async () => {
const iniFilesData = getIniFilesData();
const testInjector = createTestInjector({
avdManagerOutput: "",
avdManagerError: "my test error",
iniFilesData
});

const fs = testInjector.resolve("fs");
fs.readDirectory = () => _.keys(iniFilesData);

const avdService = testInjector.resolve("androidVirtualDeviceService");
const result = await avdService.getEmulatorImages(["emulator-5554 device"]);

assert.deepEqual(result.devices.length, 3);
assert.deepEqual(result.errors.length, 0);
});
});

describe("when avdmanager is not found", () => {
Expand Down
2 changes: 2 additions & 0 deletions lib/common/test/unit-tests/stubs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -171,4 +171,6 @@ export class DeviceLogProviderStub extends EventEmitter implements Mobile.IDevic
setProjectNameForDevice(deviceIdentifier: string, projectName: string): void {
this.currentDeviceProjectNames[deviceIdentifier] = projectName;
}

muteLogsForDevice(deviceIdentifier: string): void { }
}
2 changes: 1 addition & 1 deletion lib/declarations.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -709,7 +709,7 @@ interface IiOSNotification extends NodeJS.EventEmitter {
}

interface IiOSSocketRequestExecutor {
executeLaunchRequest(deviceIdentifier: string, timeout: number, readyForAttachTimeout: number, projectId: string, shouldBreak?: boolean): Promise<void>;
executeLaunchRequest(deviceIdentifier: string, timeout: number, readyForAttachTimeout: number, projectId: string, debugOptions: IDebugOptions): Promise<void>;
executeAttachRequest(device: Mobile.IiOSDevice, timeout: number, projectId: string): Promise<void>;
}

Expand Down
4 changes: 4 additions & 0 deletions lib/definitions/debug.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,10 @@ interface IDebugOptions {
* The sdk version of the emulator.
*/
sdk?: string;
/**
* Defines if the handshake(AppLaunching notification) between CLI and runtime should be executed. The handshake is not needed when CLI retries to attach to the debugger.
*/
skipHandshake?: boolean;
}

/**
Expand Down
Loading