From ad40b3b86bf309326c59c6b365186c904fb17729 Mon Sep 17 00:00:00 2001 From: Brandy Carney Date: Mon, 5 Jun 2017 18:57:05 -0400 Subject: [PATCH] chore(scripts): normalize paths and include typeRoots for Windows (#11933) Short description of what this resolves: Allows our e2e tests to run on a Windows machine Changes proposed in this pull request: Normalize paths using path.join() Add typeRoots to the root tsconfig file Change the spawnedCommand based on the OS Fixes: #11551 --- scripts/demos/copy.config.js | 4 ++-- scripts/demos/watch.config.js | 4 ++-- scripts/e2e/copy.config.js | 6 +++--- scripts/e2e/e2e-publish.js | 10 +++++----- scripts/gulp/constants.ts | 4 ++-- scripts/gulp/tasks/build.ts | 17 +++++++++-------- scripts/gulp/tasks/e2e.dev.ts | 2 +- scripts/gulp/tasks/e2e.prod.ts | 19 +++++++++---------- scripts/gulp/tasks/polyfill.source.ts | 3 ++- scripts/gulp/tasks/polyfill.ts | 7 ++++--- scripts/gulp/tasks/snapshot.ts | 4 +++- scripts/gulp/util.ts | 12 ++++++++---- scripts/karma/karma.config.ts | 2 +- tsconfig.json | 3 +++ 14 files changed, 54 insertions(+), 43 deletions(-) diff --git a/scripts/demos/copy.config.js b/scripts/demos/copy.config.js index bbf7187de9a..f7ac44b64a0 100644 --- a/scripts/demos/copy.config.js +++ b/scripts/demos/copy.config.js @@ -4,7 +4,7 @@ var path = require('path'); module.exports = { copyAssets: { src: [path.join(path.dirname(process.env.IONIC_APP_ENTRY_POINT), '..', 'assets', '**', '*')], - dest: '{{WWW}}/assets' + dest: path.join('{{WWW}}', 'assets') }, copyIndexContent: { src: [path.join(process.cwd(), 'scripts', 'demos', 'index.html')], @@ -12,7 +12,7 @@ module.exports = { }, copyFonts: { src: [`${process.cwd()}/node_modules/ionicons/dist/fonts/**/*`, `${process.cwd()}/src/fonts/**/*`], - dest: '{{WWW}}/assets/fonts' + dest: path.join('{{WWW}}', 'assets', 'fonts') }, copyPolyfills: { src: [path.join(process.cwd(), 'dist', 'demos', 'polyfills', 'polyfills.js')], diff --git a/scripts/demos/watch.config.js b/scripts/demos/watch.config.js index 0ecfa672e2e..8fef9ab2db5 100644 --- a/scripts/demos/watch.config.js +++ b/scripts/demos/watch.config.js @@ -1,6 +1,6 @@ var path = require('path'); -var watch = require('../../node_modules/@ionic/app-scripts/dist/watch'); +var watch = require(path.join('..', '..', 'node_modules', '@ionic', 'app-scripts', 'dist', 'watch')); var entryPointDirectory = path.dirname(process.env.IONIC_APP_ENTRY_POINT) @@ -9,7 +9,7 @@ module.exports = { paths: [path.join(entryPointDirectory, '..', '**', '*.(ts|html|s(c|a)ss)')], options: { ignored: [path.join(entryPointDirectory, '..', '**', '*.spec.ts'), path.join(entryPointDirectory, '..', '**', '*.e2e.ts'), - '**/*.DS_Store'] }, + path.join('**', '*.DS_Store')] }, callback: watch.buildUpdate } } diff --git a/scripts/e2e/copy.config.js b/scripts/e2e/copy.config.js index 6e0656e814c..8f1ad8f0ab8 100644 --- a/scripts/e2e/copy.config.js +++ b/scripts/e2e/copy.config.js @@ -4,15 +4,15 @@ var path = require('path'); module.exports = { copyAssets: { src: [path.join(path.dirname(process.env.IONIC_APP_ENTRY_POINT), '..', 'assets', '**', '*')], - dest: '{{WWW}}/assets' + dest: path.join('{{WWW}}', 'assets') }, copyIndexContent: { src: [path.join(process.cwd(), 'scripts', 'e2e', 'index.html')], dest: '{{WWW}}' }, copyFonts: { - src: [`${process.cwd()}/node_modules/ionicons/dist/fonts/**/*`, `${process.cwd()}/src/fonts/**/*`], - dest: '{{WWW}}/assets/fonts' + src: [path.join(process.cwd(), 'node_modules', 'ionicons', 'dist', 'fonts', '**', '*'), path.join(process.cwd(), 'src', 'fonts', '**', '*')], + dest: path.join('{{WWW}}', 'assets', 'fonts') }, copyPolyfills: { src: [path.join(process.cwd(), 'dist', 'e2e', 'polyfills', 'polyfills.ng.js')], diff --git a/scripts/e2e/e2e-publish.js b/scripts/e2e/e2e-publish.js index 60c895f5e50..b46c2ed0ebc 100644 --- a/scripts/e2e/e2e-publish.js +++ b/scripts/e2e/e2e-publish.js @@ -4,7 +4,7 @@ module.exports = function(options) { var fs = require('fs'); var path = require('path'); var request = require('request'); - var inputDir = path.join(__dirname, '../../dist/e2e/tests'); + var inputDir = path.join(__dirname, '..', '..' , 'dist', 'e2e', 'tests'); var uploadQueue = []; var ignoreFiles = /(\/test\/|\/ts\/|\/q\/|\/ionic-site\/|\/docs\/|\/examples\/|\/inquirer\/|\/lodash\/|\/tooling\/|\/colors\/|\/bin\/|\.ts$|\.bin|\.map$|\.md$|\.git|\.scss$|\.yml$|\.yaml$|\.dart$|\.txt|\.npm|bower|DS_Store|LICENSE)/i; @@ -13,15 +13,15 @@ module.exports = function(options) { fs.readdir(dir, function(err, list) { list.forEach(function(file) { - var url = urlPath + '/' + file; + var url = path.join(urlPath, file); - fs.stat(dir + '/' + file, function(err, stat) { + fs.stat(path.join(dir, file), function(err, stat) { if (stat && stat.isDirectory()) { - uploadFiles(dir + '/' + file, urlPath + '/' + file); + uploadFiles(path.join(dir, file), path.join(urlPath, file); } else { if ( shouldProcessPath (url) ){ - uploadFile(url, dir + '/' + file); + uploadFile(url, path.join(dir, file)); } } }); diff --git a/scripts/gulp/constants.ts b/scripts/gulp/constants.ts index ad6d9a14a1d..efdc877f885 100644 --- a/scripts/gulp/constants.ts +++ b/scripts/gulp/constants.ts @@ -20,7 +20,7 @@ export const BUNDLES = 'bundles'; export const SITE_NAME = 'ionic-site'; // File Paths -export const PROJECT_ROOT = join(__dirname, '../..'); +export const PROJECT_ROOT = join(__dirname, '..', '..'); export const DEMOS_ROOT = join(PROJECT_ROOT, DEMOS_NAME); export const DEMOS_SRC_ROOT = join(DEMOS_ROOT, SRC_NAME); export const DIST_ROOT = join(PROJECT_ROOT, DIST_NAME); @@ -45,7 +45,7 @@ export const WORKERS_SRC = join(SCRIPTS_ROOT, 'workers'); // NPM export const NPM_VENDOR_FILES = [ - '@angular', 'core-js/client', 'rxjs', 'systemjs/dist', 'zone.js/dist' + '@angular', join('core-js', 'client'), 'rxjs', join('systemjs', 'dist'), join('zone.js', 'dist') ]; diff --git a/scripts/gulp/tasks/build.ts b/scripts/gulp/tasks/build.ts index eb9fe066efa..d7668a54c46 100644 --- a/scripts/gulp/tasks/build.ts +++ b/scripts/gulp/tasks/build.ts @@ -1,4 +1,5 @@ import { task } from 'gulp'; +import { join } from 'path'; import { DIST_BUILD_ROOT, DIST_BUILD_ES2015_ROOT, DIST_BUILD_UMD_ROOT, ES5, ES_2015, PROJECT_ROOT, UMD_MODULE } from '../constants'; import { copySourceToDest, createTempTsConfig, deleteFiles, runNgc, runTsc } from '../util'; @@ -7,8 +8,8 @@ export function buildIonicAngularUmd(excludeSpec: boolean, stripDebug: boolean, const stream = copySourceToDest(DIST_BUILD_UMD_ROOT, excludeSpec, true, stripDebug); stream.on('end', () => { // the source files are copied, copy over a tsconfig from - createTempTsConfig(['./**/*.ts'], ES5, UMD_MODULE, `${PROJECT_ROOT}/tsconfig.json`, `${DIST_BUILD_UMD_ROOT}/tsconfig.json`); - runNgc(`${DIST_BUILD_UMD_ROOT}/tsconfig.json`, (err) => { + createTempTsConfig([join('.', '**', '*.ts')], ES5, UMD_MODULE, join(PROJECT_ROOT, 'tsconfig.json'), join(DIST_BUILD_UMD_ROOT, 'tsconfig.json')); + runNgc(join(DIST_BUILD_UMD_ROOT, 'tsconfig.json'), (err) => { if (err) { done(err); return; @@ -27,8 +28,8 @@ export function buildIonicAngularUmdTsc(excludeSpec: boolean, stripDebug: boolea const stream = copySourceToDest(DIST_BUILD_UMD_ROOT, excludeSpec, true, stripDebug); stream.on('end', () => { // the source files are copied, copy over a tsconfig from - createTempTsConfig(['./**/*.ts'], ES5, UMD_MODULE, `${PROJECT_ROOT}/tsconfig.json`, `${DIST_BUILD_UMD_ROOT}/tsconfig.json`); - runTsc(`${DIST_BUILD_UMD_ROOT}/tsconfig.json`, (err) => { + createTempTsConfig([join('.', '**', '*.ts')], ES5, UMD_MODULE, join(PROJECT_ROOT, 'tsconfig.json'), join(DIST_BUILD_UMD_ROOT, 'tsconfig.json')); + runTsc(join(DIST_BUILD_UMD_ROOT, 'tsconfig.json'), (err) => { if (err) { done(err); return; @@ -48,8 +49,8 @@ export function buildIonicAngularEsm(stripDebug: boolean, done: Function) { const stream = copySourceToDest(DIST_BUILD_ROOT, true, true, stripDebug); stream.on('end', () => { // the source files are copied, copy over a tsconfig from - createTempTsConfig(['./**/*.ts'], ES5, ES_2015, `${PROJECT_ROOT}/tsconfig.json`, `${DIST_BUILD_ROOT}/tsconfig.json`); - runNgc(`${DIST_BUILD_ROOT}/tsconfig.json`, (err) => { + createTempTsConfig([join('.', '**', '*.ts')], ES5, ES_2015, join(PROJECT_ROOT, 'tsconfig.json'), join(DIST_BUILD_ROOT, 'tsconfig.json')); + runNgc(join(DIST_BUILD_ROOT, 'tsconfig.json'), (err) => { if (err) { done(err); return; @@ -67,8 +68,8 @@ export function buildIonicPureEs6(stripDebug: boolean, done: Function) { const stream = copySourceToDest(DIST_BUILD_ES2015_ROOT, true, true, stripDebug); stream.on('end', () => { // the source files are copied, copy over a tsconfig from - createTempTsConfig(['./**/*.ts'], ES_2015, ES_2015, `${PROJECT_ROOT}/tsconfig.json`, `${DIST_BUILD_ES2015_ROOT}/tsconfig.json`); - runNgc(`${DIST_BUILD_ES2015_ROOT}/tsconfig.json`, (err) => { + createTempTsConfig([join('.', '**', '*.ts')], ES_2015, ES_2015, join(PROJECT_ROOT, 'tsconfig.json'), join(DIST_BUILD_ES2015_ROOT, 'tsconfig.json')); + runNgc(join(DIST_BUILD_ES2015_ROOT, 'tsconfig.json'), (err) => { if (err) { done(err); return; diff --git a/scripts/gulp/tasks/e2e.dev.ts b/scripts/gulp/tasks/e2e.dev.ts index 63e1f866382..e9a5237afca 100644 --- a/scripts/gulp/tasks/e2e.dev.ts +++ b/scripts/gulp/tasks/e2e.dev.ts @@ -47,5 +47,5 @@ function serveTest(folderInfo: any) { const appNgModulePath = join(dirname(appEntryPoint), 'app.module.ts'); const distDir = join(distTestRoot, 'www'); - return runAppScriptsServe(folderInfo.componentName + '/' + folderInfo.componentTest, appEntryPoint, appNgModulePath, ionicAngularDir, distDir, pathToWriteFile, ionicAngularDir, sassConfigPath, copyConfigPath, null); + return runAppScriptsServe(join(folderInfo.componentName, folderInfo.componentTest), appEntryPoint, appNgModulePath, ionicAngularDir, distDir, pathToWriteFile, ionicAngularDir, sassConfigPath, copyConfigPath, null); } diff --git a/scripts/gulp/tasks/e2e.prod.ts b/scripts/gulp/tasks/e2e.prod.ts index ca0aa5a8637..b9846615844 100644 --- a/scripts/gulp/tasks/e2e.prod.ts +++ b/scripts/gulp/tasks/e2e.prod.ts @@ -21,7 +21,7 @@ task('e2e.prepare', (done: Function) => { task('e2e.prepareSass', (done: Function) => { const version = `E2E-${createTimestamp()}`; - writeFileSync(join(SRC_ROOT, 'themes/version.scss'), `$ionic-version: "${version}";`); + writeFileSync(join(SRC_ROOT, 'themes', 'version.scss'), `$ionic-version: "${version}";`); done(); }); @@ -41,7 +41,7 @@ task('e2e.prod', ['e2e.prepare'], (done: Function) => { }); function e2eComponentExists(folderInfo: any): boolean { - let componentPath = `${SRC_COMPONENTS_ROOT}/${folderInfo.componentName}/test/${folderInfo.componentTest}/app`; + let componentPath = join(SRC_COMPONENTS_ROOT, folderInfo.componentName, 'test', folderInfo.componentTest, 'app'); try { accessSync(componentPath); @@ -62,11 +62,11 @@ function filterE2eTestfiles() { const folderInfo = getFolderInfo(); if (folderInfo && folderInfo.componentName && folderInfo.componentTest) { if (!e2eComponentExists(folderInfo)) { - console.log(`Can't find E2E test "${folderInfo.componentName}/test/${folderInfo.componentTest}". Make sure that the test exists and you are passing the correct folder.`); + console.log('Cannot find E2E test ', join(folderInfo.componentName, 'test', folderInfo.componentTest), '. Make sure that the test exists and you are passing the correct folder.'); return []; } const filtered = entryPoints.filter(entryPoint => { - return entryPoint.indexOf(`${folderInfo.componentName}/test/${folderInfo.componentTest}`) >= 0; + return entryPoint.indexOf(join(folderInfo.componentName, 'test', folderInfo.componentTest)) >= 0; }); return filtered; } @@ -121,7 +121,7 @@ function buildTest(filePath: string) { const relativePathFromComponents = relative(dirname(SRC_COMPONENTS_ROOT), srcTestRoot); const distTestRoot = join(process.cwd(), 'dist', 'e2e', relativePathFromComponents); - const includeGlob = [ join(ionicAngularDir, '**', '*.ts')]; + const includeGlob = [join(ionicAngularDir, '**', '*.ts')]; const pathToWriteFile = join(distTestRoot, 'tsconfig.json'); const pathToReadFile = join(PROJECT_ROOT, 'tsconfig.json'); @@ -154,7 +154,7 @@ function copyProtractorTestContent(filePaths: string[]): Promise { } function applyTemplate(filePathContent: Map) { - const buildConfig = require('../../build/config'); + const buildConfig = require(join('..', '..', 'build', 'config')); const templateFileContent = readFileSync(join(SCRIPTS_ROOT, 'e2e', 'e2e.template.js')); const templater = template(templateFileContent.toString()); const modifiedMap = new Map(); @@ -235,7 +235,7 @@ task('e2e.polyfill', (done: Function) => { return done(); } - writePolyfills('dist/e2e/polyfills').then(() => { + writePolyfills(join('dist', 'e2e', 'polyfills')).then(() => { done(); }).catch(err => { done(err); @@ -249,9 +249,8 @@ task('e2e.openProd', (done: Function) => { task('e2e.open', (done: Function) => { const folderInfo = getFolderInfo(); if (folderInfo && folderInfo.componentName && folderInfo.componentTest) { - const filePath = `${folderInfo.componentName}/test/${folderInfo.componentTest}/www/index.html`; - const fullPath = join(DIST_E2E_COMPONENTS_ROOT, filePath); - const spawnedCommand = spawn('open', [fullPath]); + const filePath = join(DIST_E2E_COMPONENTS_ROOT, folderInfo.componentName, 'test', folderInfo.componentTest, 'www', 'index.html'); + const spawnedCommand = spawn('open', [filePath]); spawnedCommand.on('close', (code: number) => { done(); diff --git a/scripts/gulp/tasks/polyfill.source.ts b/scripts/gulp/tasks/polyfill.source.ts index bc5bfc98171..a7d4fca9ab5 100644 --- a/scripts/gulp/tasks/polyfill.source.ts +++ b/scripts/gulp/tasks/polyfill.source.ts @@ -1,9 +1,10 @@ import { task } from 'gulp'; import { writePolyfills } from '../util'; +import { join } from 'path'; task('src.polyfill', (done: Function) => { - writePolyfills('scripts/polyfill').then(() => { + writePolyfills(join('scripts', 'polyfills')).then(() => { done(); }).catch(err => { done(err); diff --git a/scripts/gulp/tasks/polyfill.ts b/scripts/gulp/tasks/polyfill.ts index 598d377b031..603711dcbb7 100644 --- a/scripts/gulp/tasks/polyfill.ts +++ b/scripts/gulp/tasks/polyfill.ts @@ -1,10 +1,11 @@ import { task, src, dest } from 'gulp'; import { writePolyfills } from '../util'; +import { join } from 'path'; task('polyfill', ['polyfill.copy-readme', 'polyfill.write']); task('polyfill.write', (done: Function) => { - writePolyfills('dist/ionic-angular/polyfills').then(() => { + writePolyfills(join('dist', 'ionic-angular', 'polyfills')).then(() => { done(); }).catch(err => { done(err); @@ -12,6 +13,6 @@ task('polyfill.write', (done: Function) => { }); task('polyfill.copy-readme', (done: Function) => { - return src('scripts/polyfill/readme.md') - .pipe(dest('dist/ionic-angular/polyfills/'), done); + return src(join('scripts', 'polyfill', 'readme.md')) + .pipe(dest(join('dist', 'ionic-angular', 'polyfills')), done); }); diff --git a/scripts/gulp/tasks/snapshot.ts b/scripts/gulp/tasks/snapshot.ts index 437d22dcb32..01ed3049a64 100644 --- a/scripts/gulp/tasks/snapshot.ts +++ b/scripts/gulp/tasks/snapshot.ts @@ -77,7 +77,9 @@ function protractor(callback, args, testId: string) { console.log(`Serving ${process.cwd()} on http://localhost:${buildConfig.protractorPort}`); - const child = spawn('protractor', args, { + let spawnCommand = process.platform === 'win32' ? 'protractor.cmd' : 'protractor'; + + const child = spawn(spawnCommand, args, { stdio: [process.stdin, process.stdout, 'pipe'] }); diff --git a/scripts/gulp/util.ts b/scripts/gulp/util.ts index 44ff7147913..e87bf09db32 100644 --- a/scripts/gulp/util.ts +++ b/scripts/gulp/util.ts @@ -1,4 +1,4 @@ -import { spawn } from 'child_process'; +import { spawn } from 'cross-spawn'; import { NODE_MODULES_ROOT, SRC_ROOT } from './constants'; import { src, dest } from 'gulp'; import { dirname, join } from 'path'; @@ -60,7 +60,9 @@ export function createTempTsConfig(includeGlob: string[], target: string, module config.compilerOptions = Object.assign(config.compilerOptions, overrideCompileOptions); } + // TS represents paths internally with '/' and expects the tsconfig path to be in this format let json = JSON.stringify(config, null, 2); + json = json.replace(/\\\\/g, '/'); const dirToCreate = dirname(pathToWriteFile); ensureDirSync(dirToCreate); @@ -217,9 +219,11 @@ export function runAppScriptsServe(testOrDemoName: string, appEntryPoint: string } return new Promise((resolve, reject) => { - const args = ['./node_modules/.bin/ionic-app-scripts'].concat(scriptArgs); - console.log(`node ${args.join(' ')}`); - const spawnedCommand = spawn('node', args, {stdio: 'inherit'}); + let pathToAppScripts = join(NODE_MODULES_ROOT, '.bin', 'ionic-app-scripts'); + pathToAppScripts = process.platform === 'win32' ? pathToAppScripts + '.cmd' : pathToAppScripts; + + const spawnedCommand = spawn(pathToAppScripts, scriptArgs, {stdio: 'inherit'}); + console.log(`${pathToAppScripts} ${scriptArgs.join(' ')}`); spawnedCommand.on('close', (code: number) => { if (code === 0) { diff --git a/scripts/karma/karma.config.ts b/scripts/karma/karma.config.ts index 61a64347cff..d84694f60ca 100644 --- a/scripts/karma/karma.config.ts +++ b/scripts/karma/karma.config.ts @@ -95,4 +95,4 @@ export function config(config) { singleRun: true }); -}; +}; \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json index 7823d30a724..b7c5bb3a2c8 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -11,6 +11,9 @@ "removeComments": false, "sourceMap": true, "target": "es2015", + "typeRoots": [ + "./node_modules/@types" + ], "types": ["jasmine", "systemjs"] }, "include": [