From d57e9c310143248d561b7a252116b6b2d56aee4d Mon Sep 17 00:00:00 2001 From: Dan Bucholtz Date: Tue, 13 Dec 2016 13:29:28 -0600 Subject: [PATCH] refactor(tests): interim commit for sharing test --- package.json | 8 +- {src/spec => scripts}/jasmine.config.json | 2 +- src/{spec => }/build.spec.ts | 37 ++-- src/build.ts | 1 - src/bundle.spec.ts | 214 ++++++++++++++++++++++ src/bundle.ts | 50 +++-- src/clean.spec.ts | 41 +++++ src/clean.ts | 6 +- src/copy.ts | 2 +- src/declarations.d.ts | 1 + src/lint.ts | 4 +- src/mocks/mock-helpers.ts | 9 + src/transpile.ts | 2 - src/util/config.ts | 105 ++++------- src/util/constants.ts | 27 +++ src/util/helpers.ts | 10 +- src/watch.ts | 2 +- src/webpack.ts | 13 +- 18 files changed, 402 insertions(+), 132 deletions(-) rename {src/spec => scripts}/jasmine.config.json (79%) rename src/{spec => }/build.spec.ts (66%) create mode 100644 src/bundle.spec.ts create mode 100644 src/clean.spec.ts create mode 100644 src/mocks/mock-helpers.ts diff --git a/package.json b/package.json index 233f4fa7..dd56a8a4 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,7 @@ }, "scripts": { "build": "npm run clean && tsc && npm run sass", + "test-watch": "tsc --watch --target es2015", "build-and-test": "npm run build && npm run test", "changelog": "./node_modules/.bin/conventional-changelog -p angular -i CHANGELOG.md -s", "clean": "rimraf ./dist", @@ -26,8 +27,8 @@ "nightly": "npm run build && node ./scripts/publish-nightly.js", "sass": "node-sass ./src/dev-client/sass/ion-dev.scss --output ./bin/ --output-style compressed", "sass-watch": "npm run sass && node-sass ./src/dev-client/sass/ion-dev.scss --watch --output ./bin/ --output-style compressed", - "test": "jasmine JASMINE_CONFIG_PATH=src/spec/jasmine.config.json || true", - "watch": "npm run clean && tsc --watch & npm run sass-watch" + "test": "jasmine JASMINE_CONFIG_PATH=scripts/jasmine.config.json || true", + "watch": "npm run clean && & npm run sass-watch" }, "main": "dist/index.js", "dependencies": { @@ -88,10 +89,11 @@ "jasmine": "2.5.2", "mock-fs": "3.11.0", "node-sass": "3.10.1", + "proxyquire": "^1.7.10", "rimraf": "2.5.4", "rxjs": "5.0.0-beta.12", "tslint-ionic-rules": "0.0.8", - "typescript": "2.0.9", + "typescript": "^2.1.4", "zone.js": "^0.6.26" }, "peerDependencies": { diff --git a/src/spec/jasmine.config.json b/scripts/jasmine.config.json similarity index 79% rename from src/spec/jasmine.config.json rename to scripts/jasmine.config.json index 997a08d4..c36b7ce4 100644 --- a/src/spec/jasmine.config.json +++ b/scripts/jasmine.config.json @@ -1,5 +1,5 @@ { - "spec_dir": "dist/spec", + "spec_dir": "dist", "spec_files": [ "**/*[sS]pec.js" ], diff --git a/src/spec/build.spec.ts b/src/build.spec.ts similarity index 66% rename from src/spec/build.spec.ts rename to src/build.spec.ts index 4860e5d3..f88fb591 100644 --- a/src/spec/build.spec.ts +++ b/src/build.spec.ts @@ -1,16 +1,18 @@ -import { BuildContext } from '../util/interfaces'; +/*import { BuildContext } from './util/interfaces'; -import * as build from '../build'; -import * as bundle from '../bundle'; -import * as copy from '../copy'; -import * as minify from '../minify'; -import * as lint from '../lint'; -import * as ngc from '../ngc'; -import * as sass from '../sass'; -import * as transpile from '../transpile'; +import * as helpers from './util/helpers'; +import * as build from './build'; +import * as bundle from './bundle'; +import * as copy from './copy'; +import * as minify from './minify'; +import * as lint from './lint'; +import * as ngc from './ngc'; +import * as sass from './sass'; +import * as transpile from './transpile'; describe('build', () => { beforeEach(() => { + spyOn(helpers, 'readFileAsync').and.returnValue(Promise.resolve()); spyOn(copy, 'copy').and.returnValue(Promise.resolve()); spyOn(ngc, 'ngc').and.returnValue(Promise.resolve()); spyOn(bundle, 'bundle').and.returnValue(Promise.resolve()); @@ -21,8 +23,7 @@ describe('build', () => { spyOn(transpile, 'transpile').and.returnValue(Promise.resolve()); }); - describe('build', () => { - it('isProd', () => { + it('should do a prod build', (done: Function) => { let context: BuildContext = { isProd: true, optimizeJs: true, @@ -32,6 +33,7 @@ describe('build', () => { }; build.build(context).then(() => { + expect(helpers.readFileAsync).toHaveBeenCalled(); expect(copy.copy).toHaveBeenCalled(); expect(ngc.ngc).toHaveBeenCalled(); expect(bundle.bundle).toHaveBeenCalled(); @@ -41,10 +43,14 @@ describe('build', () => { expect(lint.lint).toHaveBeenCalled(); expect(transpile.transpile).not.toHaveBeenCalled(); + done(); + }).catch(err => { + console.log(`err.message: `, err.message); + expect(true).toEqual(false); }); }); - it('isDev', () => { + it('should do a dev build', (done: Function) => { let context: BuildContext = { isProd: false, optimizeJs: false, @@ -54,6 +60,7 @@ describe('build', () => { }; build.build(context).then(() => { + expect(helpers.readFileAsync).toHaveBeenCalled(); expect(copy.copy).toHaveBeenCalled(); expect(transpile.transpile).toHaveBeenCalled(); expect(bundle.bundle).toHaveBeenCalled(); @@ -63,8 +70,12 @@ describe('build', () => { expect(ngc.ngc).not.toHaveBeenCalled(); expect(minify.minifyJs).not.toHaveBeenCalled(); expect(minify.minifyCss).not.toHaveBeenCalled(); + done(); + }).catch(err => { + console.log(`err.message: `, err.message); + expect(true).toEqual(false); }); }); - }); }); +*/ diff --git a/src/build.ts b/src/build.ts index ead4e2c3..0d0f3b6b 100644 --- a/src/build.ts +++ b/src/build.ts @@ -14,7 +14,6 @@ import { sass, sassUpdate } from './sass'; import { templateUpdate } from './template'; import { transpile, transpileUpdate, transpileDiagnosticsOnly } from './transpile'; - export function build(context: BuildContext) { setContext(context); const logger = new Logger(`build ${(context.isProd ? 'prod' : 'dev')}`); diff --git a/src/bundle.spec.ts b/src/bundle.spec.ts new file mode 100644 index 00000000..41e4dcc7 --- /dev/null +++ b/src/bundle.spec.ts @@ -0,0 +1,214 @@ +import * as bundle from './bundle'; +import * as rollup from './rollup'; +import * as webpack from './webpack'; +import * as Constants from './util/constants'; +import { ChangedFile } from './util/interfaces'; + +describe('bundle task', () => { + + describe('bundle', () => { + it('should return the value rollup task returns', async (done: Function) => { + // arrange + spyOn(rollup, rollup.rollup.name).and.returnValue(Promise.resolve()); + const context = { bundler: Constants.BUNDLER_ROLLUP}; + + // act + await bundle.bundle(context); + + // assert + expect(rollup.rollup).toHaveBeenCalled(); + done(); + }); + + it('should throw when rollup throws', async (done: Function) => { + const errorText = 'simulating an error'; + try { + // arrange + spyOn(rollup, rollup.rollup.name).and.throwError(errorText); + const context = { bundler: Constants.BUNDLER_ROLLUP}; + + // act + await bundle.bundle(context); + throw new Error('Should never happen'); + } catch (ex) { + // assert + expect(rollup.rollup).toHaveBeenCalled(); + expect(ex.message).toBe(errorText, `Received ${ex.message} instead of expected ${errorText}`); + done(); + } + }); + + it('should return the value webpack task returns', async (done: Function) => { + // arrange + spyOn(webpack, webpack.webpack.name).and.returnValue(Promise.resolve()); + const context = { bundler: Constants.BUNDLER_WEBPACK}; + + // act + await bundle.bundle(context); + + // assert + expect(webpack.webpack).toHaveBeenCalled(); + done(); + }); + + it('should throw when rollup throws', async (done: Function) => { + const errorText = 'simulating an error'; + try { + // arrange + spyOn(webpack, webpack.webpack.name).and.throwError(errorText); + const context = { bundler: Constants.BUNDLER_WEBPACK}; + + // act + await bundle.bundle(context); + throw new Error('Should never happen'); + } catch (ex) { + // assert + expect(webpack.webpack).toHaveBeenCalled(); + expect(ex.message).toBe(errorText, `Received ${ex.message} instead of expected ${errorText}`); + done(); + } + }); + }); + + describe('bundleUpdate', () => { + it('should return the value rollup returns', async (done: Function) => { + // arrange + spyOn(rollup, rollup.rollupUpdate.name).and.returnValue(Promise.resolve()); + const context = { bundler: Constants.BUNDLER_ROLLUP}; + const changedFiles: ChangedFile[] = []; + + // act + await bundle.bundleUpdate(changedFiles, context); + + // assert + expect(rollup.rollupUpdate).toHaveBeenCalledWith(changedFiles, context); + done(); + }); + + it('should throw when rollup throws', async (done: Function) => { + const errorText = 'simulating an error'; + try { + // arrange + spyOn(rollup, rollup.rollupUpdate.name).and.throwError(errorText); + const context = { bundler: Constants.BUNDLER_ROLLUP}; + const changedFiles: ChangedFile[] = []; + + // act + await bundle.bundleUpdate(changedFiles, context); + throw new Error('Should never happen'); + } catch (ex) { + // assert + expect(rollup.rollupUpdate).toHaveBeenCalled(); + expect(ex.message).toBe(errorText, `Received ${ex.message} instead of expected ${errorText}`); + done(); + } + }); + + it('should return the value webpack returns', async (done: Function) => { + // arrange + spyOn(webpack, webpack.webpackUpdate.name).and.returnValue(Promise.resolve()); + const context = { bundler: Constants.BUNDLER_WEBPACK}; + const changedFiles: ChangedFile[] = []; + + // act + await bundle.bundleUpdate(changedFiles, context); + + // assert + expect(webpack.webpackUpdate).toHaveBeenCalledWith(changedFiles, context); + done(); + }); + + it('should throw when webpack throws', async (done: Function) => { + const errorText = 'simulating an error'; + try { + // arrange + spyOn(webpack, webpack.webpackUpdate.name).and.throwError(errorText); + const context = { bundler: Constants.BUNDLER_WEBPACK}; + const changedFiles: ChangedFile[] = []; + + // act + await bundle.bundleUpdate(changedFiles, context); + throw new Error('Should never happen'); + } catch (ex) { + // assert + expect(webpack.webpackUpdate).toHaveBeenCalled(); + expect(ex.message).toBe(errorText, `Received ${ex.message} instead of expected ${errorText}`); + done(); + } + }); + }); + + describe('buildJsSourceMaps', () => { + it('should get the value from the rollup config', () => { + // arrange + const config = { + sourceMap: true + }; + spyOn(rollup, rollup.getRollupConfig.name).and.returnValue(config); + const context = { bundler: Constants.BUNDLER_ROLLUP}; + // act + const result = bundle.buildJsSourceMaps(context); + + // assert + expect(rollup.getRollupConfig).toHaveBeenCalledWith(context, null); + expect(result).toEqual(config.sourceMap, `Expected result ${result} to equal ${config.sourceMap}`); + }); + + it('should get false when devtool is null for webpack', () => { + // arrange + const config = { }; + spyOn(webpack, webpack.getWebpackConfig.name).and.returnValue(config); + const context = { bundler: Constants.BUNDLER_WEBPACK}; + // act + const result = bundle.buildJsSourceMaps(context); + + // assert + expect(webpack.getWebpackConfig).toHaveBeenCalledWith(context, null); + expect(result).toEqual(false, `Expected result ${result} to equal false`); + }); + + it('should get false when devtool is valid', () => { + // arrange + const config = { devtool: 'someValue'}; + spyOn(webpack, webpack.getWebpackConfig.name).and.returnValue(config); + const context = { bundler: Constants.BUNDLER_WEBPACK}; + // act + const result = bundle.buildJsSourceMaps(context); + + // assert + expect(webpack.getWebpackConfig).toHaveBeenCalledWith(context, null); + expect(result).toEqual(true, `Expected result ${result} to equal true`); + }); + }); + + describe('getJsOutputDest', () => { + it('should get the value from rollup', () => { + // arrange + const config = { }; + const returnValue = 'someString'; + spyOn(rollup, rollup.getRollupConfig.name).and.returnValue(config); + spyOn(rollup, rollup.getOutputDest.name).and.returnValue(returnValue); + const context = { bundler: Constants.BUNDLER_ROLLUP}; + // act + const result = bundle.getJsOutputDest(context); + + // assert + expect(rollup.getRollupConfig).toHaveBeenCalledWith(context, null); + expect(rollup.getOutputDest).toHaveBeenCalledWith(context, config); + expect(result).toEqual(returnValue, `Expected result ${result} to equal ${returnValue}`); + }); + + it('should get the value from webpack', () => { + // arrange + const returnValue = 'someString'; + spyOn(webpack, webpack.getOutputDest.name).and.returnValue(returnValue); + const context = { bundler: Constants.BUNDLER_WEBPACK}; + // act + const result = bundle.getJsOutputDest(context); + + // assert + expect(webpack.getOutputDest).toHaveBeenCalledWith(context); + expect(result).toEqual(returnValue, `Expected result ${result} to equal ${returnValue}`); + }); + }); +}); diff --git a/src/bundle.ts b/src/bundle.ts index 4c1998e5..2a4c7a90 100644 --- a/src/bundle.ts +++ b/src/bundle.ts @@ -1,20 +1,21 @@ import { BuildContext, ChangedFile } from './util/interfaces'; -import { BuildError, IgnorableError } from './util/errors'; -import { BUNDLER_ROLLUP } from './util/config'; +import { BuildError } from './util/errors'; +import * as Constants from './util/constants'; import { rollup, rollupUpdate, getRollupConfig, getOutputDest as rollupGetOutputDest } from './rollup'; import { webpack, webpackUpdate, getWebpackConfig, getOutputDest as webpackGetOutputDest } from './webpack'; -export function bundle(context: BuildContext, configFile?: string) { - return bundleWorker(context, configFile) - .catch((err: Error) => { - throw new BuildError(err); - }); +export async function bundle(context: BuildContext, configFile?: string): Promise { + try { + return await bundleWorker(context, configFile); + } catch (ex) { + throw new BuildError(ex); + } } function bundleWorker(context: BuildContext, configFile: string) { - if (context.bundler === BUNDLER_ROLLUP) { + if (context.bundler === Constants.BUNDLER_ROLLUP) { return rollup(context, configFile); } @@ -22,41 +23,34 @@ function bundleWorker(context: BuildContext, configFile: string) { } -export function bundleUpdate(changedFiles: ChangedFile[], context: BuildContext) { - if (context.bundler === BUNDLER_ROLLUP) { - return rollupUpdate(changedFiles, context) - .catch(err => { - throw new BuildError(err); - }); +export async function bundleUpdate(changedFiles: ChangedFile[], context: BuildContext) { + try { + if (context.bundler === Constants.BUNDLER_ROLLUP) { + return await rollupUpdate(changedFiles, context); + } + return await webpackUpdate(changedFiles, context); + } catch (ex) { + throw new BuildError(ex); } - - return webpackUpdate(changedFiles, context, null) - .catch(err => { - if (err instanceof IgnorableError) { - throw err; - } - throw new BuildError(err); - }); } export function buildJsSourceMaps(context: BuildContext) { - if (context.bundler === BUNDLER_ROLLUP) { + if (context.bundler === Constants.BUNDLER_ROLLUP) { const rollupConfig = getRollupConfig(context, null); return rollupConfig.sourceMap; } - // TODO - read this from webpack config (could be multiple values) - return true; + const webpackConfig = getWebpackConfig(context, null); + return !!(webpackConfig.devtool && webpackConfig.devtool.length > 0); } export function getJsOutputDest(context: BuildContext) { - if (context.bundler === BUNDLER_ROLLUP) { + if (context.bundler === Constants.BUNDLER_ROLLUP) { const rollupConfig = getRollupConfig(context, null); return rollupGetOutputDest(context, rollupConfig); } - const webpackConfig = getWebpackConfig(context, null); - return webpackGetOutputDest(context, webpackConfig); + return webpackGetOutputDest(context); } diff --git a/src/clean.spec.ts b/src/clean.spec.ts new file mode 100644 index 00000000..73873aaf --- /dev/null +++ b/src/clean.spec.ts @@ -0,0 +1,41 @@ +import * as fs from 'fs-extra'; +import * as clean from './clean'; + +describe('clean task', () => { + + describe('clean', () => { + it('should empty the build directory', async (done: Function) => { + // arrage + spyOn(fs, fs.emptyDirSync.name).and.returnValue('hurray'); + const context = { buildDir: 'something' }; + + // act + const result = clean.clean(context); + + // assert + await result; + expect(fs.emptyDirSync).toHaveBeenCalledWith(context.buildDir); + done(); + }); + + it('should throw when failing to empty dir', (done: Function) => { + // arrage + spyOn(fs, fs.emptyDirSync.name).and.throwError('Simulating an error'); + const context = { buildDir: 'something' }; + + // act + let error: Error = null; + try { + clean.clean(context); + } catch (ex) { + error = ex; + } + + // assert + expect(error).toBeTruthy('Error is null'); + expect(error instanceof Error).toBe(true, 'Error is not an instance of type Error'); + expect(typeof error.message).toBe('string', 'error.message is not a string'); + done(); + }); + }); +}); \ No newline at end of file diff --git a/src/clean.ts b/src/clean.ts index 01c4e39a..3edc90c8 100644 --- a/src/clean.ts +++ b/src/clean.ts @@ -8,13 +8,13 @@ export function clean(context: BuildContext) { const logger = new Logger('clean'); try { - Logger.debug(`clean ${context.buildDir}`); + Logger.debug(`[Clean] clean: cleaning ${context.buildDir}`); emptyDirSync(context.buildDir); logger.finish(); - } catch (e) { - throw logger.fail(new BuildError(`Error cleaning ${context.buildDir}, ${e}`)); + } catch (ex) { + throw logger.fail(new BuildError(`Failed to clean directory ${context.buildDir} - ${ex.message}`)); } return Promise.resolve(); diff --git a/src/copy.ts b/src/copy.ts index 09718106..fc2841e4 100644 --- a/src/copy.ts +++ b/src/copy.ts @@ -163,7 +163,7 @@ function processRemoveFile(changedFile: ChangedFile) { }); } -function processRemoveDir(changedFile: ChangedFile) { +function processRemoveDir(changedFile: ChangedFile): Promise { // remove any files from the cache where the dirname equals the provided path const keysToRemove: string[] = []; const directoriesToRemove = new Set(); diff --git a/src/declarations.d.ts b/src/declarations.d.ts index 9fda4149..e66ccc92 100644 --- a/src/declarations.d.ts +++ b/src/declarations.d.ts @@ -1,5 +1,6 @@ declare module 'autoprefixer'; declare module 'mime-types'; +declare module 'proxyquire'; declare module 'os-name'; declare module 'proxy-middleware'; declare module 'rollup-pluginutils'; diff --git a/src/lint.ts b/src/lint.ts index 9c5b59e3..1a1572db 100644 --- a/src/lint.ts +++ b/src/lint.ts @@ -66,14 +66,14 @@ function lintApp(context: BuildContext, configFile: string) { } function lintFiles(context: BuildContext, program: ts.Program, filePaths: string[]) { - const promises: Promise[] = []; + const promises: Promise[] = []; for (const filePath of filePaths) { promises.push(lintFile(context, program, filePath)); } return Promise.all(promises); } -function lintFile(context: BuildContext, program: ts.Program, filePath: string) { +function lintFile(context: BuildContext, program: ts.Program, filePath: string): Promise { return new Promise((resolve) => { if (isMpegFile(filePath)) { diff --git a/src/mocks/mock-helpers.ts b/src/mocks/mock-helpers.ts new file mode 100644 index 00000000..f5126373 --- /dev/null +++ b/src/mocks/mock-helpers.ts @@ -0,0 +1,9 @@ +import { BuildContext } from '../util/interfaces'; + +export function setContext(context: BuildContext) { +} + +export function readFileAsync(filePath: string) { + return Promise.resolve(); +} + diff --git a/src/transpile.ts b/src/transpile.ts index 18697c35..bdca0fcc 100644 --- a/src/transpile.ts +++ b/src/transpile.ts @@ -331,7 +331,6 @@ export function getTsConfig(context: BuildContext, tsConfigPath?: string): TsCon config = { options: parsedConfig.options, fileNames: parsedConfig.fileNames, - typingOptions: parsedConfig.typingOptions, raw: parsedConfig.raw }; } @@ -350,7 +349,6 @@ export function getTsConfigPath(context: BuildContext) { export interface TsConfig { options: ts.CompilerOptions; fileNames: string[]; - typingOptions: ts.TypingOptions; raw: any; } diff --git a/src/util/config.ts b/src/util/config.ts index 6183c019..d4c4dcec 100644 --- a/src/util/config.ts +++ b/src/util/config.ts @@ -3,7 +3,7 @@ import { BuildContext, TaskInfo } from './interfaces'; import { join, resolve } from 'path'; import { objectAssign } from './helpers'; import { FileCache } from './file-cache'; -import { SOURCE_MAP_TYPE_EXPENSIVE } from './constants'; +import * as Constants from './constants'; /** * Create a context object which is used by all the build tasks. @@ -55,56 +55,56 @@ export function generateContext(context?: BuildContext): BuildContext { context.isWatch = hasArg('--watch'); } - context.rootDir = resolve(context.rootDir || getConfigValue(context, '--rootDir', null, ENV_VAR_ROOT_DIR, ENV_VAR_ROOT_DIR.toLowerCase(), processCwd)); - setProcessEnvVar(ENV_VAR_ROOT_DIR, context.rootDir); + context.rootDir = resolve(context.rootDir || getConfigValue(context, '--rootDir', null, Constants.ENV_VAR_ROOT_DIR, Constants.ENV_VAR_ROOT_DIR.toLowerCase(), processCwd)); + setProcessEnvVar(Constants.ENV_VAR_ROOT_DIR, context.rootDir); - context.srcDir = resolve(context.srcDir || getConfigValue(context, '--srcDir', null, ENV_VAR_SRC_DIR, ENV_VAR_SRC_DIR.toLowerCase(), join(context.rootDir, SRC_DIR))); - setProcessEnvVar(ENV_VAR_SRC_DIR, context.srcDir); + context.srcDir = resolve(context.srcDir || getConfigValue(context, '--srcDir', null, Constants.ENV_VAR_SRC_DIR, Constants.ENV_VAR_SRC_DIR.toLowerCase(), join(context.rootDir, Constants.SRC_DIR))); + setProcessEnvVar(Constants.ENV_VAR_SRC_DIR, context.srcDir); - context.wwwDir = resolve(context.wwwDir || getConfigValue(context, '--wwwDir', null, ENV_VAR_WWW_DIR, ENV_VAR_WWW_DIR.toLowerCase(), join(context.rootDir, WWW_DIR))); - setProcessEnvVar(ENV_VAR_WWW_DIR, context.wwwDir); + context.wwwDir = resolve(context.wwwDir || getConfigValue(context, '--wwwDir', null, Constants.ENV_VAR_WWW_DIR, Constants.ENV_VAR_WWW_DIR.toLowerCase(), join(context.rootDir, Constants.WWW_DIR))); + setProcessEnvVar(Constants.ENV_VAR_WWW_DIR, context.wwwDir); - context.wwwIndex = join(context.wwwDir, WWW_INDEX_FILENAME); + context.wwwIndex = join(context.wwwDir, Constants.WWW_INDEX_FILENAME); - context.buildDir = resolve(context.buildDir || getConfigValue(context, '--buildDir', null, ENV_VAR_BUILD_DIR, ENV_VAR_BUILD_DIR.toLowerCase(), join(context.wwwDir, BUILD_DIR))); - setProcessEnvVar(ENV_VAR_BUILD_DIR, context.buildDir); + context.buildDir = resolve(context.buildDir || getConfigValue(context, '--buildDir', null, Constants.ENV_VAR_BUILD_DIR, Constants.ENV_VAR_BUILD_DIR.toLowerCase(), join(context.wwwDir, Constants.BUILD_DIR))); + setProcessEnvVar(Constants.ENV_VAR_BUILD_DIR, context.buildDir); - setProcessEnvVar(ENV_VAR_APP_SCRIPTS_DIR, join(__dirname, '..', '..')); + setProcessEnvVar(Constants.ENV_VAR_APP_SCRIPTS_DIR, join(__dirname, '..', '..')); - const generateSourceMap = getConfigValue(context, '--generateSourceMap', null, ENV_VAR_GENERATE_SOURCE_MAP, ENV_VAR_GENERATE_SOURCE_MAP.toLowerCase(), context.isProd || context.runMinifyJs ? null : 'true'); - setProcessEnvVar(ENV_VAR_GENERATE_SOURCE_MAP, generateSourceMap); + const generateSourceMap = getConfigValue(context, '--generateSourceMap', null, Constants.ENV_VAR_GENERATE_SOURCE_MAP, Constants.ENV_VAR_GENERATE_SOURCE_MAP.toLowerCase(), context.isProd || context.runMinifyJs ? null : 'true'); + setProcessEnvVar(Constants.ENV_VAR_GENERATE_SOURCE_MAP, generateSourceMap); - const sourceMapTypeValue = getConfigValue(context, '--sourceMapType', null, ENV_VAR_SOURCE_MAP_TYPE, ENV_VAR_SOURCE_MAP_TYPE.toLowerCase(), SOURCE_MAP_TYPE_EXPENSIVE); - setProcessEnvVar(ENV_VAR_SOURCE_MAP_TYPE, sourceMapTypeValue); + const sourceMapTypeValue = getConfigValue(context, '--sourceMapType', null, Constants.ENV_VAR_SOURCE_MAP_TYPE, Constants.ENV_VAR_SOURCE_MAP_TYPE.toLowerCase(), Constants.SOURCE_MAP_TYPE_EXPENSIVE); + setProcessEnvVar(Constants.ENV_VAR_SOURCE_MAP_TYPE, sourceMapTypeValue); - const tsConfigPathValue = getConfigValue(context, '--tsconfig', null, ENV_TS_CONFIG, ENV_TS_CONFIG.toLowerCase(), join(context.rootDir, 'tsconfig.json')); - setProcessEnvVar(ENV_TS_CONFIG, tsConfigPathValue); + const tsConfigPathValue = getConfigValue(context, '--tsconfig', null, Constants.ENV_TS_CONFIG, Constants.ENV_TS_CONFIG.toLowerCase(), join(context.rootDir, 'tsconfig.json')); + setProcessEnvVar(Constants.ENV_TS_CONFIG, tsConfigPathValue); - const appEntryPointPathValue = getConfigValue(context, '--appEntryPoint', null, ENV_APP_ENTRY_POINT, ENV_APP_ENTRY_POINT.toLowerCase(), join(context.srcDir, 'app', 'main.ts')); - setProcessEnvVar(ENV_APP_ENTRY_POINT, appEntryPointPathValue); + const appEntryPointPathValue = getConfigValue(context, '--appEntryPoint', null, Constants.ENV_APP_ENTRY_POINT, Constants.ENV_APP_ENTRY_POINT.toLowerCase(), join(context.srcDir, 'app', 'main.ts')); + setProcessEnvVar(Constants.ENV_APP_ENTRY_POINT, appEntryPointPathValue); - setProcessEnvVar(ENV_GLOB_UTIL, join(getProcessEnvVar(ENV_VAR_APP_SCRIPTS_DIR), 'dist', 'util', 'glob-util.js')); + setProcessEnvVar(Constants.ENV_GLOB_UTIL, join(getProcessEnvVar(Constants.ENV_VAR_APP_SCRIPTS_DIR), 'dist', 'util', 'glob-util.js')); - const cleanBeforeCopy = getConfigValue(context, '--cleanBeforeCopy', null, ENV_CLEAN_BEFORE_COPY, ENV_CLEAN_BEFORE_COPY.toLowerCase(), null); - setProcessEnvVar(ENV_CLEAN_BEFORE_COPY, cleanBeforeCopy); + const cleanBeforeCopy = getConfigValue(context, '--cleanBeforeCopy', null, Constants.ENV_CLEAN_BEFORE_COPY, Constants.ENV_CLEAN_BEFORE_COPY.toLowerCase(), null); + setProcessEnvVar(Constants.ENV_CLEAN_BEFORE_COPY, cleanBeforeCopy); - setProcessEnvVar(ENV_CLOSURE_JAR, join(getProcessEnvVar(ENV_VAR_APP_SCRIPTS_DIR), 'bin', 'closure-compiler.jar')); + setProcessEnvVar(Constants.ENV_CLOSURE_JAR, join(getProcessEnvVar(Constants.ENV_VAR_APP_SCRIPTS_DIR), 'bin', 'closure-compiler.jar')); - const outputJsFileName = getConfigValue(context, '--outputJsFileName', null, ENV_OUTPUT_JS_FILE_NAME, ENV_OUTPUT_JS_FILE_NAME.toLowerCase(), 'main.js'); - setProcessEnvVar(ENV_OUTPUT_JS_FILE_NAME, outputJsFileName); + const outputJsFileName = getConfigValue(context, '--outputJsFileName', null, Constants.ENV_OUTPUT_JS_FILE_NAME, Constants.ENV_OUTPUT_JS_FILE_NAME.toLowerCase(), 'main.js'); + setProcessEnvVar(Constants.ENV_OUTPUT_JS_FILE_NAME, outputJsFileName); - const outputJsMapFileName = getConfigValue(context, '--outputJsMapFileName', null, ENV_OUTPUT_JS_MAP_FILE_NAME, ENV_OUTPUT_JS_MAP_FILE_NAME.toLowerCase(), 'main.js.map'); - setProcessEnvVar(ENV_OUTPUT_JS_MAP_FILE_NAME, outputJsMapFileName); + const outputJsMapFileName = getConfigValue(context, '--outputJsMapFileName', null, Constants.ENV_OUTPUT_JS_MAP_FILE_NAME, Constants.ENV_OUTPUT_JS_MAP_FILE_NAME.toLowerCase(), 'main.js.map'); + setProcessEnvVar(Constants.ENV_OUTPUT_JS_MAP_FILE_NAME, outputJsMapFileName); - const outputCssFileName = getConfigValue(context, '--outputCssFileName', null, ENV_OUTPUT_CSS_FILE_NAME, ENV_OUTPUT_CSS_FILE_NAME.toLowerCase(), 'main.css'); - setProcessEnvVar(ENV_OUTPUT_CSS_FILE_NAME, outputCssFileName); + const outputCssFileName = getConfigValue(context, '--outputCssFileName', null, Constants.ENV_OUTPUT_CSS_FILE_NAME, Constants.ENV_OUTPUT_CSS_FILE_NAME.toLowerCase(), 'main.css'); + setProcessEnvVar(Constants.ENV_OUTPUT_CSS_FILE_NAME, outputCssFileName); - const outputCssMapFileName = getConfigValue(context, '--outputCssMapFileName', null, ENV_OUTPUT_CSS_MAP_FILE_NAME, ENV_OUTPUT_CSS_MAP_FILE_NAME.toLowerCase(), 'main.css.map'); - setProcessEnvVar(ENV_OUTPUT_CSS_MAP_FILE_NAME, outputCssMapFileName); + const outputCssMapFileName = getConfigValue(context, '--outputCssMapFileName', null, Constants.ENV_OUTPUT_CSS_MAP_FILE_NAME, Constants.ENV_OUTPUT_CSS_MAP_FILE_NAME.toLowerCase(), 'main.css.map'); + setProcessEnvVar(Constants.ENV_OUTPUT_CSS_MAP_FILE_NAME, outputCssMapFileName); - setProcessEnvVar(ENV_WEBPACK_FACTORY, join(getProcessEnvVar(ENV_VAR_APP_SCRIPTS_DIR), 'dist', 'webpack', 'ionic-webpack-factory.js')); + setProcessEnvVar(Constants.ENV_WEBPACK_FACTORY, join(getProcessEnvVar(Constants.ENV_VAR_APP_SCRIPTS_DIR), 'dist', 'webpack', 'ionic-webpack-factory.js')); - setProcessEnvVar(ENV_WEBPACK_LOADER, join(getProcessEnvVar(ENV_VAR_APP_SCRIPTS_DIR), 'dist', 'webpack', 'typescript-sourcemap-loader-memory.js')); + setProcessEnvVar(Constants.ENV_WEBPACK_LOADER, join(getProcessEnvVar(Constants.ENV_VAR_APP_SCRIPTS_DIR), 'dist', 'webpack', 'typescript-sourcemap-loader-memory.js')); if (!isValidBundler(context.bundler)) { context.bundler = bundlerStrategy(context); @@ -162,7 +162,7 @@ export function bundlerStrategy(context: BuildContext): string { // 1) User provided a rollup config via cmd line args let val: any = getArgValue('--rollup', '-r'); if (val) { - return BUNDLER_ROLLUP; + return Constants.BUNDLER_ROLLUP; } // 2) User provided both a rollup config and webpack config in package.json config @@ -178,13 +178,13 @@ export function bundlerStrategy(context: BuildContext): string { // 3) User provided a rollup config env var val = getProcessEnvVar('ionic_rollup'); if (val) { - return BUNDLER_ROLLUP; + return Constants.BUNDLER_ROLLUP; } // 4) User provided a rollup config in package.json config val = getPackageJsonConfig(context, 'ionic_rollup'); if (val) { - return BUNDLER_ROLLUP; + return Constants.BUNDLER_ROLLUP; } // 5) User set bundler through full arg @@ -206,12 +206,12 @@ export function bundlerStrategy(context: BuildContext): string { } // 8) Default to use webpack - return BUNDLER_WEBPACK; + return Constants.BUNDLER_WEBPACK; } function isValidBundler(bundler: any) { - return (bundler === BUNDLER_ROLLUP || bundler === BUNDLER_WEBPACK); + return (bundler === Constants.BUNDLER_ROLLUP || bundler === Constants.BUNDLER_WEBPACK); } @@ -405,32 +405,3 @@ function getAppPackageJsonData(context: BuildContext) { return appPackageJsonData; } - - -const BUILD_DIR = 'build'; -const SRC_DIR = 'src'; -const TMP_DIR = '.tmp'; -const WWW_DIR = 'www'; -const WWW_INDEX_FILENAME = 'index.html'; - -const ENV_VAR_ROOT_DIR = 'IONIC_ROOT_DIR'; -const ENV_VAR_SRC_DIR = 'IONIC_SRC_DIR'; -const ENV_VAR_WWW_DIR = 'IONIC_WWW_DIR'; -const ENV_VAR_BUILD_DIR = 'IONIC_BUILD_DIR'; -const ENV_VAR_APP_SCRIPTS_DIR = 'IONIC_APP_SCRIPTS_DIR'; -const ENV_VAR_GENERATE_SOURCE_MAP = 'IONIC_GENERATE_SOURCE_MAP'; -const ENV_VAR_SOURCE_MAP_TYPE = 'IONIC_SOURCE_MAP_TYPE'; -const ENV_TS_CONFIG = 'IONIC_TS_CONFIG'; -const ENV_APP_ENTRY_POINT = 'IONIC_APP_ENTRY_POINT'; -const ENV_GLOB_UTIL = 'IONIC_GLOB_UTIL'; -const ENV_CLEAN_BEFORE_COPY = 'IONIC_CLEAN_BEFORE_COPY'; -const ENV_CLOSURE_JAR = 'IONIC_CLOSURE_JAR'; -const ENV_OUTPUT_JS_FILE_NAME = 'IONIC_OUTPUT_JS_FILE_NAME'; -const ENV_OUTPUT_JS_MAP_FILE_NAME = 'IONIC_OUTPUT_JS_MAP_FILE_NAME'; -const ENV_OUTPUT_CSS_FILE_NAME = 'IONIC_OUTPUT_CSS_FILE_NAME'; -const ENV_OUTPUT_CSS_MAP_FILE_NAME = 'IONIC_OUTPUT_CSS_MAP_FILE_NAME'; -const ENV_WEBPACK_FACTORY = 'IONIC_WEBPACK_FACTORY'; -const ENV_WEBPACK_LOADER = 'IONIC_WEBPACK_LOADER'; - -export const BUNDLER_ROLLUP = 'rollup'; -export const BUNDLER_WEBPACK = 'webpack'; diff --git a/src/util/constants.ts b/src/util/constants.ts index 3b382e5e..1433be2d 100644 --- a/src/util/constants.ts +++ b/src/util/constants.ts @@ -6,3 +6,30 @@ export const DIRECTORY_DELETE_EVENT = 'unlinkDir'; export const SOURCE_MAP_TYPE_CHEAP = 'eval'; export const SOURCE_MAP_TYPE_EXPENSIVE = 'source-map'; + +export const BUILD_DIR = 'build'; +export const SRC_DIR = 'src'; +export const WWW_DIR = 'www'; +export const WWW_INDEX_FILENAME = 'index.html'; + +export const ENV_VAR_ROOT_DIR = 'IONIC_ROOT_DIR'; +export const ENV_VAR_SRC_DIR = 'IONIC_SRC_DIR'; +export const ENV_VAR_WWW_DIR = 'IONIC_WWW_DIR'; +export const ENV_VAR_BUILD_DIR = 'IONIC_BUILD_DIR'; +export const ENV_VAR_APP_SCRIPTS_DIR = 'IONIC_APP_SCRIPTS_DIR'; +export const ENV_VAR_GENERATE_SOURCE_MAP = 'IONIC_GENERATE_SOURCE_MAP'; +export const ENV_VAR_SOURCE_MAP_TYPE = 'IONIC_SOURCE_MAP_TYPE'; +export const ENV_TS_CONFIG = 'IONIC_TS_CONFIG'; +export const ENV_APP_ENTRY_POINT = 'IONIC_APP_ENTRY_POINT'; +export const ENV_GLOB_UTIL = 'IONIC_GLOB_UTIL'; +export const ENV_CLEAN_BEFORE_COPY = 'IONIC_CLEAN_BEFORE_COPY'; +export const ENV_CLOSURE_JAR = 'IONIC_CLOSURE_JAR'; +export const ENV_OUTPUT_JS_FILE_NAME = 'IONIC_OUTPUT_JS_FILE_NAME'; +export const ENV_OUTPUT_JS_MAP_FILE_NAME = 'IONIC_OUTPUT_JS_MAP_FILE_NAME'; +export const ENV_OUTPUT_CSS_FILE_NAME = 'IONIC_OUTPUT_CSS_FILE_NAME'; +export const ENV_OUTPUT_CSS_MAP_FILE_NAME = 'IONIC_OUTPUT_CSS_MAP_FILE_NAME'; +export const ENV_WEBPACK_FACTORY = 'IONIC_WEBPACK_FACTORY'; +export const ENV_WEBPACK_LOADER = 'IONIC_WEBPACK_LOADER'; + +export const BUNDLER_ROLLUP = 'rollup'; +export const BUNDLER_WEBPACK = 'webpack'; \ No newline at end of file diff --git a/src/util/helpers.ts b/src/util/helpers.ts index 82e70d08..73d8b99f 100644 --- a/src/util/helpers.ts +++ b/src/util/helpers.ts @@ -116,7 +116,7 @@ export function readFileAsync(filePath: string): Promise { }); } -export function unlinkAsync(filePath: string): Promise { +export function unlinkAsync(filePath: string): Promise { return new Promise((resolve, reject) => { unlink(filePath, (err: Error) => { if (err) { @@ -125,9 +125,11 @@ export function unlinkAsync(filePath: string): Promise { return resolve(); }); }); + + } -export function rimRafAsync(directoryPath: string) { +export function rimRafAsync(directoryPath: string): Promise { return new Promise((resolve, reject) => { remove(directoryPath, (err: Error) => { if (err) { @@ -138,7 +140,7 @@ export function rimRafAsync(directoryPath: string) { }); } -export function copyFileAsync(srcPath: string, destPath: string) { +export function copyFileAsync(srcPath: string, destPath: string): Promise { return new Promise((resolve, reject) => { const writeStream = createWriteStream(destPath); @@ -206,4 +208,4 @@ export function stringSplice(source: string, startIndex: number, numToDelete: nu export function toUnixPath(filePath: string) { return filePath.replace(/\\/g, '/'); -} \ No newline at end of file +} diff --git a/src/watch.ts b/src/watch.ts index a50f8f59..d3a8000e 100644 --- a/src/watch.ts +++ b/src/watch.ts @@ -53,7 +53,7 @@ export function watch(context?: BuildContext, configFile?: string) { function startWatchers(context: BuildContext, configFile: string) { const watchConfig: WatchConfig = fillConfigDefaults(configFile, taskInfo.defaultConfigFile); - const promises: Promise[] = []; + const promises: Promise[] = []; Object.keys(watchConfig).forEach((key) => { promises.push(startWatcher(key, watchConfig[key], context)); }); diff --git a/src/webpack.ts b/src/webpack.ts index 82b33f6b..d6182ab8 100644 --- a/src/webpack.ts +++ b/src/webpack.ts @@ -21,7 +21,7 @@ const INCREMENTAL_BUILD_SUCCESS = 'incremental_build_success'; * To mitigate this, store pending "webpack watch"/bundle update promises in this array and only resolve the * the most recent one. reject all others at that time with an IgnorableError. */ -let pendingPromises: Promise[] = []; +let pendingPromises: Promise[] = []; export function webpack(context: BuildContext, configFile: string) { configFile = getUserConfigFile(context, taskInfo, configFile); @@ -40,7 +40,7 @@ export function webpack(context: BuildContext, configFile: string) { } -export function webpackUpdate(changedFiles: ChangedFile[], context: BuildContext, configFile: string) { +export function webpackUpdate(changedFiles: ChangedFile[], context: BuildContext, configFile?: string) { const logger = new Logger('webpack update'); const webpackConfig = getWebpackConfig(context, configFile); Logger.debug('webpackUpdate: Starting Incremental Build'); @@ -68,7 +68,7 @@ export function webpackUpdate(changedFiles: ChangedFile[], context: BuildContext export function webpackWorker(context: BuildContext, configFile: string): Promise { const webpackConfig = getWebpackConfig(context, configFile); - let promise: Promise = null; + let promise: Promise = null; if (context.isWatch) { promise = runWebpackIncrementalBuild(!context.webpackWatch, context, webpackConfig); } else { @@ -140,7 +140,7 @@ function runWebpackIncrementalBuild(initializeWatch: boolean, context: BuildCont return promise; } -function handleWebpackBuildFailure(resolve: Function, reject: Function, error: Error, promise: Promise, pendingPromises: Promise[]) { +function handleWebpackBuildFailure(resolve: Function, reject: Function, error: Error, promise: Promise, pendingPromises: Promise[]) { // check if the promise if the last promise in the list of pending promises if (pendingPromises.length > 0 && pendingPromises[pendingPromises.length - 1] === promise) { // reject this one with a build error @@ -151,7 +151,7 @@ function handleWebpackBuildFailure(resolve: Function, reject: Function, error: E reject(new IgnorableError()); } -function handleWebpackBuildSuccess(resolve: Function, reject: Function, stats: any, promise: Promise, pendingPromises: Promise[]) { +function handleWebpackBuildSuccess(resolve: Function, reject: Function, stats: any, promise: Promise, pendingPromises: Promise[]) { // check if the promise if the last promise in the list of pending promises if (pendingPromises.length > 0 && pendingPromises[pendingPromises.length - 1] === promise) { Logger.debug('handleWebpackBuildSuccess: Resolving with Webpack data'); @@ -186,7 +186,8 @@ export function getWebpackConfig(context: BuildContext, configFile: string): Web } -export function getOutputDest(context: BuildContext, webpackConfig: WebpackConfig) { +export function getOutputDest(context: BuildContext) { + const webpackConfig = getWebpackConfig(context, null); return join(webpackConfig.output.path, webpackConfig.output.filename); }