diff --git a/lib/bootstrap.ts b/lib/bootstrap.ts index 45a92f38d3..303febcc66 100644 --- a/lib/bootstrap.ts +++ b/lib/bootstrap.ts @@ -131,6 +131,7 @@ $injector.requirePublicClass("androidLivesyncTool", "./services/livesync/android $injector.require("androidLiveSyncService", "./services/livesync/android-livesync-service"); $injector.require("iOSLiveSyncService", "./services/livesync/ios-livesync-service"); $injector.require("usbLiveSyncService", "./services/livesync/livesync-service"); // The name is used in https://github.com/NativeScript/nativescript-dev-typescript +$injector.require("previewAppFilesService", "./services/livesync/playground/preview-app-files-service"); $injector.require("previewAppLiveSyncService", "./services/livesync/playground/preview-app-livesync-service"); $injector.require("previewAppLogProvider", "./services/livesync/playground/preview-app-log-provider"); $injector.require("previewAppPluginsService", "./services/livesync/playground/preview-app-plugins-service"); diff --git a/lib/common/helpers.ts b/lib/common/helpers.ts index 799574ab0b..c355e3a6dd 100644 --- a/lib/common/helpers.ts +++ b/lib/common/helpers.ts @@ -563,6 +563,10 @@ export function getWinRegPropertyValue(key: string, propertyName: string): Promi }); } +export function stringify(value: any, replacer?: (key: string, value: any) => any, space?: string | number): string { + return JSON.stringify(value, replacer, space || 2); +} + //--- begin part copied from AngularJS //The MIT License diff --git a/lib/definitions/preview-app-livesync.d.ts b/lib/definitions/preview-app-livesync.d.ts index bac20cb7b0..18c3b8d877 100644 --- a/lib/definitions/preview-app-livesync.d.ts +++ b/lib/definitions/preview-app-livesync.d.ts @@ -8,6 +8,16 @@ declare global { stopLiveSync(): Promise; } + interface IPreviewAppFilesService { + getInitialFilesPayload(liveSyncData: IPreviewAppLiveSyncData, platform: string, deviceId?: string): FilesPayload; + getFilesPayload(liveSyncData: IPreviewAppLiveSyncData, filesData: IPreviewAppFilesData, platform: string, deviceId?: string): FilesPayload; + } + + interface IPreviewAppFilesData { + filesToSync: string[]; + filesToRemove?: string[]; + } + interface IPreviewAppLiveSyncData extends IProjectDir, IHasUseHotModuleReloadOption, IBundle, IEnvOptions { } interface IPreviewSdkService extends EventEmitter { diff --git a/lib/services/livesync/playground/preview-app-files-service.ts b/lib/services/livesync/playground/preview-app-files-service.ts new file mode 100644 index 0000000000..5822eb1b00 --- /dev/null +++ b/lib/services/livesync/playground/preview-app-files-service.ts @@ -0,0 +1,89 @@ +import * as path from "path"; +import { APP_FOLDER_NAME, TNS_MODULES_FOLDER_NAME, APP_RESOURCES_FOLDER_NAME } from "../../../constants"; +import { PreviewSdkEventNames } from "./preview-app-constants"; +import { FilePayload, FilesPayload } from "nativescript-preview-sdk"; +const isTextOrBinary = require('istextorbinary'); + +export class PreviewAppFilesService implements IPreviewAppFilesService { + private excludedFileExtensions = [".ts", ".sass", ".scss", ".less"]; + private excludedFiles = [".DS_Store"]; + + constructor( + private $fs: IFileSystem, + private $logger: ILogger, + private $platformsData: IPlatformsData, + private $projectDataService: IProjectDataService, + private $projectFilesManager: IProjectFilesManager + ) { } + + public getInitialFilesPayload(data: IPreviewAppLiveSyncData, platform: string, deviceId?: string): FilesPayload { + const rootFilesDir = this.getRootFilesDir(data, platform); + const filesToSync = this.$projectFilesManager.getProjectFiles(rootFilesDir); + const payloads = this.getFilesPayload(data, { filesToSync }, platform, deviceId); + return payloads; + } + + public getFilesPayload(data: IPreviewAppLiveSyncData, filesData: IPreviewAppFilesData, platform: string, deviceId?: string): FilesPayload { + const { filesToSync, filesToRemove } = filesData; + + const filesToTransfer = filesToSync + .filter(file => file.indexOf(TNS_MODULES_FOLDER_NAME) === -1) + .filter(file => file.indexOf(APP_RESOURCES_FOLDER_NAME) === -1) + .filter(file => !_.includes(this.excludedFiles, path.basename(file))) + .filter(file => !_.includes(this.excludedFileExtensions, path.extname(file))); + + this.$logger.trace(`Sending ${filesToTransfer.join("\n")}.`); + + const rootFilesDir = this.getRootFilesDir(data, platform); + const payloadsToSync = _.map(filesToTransfer, file => this.createFilePayload(file, rootFilesDir, PreviewSdkEventNames.CHANGE_EVENT_NAME)); + const payloadsToRemove = _.map(filesToRemove, file => this.createFilePayload(file, rootFilesDir, PreviewSdkEventNames.UNLINK_EVENT_NAME)); + const payloads = payloadsToSync.concat(payloadsToRemove); + + return { + files: payloads, + platform: platform, + hmrMode: data.useHotModuleReload ? 1 : 0, + deviceId + }; + } + + private createFilePayload(file: string, rootFilesDir: string, event: string): FilePayload { + let fileContents = ""; + let binary = false; + + if (event === PreviewSdkEventNames.CHANGE_EVENT_NAME) { + binary = isTextOrBinary.isBinarySync(file); + if (binary) { + const bitmap = this.$fs.readFile(file); + const base64 = Buffer.from(bitmap).toString('base64'); + fileContents = base64; + } else { + fileContents = this.$fs.readText(file); + } + } + + const filePayload = { + event, + file: path.relative(rootFilesDir, file), + binary, + fileContents + }; + + return filePayload; + } + + private getRootFilesDir(data: IPreviewAppLiveSyncData, platform: string): string { + const projectData = this.$projectDataService.getProjectData(data.projectDir); + const platformData = this.$platformsData.getPlatformData(platform, projectData); + + let rootFilesDir = null; + if (data.bundle) { + rootFilesDir = path.join(platformData.appDestinationDirectoryPath, APP_FOLDER_NAME); + } else { + rootFilesDir = projectData.getAppDirectoryPath(); + } + + return rootFilesDir; + } +} +$injector.register("previewAppFilesService", PreviewAppFilesService); diff --git a/lib/services/livesync/playground/preview-app-livesync-service.ts b/lib/services/livesync/playground/preview-app-livesync-service.ts index 1b8de93f86..bed0faac20 100644 --- a/lib/services/livesync/playground/preview-app-livesync-service.ts +++ b/lib/services/livesync/playground/preview-app-livesync-service.ts @@ -1,37 +1,25 @@ import * as path from "path"; -import { FilePayload, Device, FilesPayload } from "nativescript-preview-sdk"; -import { PreviewSdkEventNames } from "./preview-app-constants"; -import { APP_FOLDER_NAME, APP_RESOURCES_FOLDER_NAME, TNS_MODULES_FOLDER_NAME } from "../../../constants"; +import { Device, FilesPayload } from "nativescript-preview-sdk"; +import { APP_RESOURCES_FOLDER_NAME, APP_FOLDER_NAME } from "../../../constants"; import { HmrConstants } from "../../../common/constants"; -const isTextOrBinary = require('istextorbinary'); - -interface ISyncFilesOptions { - filesToSync?: string[]; - filesToRemove?: string[]; - isInitialSync?: boolean; - skipPrepare?: boolean; - useHotModuleReload?: boolean; - deviceId?: string; -} +import { stringify } from "../../../common/helpers"; export class PreviewAppLiveSyncService implements IPreviewAppLiveSyncService { - private excludedFileExtensions = [".ts", ".sass", ".scss", ".less"]; - private excludedFiles = [".DS_Store"]; + private deviceInitializationPromise: IDictionary> = {}; - constructor(private $fs: IFileSystem, + constructor( private $errors: IErrors, private $hooksService: IHooksService, private $logger: ILogger, - private $platformService: IPlatformService, private $platformsData: IPlatformsData, private $projectDataService: IProjectDataService, private $previewSdkService: IPreviewSdkService, + private $previewAppFilesService: IPreviewAppFilesService, private $previewAppPluginsService: IPreviewAppPluginsService, private $previewDevicesService: IPreviewDevicesService, - private $projectFilesManager: IProjectFilesManager, private $hmrStatusService: IHmrStatusService, - private $projectFilesProvider: IProjectFilesProvider) { } + ) { } public async initialize(data: IPreviewAppLiveSyncData): Promise { await this.$previewSdkService.initialize(async (device: Device) => { @@ -43,7 +31,7 @@ export class PreviewAppLiveSyncService implements IPreviewAppLiveSyncService { return this.deviceInitializationPromise[device.id]; } - this.deviceInitializationPromise[device.id] = this.initializePreviewForDevice(data, device); + this.deviceInitializationPromise[device.id] = this.getInitialFilesForDevice(data, device); try { const payloads = await this.deviceInitializationPromise[device.id]; return payloads; @@ -65,8 +53,9 @@ export class PreviewAppLiveSyncService implements IPreviewAppLiveSyncService { .map(device => device.platform) .uniq() .value(); + for (const platform of platforms) { - await this.syncFilesForPlatformSafe(data, platform, { filesToSync, filesToRemove, useHotModuleReload: data.useHotModuleReload }); + await this.syncFilesForPlatformSafe(data, { filesToSync, filesToRemove }, platform); } } @@ -74,18 +63,18 @@ export class PreviewAppLiveSyncService implements IPreviewAppLiveSyncService { this.$previewSdkService.stop(); } - private async initializePreviewForDevice(data: IPreviewAppLiveSyncData, device: Device): Promise { + private async getInitialFilesForDevice(data: IPreviewAppLiveSyncData, device: Device): Promise { const hookArgs = this.getHookArgs(data, device); await this.$hooksService.executeBeforeHooks("preview-sync", { hookArgs }); await this.$previewAppPluginsService.comparePluginsOnDevice(data, device); - const payloads = await this.syncFilesForPlatformSafe(data, device.platform, { isInitialSync: true, useHotModuleReload: data.useHotModuleReload }); + const payloads = await this.getInitialFilesForPlatformSafe(data, device.platform); return payloads; } private getHookArgs(data: IPreviewAppLiveSyncData, device: Device) { const filesToSyncMap: IDictionary = {}; const hmrData: IDictionary = {}; - const promise = Promise.resolve(null); + const promise = Promise.resolve(); const result = { projectData: this.$projectDataService.getProjectData(data.projectDir), hmrData, @@ -106,14 +95,44 @@ export class PreviewAppLiveSyncService implements IPreviewAppLiveSyncService { return result; } - private async onWebpackCompilationComplete(data: IPreviewAppLiveSyncData, hmrData: IDictionary, filesToSyncMap: IDictionary, promise: Promise, platform: string) { + private async getInitialFilesForPlatformSafe(data: IPreviewAppLiveSyncData, platform: string): Promise { + this.$logger.info(`Start sending initial files for platform ${platform}.`); + + try { + const payloads = this.$previewAppFilesService.getInitialFilesPayload(data, platform); + this.$logger.info(`Successfully sent initial files for platform ${platform}.`); + return payloads; + } catch (err) { + this.$logger.warn(`Unable to apply changes for platform ${platform}. Error is: ${err}, ${stringify(err)}`); + } + } + + private async syncFilesForPlatformSafe(data: IPreviewAppLiveSyncData, filesData: IPreviewAppFilesData, platform: string, deviceId?: string): Promise { + this.$logger.info(`Start syncing changes for platform ${platform}.`); + + try { + const payloads = this.$previewAppFilesService.getFilesPayload(data, filesData, platform); + await this.$previewSdkService.applyChanges(payloads); + this.$logger.info(`Successfully synced ${payloads.files.map(filePayload => filePayload.file.yellow)} for platform ${platform}.`); + } catch (err) { + this.$logger.warn(`Unable to apply changes for platform ${platform}. Error is: ${err}, ${stringify(err)}.`); + } + } + + private async onWebpackCompilationComplete(data: IPreviewAppLiveSyncData, hmrData: IDictionary, filesToSyncMap: IDictionary, promise: Promise, platform: string) { await promise .then(async () => { const currentHmrData = _.cloneDeep(hmrData); const platformHmrData = currentHmrData[platform] || {}; - const filesToSync = _.cloneDeep(filesToSyncMap[platform]); - // We don't need to prepare when webpack emits changed files. We just need to send a message to pubnub. - promise = this.syncFilesForPlatformSafe(data, platform, { filesToSync, skipPrepare: true, useHotModuleReload: data.useHotModuleReload }); + const projectData = this.$projectDataService.getProjectData(data.projectDir); + const platformData = this.$platformsData.getPlatformData(platform, projectData); + const clonedFiles = _.cloneDeep(filesToSyncMap[platform]); + const filesToSync = _.map(clonedFiles, fileToSync => { + const result = path.join(platformData.appDestinationDirectoryPath, APP_FOLDER_NAME, path.relative(projectData.getAppDirectoryPath(), fileToSync)); + return result; + }); + + promise = this.syncFilesForPlatformSafe(data, { filesToSync }, platform); await promise; if (data.useHotModuleReload && platformHmrData.hash) { @@ -122,7 +141,10 @@ export class PreviewAppLiveSyncService implements IPreviewAppLiveSyncService { await Promise.all(_.map(devices, async (previewDevice: Device) => { const status = await this.$hmrStatusService.getHmrStatus(previewDevice.id, platformHmrData.hash); if (status === HmrConstants.HMR_ERROR_STATUS) { - await this.syncFilesForPlatformSafe(data, platform, { filesToSync: platformHmrData.fallbackFiles, useHotModuleReload: false, deviceId: previewDevice.id }); + const originalUseHotModuleReload = data.useHotModuleReload; + data.useHotModuleReload = false; + await this.syncFilesForPlatformSafe(data, { filesToSync: platformHmrData.fallbackFiles }, platform, previewDevice.id ); + data.useHotModuleReload = originalUseHotModuleReload; } })); } @@ -130,115 +152,9 @@ export class PreviewAppLiveSyncService implements IPreviewAppLiveSyncService { filesToSyncMap[platform] = []; } - private async syncFilesForPlatformSafe(data: IPreviewAppLiveSyncData, platform: string, opts?: ISyncFilesOptions): Promise { - this.$logger.info(`Start syncing changes for platform ${platform}.`); - - opts = opts || {}; - let payloads = null; - - try { - const { env, projectDir } = data; - const projectData = this.$projectDataService.getProjectData(projectDir); - const platformData = this.$platformsData.getPlatformData(platform, projectData); - - if (!opts.skipPrepare) { - await this.preparePlatform(platform, data, env, projectData); - } - - if (opts.isInitialSync) { - const platformsAppFolderPath = path.join(platformData.appDestinationDirectoryPath, APP_FOLDER_NAME); - opts.filesToSync = this.$projectFilesManager.getProjectFiles(platformsAppFolderPath); - payloads = this.getFilesPayload(platformData, projectData, opts); - this.$logger.info(`Successfully synced changes for platform ${platform}.`); - } else { - opts.filesToSync = _.map(opts.filesToSync, file => this.$projectFilesProvider.mapFilePath(file, platformData.normalizedPlatformName, projectData)); - payloads = this.getFilesPayload(platformData, projectData, opts); - await this.$previewSdkService.applyChanges(payloads); - this.$logger.info(`Successfully synced ${payloads.files.map(filePayload => filePayload.file.yellow)} for platform ${platform}.`); - } - - return payloads; - } catch (err) { - this.$logger.warn(`Unable to apply changes for platform ${platform}. Error is: ${err}, ${JSON.stringify(err, null, 2)}.`); - } - } - - private getFilesPayload(platformData: IPlatformData, projectData: IProjectData, opts?: ISyncFilesOptions): FilesPayload { - const { filesToSync, filesToRemove, deviceId } = opts; - - const filesToTransfer = filesToSync - .filter(file => file.indexOf(TNS_MODULES_FOLDER_NAME) === -1) - .filter(file => file.indexOf(APP_RESOURCES_FOLDER_NAME) === -1) - .filter(file => !_.includes(this.excludedFiles, path.basename(file))) - .filter(file => !_.includes(this.excludedFileExtensions, path.extname(file))); - - this.$logger.trace(`Transferring ${filesToTransfer.join("\n")}.`); - - const payloadsToSync = filesToTransfer.map(file => this.createFilePayload(file, platformData, projectData, PreviewSdkEventNames.CHANGE_EVENT_NAME)); - const payloadsToRemove = _.map(filesToRemove, file => this.createFilePayload(file, platformData, projectData, PreviewSdkEventNames.UNLINK_EVENT_NAME)); - const payloads = payloadsToSync.concat(payloadsToRemove); - - const hmrMode = opts.useHotModuleReload ? 1 : 0; - return { files: payloads, platform: platformData.normalizedPlatformName.toLowerCase(), hmrMode, deviceId }; - } - - private async preparePlatform(platform: string, data: IPreviewAppLiveSyncData, env: Object, projectData: IProjectData): Promise { - const appFilesUpdaterOptions = { - bundle: data.bundle, - useHotModuleReload: data.useHotModuleReload, - release: false - }; - const nativePrepare = { skipNativePrepare: true }; - const config = {}; - const platformTemplate = null; - const prepareInfo = { - platform, - appFilesUpdaterOptions, - env, - projectData, - nativePrepare, - config, - platformTemplate, - skipCopyTnsModules: true, - skipCopyAppResourcesFiles: true - }; - await this.$platformService.preparePlatform(prepareInfo); - } - private showWarningsForNativeFiles(files: string[]): void { _.filter(files, file => file.indexOf(APP_RESOURCES_FOLDER_NAME) > -1) .forEach(file => this.$logger.warn(`Unable to apply changes from ${APP_RESOURCES_FOLDER_NAME} folder. You need to build your application in order to make changes in ${APP_RESOURCES_FOLDER_NAME} folder.`)); } - - private createFilePayload(file: string, platformData: IPlatformData, projectData: IProjectData, event: string): FilePayload { - const projectFileInfo = this.$projectFilesProvider.getProjectFileInfo(file, platformData.normalizedPlatformName, null); - const binary = isTextOrBinary.isBinarySync(file); - let fileContents = ""; - let filePath = ""; - - if (event === PreviewSdkEventNames.CHANGE_EVENT_NAME) { - const relativePath = path.relative(path.join(platformData.appDestinationDirectoryPath, APP_FOLDER_NAME), file); - filePath = path.join(path.dirname(relativePath), projectFileInfo.onDeviceFileName); - - if (binary) { - const bitmap = this.$fs.readFile(file); - const base64 = Buffer.from(bitmap).toString('base64'); - fileContents = base64; - } else { - fileContents = this.$fs.readText(path.join(path.dirname(projectFileInfo.filePath), projectFileInfo.onDeviceFileName)); - } - } else if (event === PreviewSdkEventNames.UNLINK_EVENT_NAME) { - filePath = path.relative(path.join(projectData.projectDir, APP_FOLDER_NAME), file); - } - - const filePayload = { - event, - file: filePath, - binary, - fileContents - }; - - return filePayload; - } } $injector.register("previewAppLiveSyncService", PreviewAppLiveSyncService); diff --git a/test/services/playground/preview-app-files-service.ts b/test/services/playground/preview-app-files-service.ts new file mode 100644 index 0000000000..0eb7319f08 --- /dev/null +++ b/test/services/playground/preview-app-files-service.ts @@ -0,0 +1,128 @@ +import { Yok } from "../../../lib/common/yok"; +import { PreviewAppFilesService } from "../../../lib/services/livesync/playground/preview-app-files-service"; +import { FileSystemStub, LoggerStub } from "../../stubs"; +import * as path from "path"; +import { assert } from "chai"; +import { FilesPayload } from "nativescript-preview-sdk"; + +const projectDir = "path/to/my/test/project"; +const appDirectoryPath = path.join(projectDir, "src"); + +class ProjectDataServiceMock { + public getProjectData() { + return { + getAppDirectoryPath: () => appDirectoryPath, + appDirectoryPath: () => appDirectoryPath + }; + } +} + +class PlatformsDataMock { + public getPlatformData(platform: string) { + const appDestinationDirectoryPath = path.join(projectDir, "platforms", platform, "app"); + return { + appDestinationDirectoryPath + }; + } +} + +function createTestInjector(data?: { files: string[] }) { + const injector = new Yok(); + injector.register("previewAppFilesService", PreviewAppFilesService); + injector.register("fs", FileSystemStub); + injector.register("logger", LoggerStub); + injector.register("platformsData", PlatformsDataMock); + injector.register("projectDataService", ProjectDataServiceMock); + injector.register("projectFilesManager", { + getProjectFiles: () => data ? data.files : [] + }); + return injector; +} + +function getExpectedResult(data: IPreviewAppLiveSyncData, injector: IInjector, expectedFiles: string[], platform: string): FilesPayload { + const projectData = injector.resolve("projectDataService").getProjectData(); + const platformData = injector.resolve("platformsData").getPlatformData(platform); + const files = _.map(expectedFiles, expectedFile => { + return { + event: 'change', + file: data.bundle ? path.relative(path.join(platformData.appDestinationDirectoryPath, "app"), expectedFile) : path.relative(projectData.appDirectoryPath(), expectedFile), + binary: false, + fileContents: undefined + }; + }); + + return { + files, + platform, + hmrMode: data.useHotModuleReload ? 1 : 0, + deviceId: undefined + }; +} + +describe("PreviewAppFilesService", () => { + const testCases = [ + { + name: ".ts files", + files: ["dir1/file.js", "file.ts"], + expectedFiles: [`dir1/file.js`] + }, + { + name: ".sass files", + files: ["myDir1/mySubDir/myfile.css", "myDir1/mySubDir/myfile.sass"], + expectedFiles: [`myDir1/mySubDir/myfile.css`] + }, + { + name: ".scss files", + files: ["myDir1/mySubDir/myfile1.css", "myDir1/mySubDir/myfile.scss", "my/file.js"], + expectedFiles: [`myDir1/mySubDir/myfile1.css`, `my/file.js`] + }, + { + name: ".less files", + files: ["myDir1/mySubDir/myfile1.css", "myDir1/mySubDir/myfile.less", "my/file.js"], + expectedFiles: [`myDir1/mySubDir/myfile1.css`, `my/file.js`] + }, + { + name: ".DS_Store file", + files: ["my/test/file.js", ".DS_Store"], + expectedFiles: [`my/test/file.js`] + } + ]; + + describe("getInitialFilesPayload", () => { + _.each(testCases, testCase => { + _.each(["ios", "android"], platform => { + _.each([true, false], bundle => { + _.each([true, false], useHotModuleReload => { + it(`should exclude ${testCase.name} when { platform: ${platform}, bundle: ${bundle}, useHotModuleReload: ${useHotModuleReload} }`, () => { + const injector = createTestInjector({ files: testCase.files }); + const previewAppFilesService = injector.resolve("previewAppFilesService"); + const data = { projectDir, bundle, useHotModuleReload, env: {} }; + const result = previewAppFilesService.getInitialFilesPayload(data, platform); + const expectedResult = getExpectedResult(data, injector, testCase.expectedFiles, platform); + assert.deepEqual(result, expectedResult); + }); + }); + }); + }); + }); + }); + + describe("getFilesPayload", () => { + _.each(testCases, testCase => { + _.each(["ios", "android"], platform => { + _.each([true, false], bundle => { + _.each([true, false], useHotModuleReload => { + it(`should exclude ${testCase.name} when { platform: ${platform}, bundle: ${bundle}, useHotModuleReload: ${useHotModuleReload} }`, () => { + const injector = createTestInjector(); + const previewAppFilesService: IPreviewAppFilesService = injector.resolve("previewAppFilesService"); + const data = { projectDir, bundle, useHotModuleReload, env: {} }; + const result = previewAppFilesService.getFilesPayload(data, { filesToSync: testCase.files }, platform); + const expectedResult = getExpectedResult(data, injector, testCase.expectedFiles, platform); + assert.deepEqual(result, expectedResult); + }); + }); + }); + }); + }); + }); +}); diff --git a/test/services/playground/preview-app-livesync-service.ts b/test/services/playground/preview-app-livesync-service.ts index 95d7008458..ccbf24b999 100644 --- a/test/services/playground/preview-app-livesync-service.ts +++ b/test/services/playground/preview-app-livesync-service.ts @@ -7,6 +7,7 @@ import * as chai from "chai"; import * as path from "path"; import { ProjectFilesManager } from "../../../lib/common/services/project-files-manager"; import { EventEmitter } from "events"; +import { PreviewAppFilesService } from "../../../lib/services/livesync/playground/preview-app-files-service"; interface ITestCase { name: string; @@ -101,9 +102,6 @@ function createTestInjector(options?: { const injector = new Yok(); injector.register("logger", LoggerMock); - injector.register("platformService", { - preparePlatform: async () => ({}) - }); injector.register("hmrStatusService", {}); injector.register("errors", ErrorsStub); injector.register("platformsData", { @@ -114,7 +112,9 @@ function createTestInjector(options?: { }); injector.register("projectDataService", { getProjectData: () => ({ - projectDir: projectDirPath + projectDir: projectDirPath, + getAppDirectoryPath: () => path.join(projectDirPath, "app"), + appDirectoryPath: () => path.join(projectDirPath, "app") }) }); injector.register("previewSdkService", PreviewSdkServiceMock); @@ -157,6 +157,7 @@ function createTestInjector(options?: { injector.register("previewDevicesService", { getConnectedDevices: () => [deviceMockData] }); + injector.register("previewAppFilesService", PreviewAppFilesService); return injector; } @@ -234,7 +235,7 @@ function mapFiles(files: string[]): FilePayload[] { return files.map(file => { return { event: "change", - file: path.relative(path.join(platformsDirPath, "app"), path.join(platformsDirPath, "app", file)), + file: path.join("..", "platforms", "app", file), fileContents: undefined, binary: false }; @@ -291,34 +292,6 @@ describe("previewAppLiveSyncService", () => { describe("syncFiles", () => { afterEach(() => reset()); - const excludeFilesTestCases: ITestCase[] = [ - { - name: ".ts files", - appFiles: ["dir1/file.js", "file.ts"], - expectedFiles: [`dir1/file.js`] - }, - { - name: ".sass files", - appFiles: ["myDir1/mySubDir/myfile.css", "myDir1/mySubDir/myfile.sass"], - expectedFiles: [`myDir1/mySubDir/myfile.css`] - }, - { - name: ".scss files", - appFiles: ["myDir1/mySubDir/myfile1.css", "myDir1/mySubDir/myfile.scss", "my/file.js"], - expectedFiles: [`myDir1/mySubDir/myfile1.css`, `my/file.js`] - }, - { - name: ".less files", - appFiles: ["myDir1/mySubDir/myfile1.css", "myDir1/mySubDir/myfile.less", "my/file.js"], - expectedFiles: [`myDir1/mySubDir/myfile1.css`, `my/file.js`] - }, - { - name: ".DS_Store file", - appFiles: ["my/test/file.js", ".DS_Store"], - expectedFiles: [`my/test/file.js`] - } - ]; - const nativeFilesTestCases: ITestCase[] = [ { name: "Android manifest is changed", @@ -380,10 +353,6 @@ describe("previewAppLiveSyncService", () => { ]; const testCategories = [ - { - name: "should exclude", - testCases: excludeFilesTestCases - }, { name: "should show warning and not transfer native files when", testCases: nativeFilesTestCases.map(testCase => {