diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 00000000..918461d6 --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,42 @@ +{ + "extends": "airbnb-base", + "env": { + "jasmine": true + }, + "rules": { + "arrow-body-style": "off", + "arrow-parens": "off", + "comma-dangle": "off", + "consistent-return": "off", + "default-case": "off", + "func-names": "off", + "global-require": "off", + "import/newline-after-import": "off", + "import/no-dynamic-require": "off", + "import/order": "off", + "lines-around-directive": "off", + "no-console": "off", + "no-multi-assign": "off", + "no-param-reassign": "off", + "no-plusplus": "off", + "no-use-before-define": "off", + "no-useless-escape": "off", + "object-curly-newline": "off", + "object-shorthand": "off", + "operator-linebreak": "off", + "padded-blocks": "off", + "prefer-arrow-callback": "off", + "prefer-const": "off", + "prefer-destructuring": "off", + "prefer-rest-params": "off", + "prefer-spread": "off", + "prefer-template": "off", + "quote-props": "off", + "quotes": ["error", "single", { + "allowTemplateLiterals": true, + "avoidEscape": true + }], + "spaced-comment": "off", + "strict": "off" + } +} diff --git a/.nvmrc b/.nvmrc index 5debbed2..03128968 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -lts/carbon +lts/dubnium diff --git a/.travis.yml b/.travis.yml index a9a99fc9..8378a6c2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,10 +6,6 @@ env: - TEST_COMMAND=coverage - TEST_COMMAND=e2e -node_js: - - "8" - - "6" - script: "npm run lint && npm run $TEST_COMMAND" addons: diff --git a/CHANGELOG.md b/CHANGELOG.md index f977a839..bb7a34d8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # 1.30.0 (2018-11-26) -- Added `SkyAuthHttpClientModule` that can be used in conjunction with Angular's `HttpClient` to make authenticated calls to services backed by Blackbaud ID. (blackbaud/skyux-http#11)[https://github.com/blackbaud/skyux-http/pull/11] +- Added `SkyAuthHttpClientModule` that can be used in conjunction with Angular's `HttpClient` to make authenticated calls to services backed by Blackbaud ID. [blackbaud/skyux-http#11](https://github.com/blackbaud/skyux-http/pull/11) - Fixed coverage reports to accurately match against configured thresholds. [#499](https://github.com/blackbaud/skyux-builder/pull/499) # 1.29.0 (2018-11-09) diff --git a/README.md b/README.md index 5cbda92b..78405f70 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ -# @blackbaud/skyux-builder +# @skyux-sdk/builder -[![npm](https://img.shields.io/npm/v/@blackbaud/skyux-builder.svg)](https://www.npmjs.com/package/@blackbaud/skyux-builder) +[![npm](https://img.shields.io/npm/v/@skyux-sdk/builder.svg)](https://www.npmjs.com/package/@skyux-sdk/builder) [![status](https://travis-ci.org/blackbaud/skyux-builder.svg?branch=master)](https://travis-ci.org/blackbaud/skyux-builder) Builds the output of a SKY UX application. See [skyux-cli](https://github.com/blackbaud/skyux-cli) for more information. diff --git a/cli/build-public-library.js b/cli/build-public-library.js index 16da37dc..833f52d9 100644 --- a/cli/build-public-library.js +++ b/cli/build-public-library.js @@ -57,7 +57,7 @@ function getEntryPointFiles() { } function writeTSConfig() { - var config = { + const config = { 'compilerOptions': { 'target': 'es5', 'module': 'es2015', @@ -66,6 +66,8 @@ function writeTSConfig() { 'experimentalDecorators': true, 'allowSyntheticDefaultImports': true, 'sourceMap': true, + 'importHelpers': true, + 'noEmitHelpers': true, 'noImplicitAny': true, 'declaration': true, 'skipLibCheck': true, @@ -81,7 +83,7 @@ function writeTSConfig() { 'rootDir': skyPagesConfigUtil.spaPathTemp(), 'baseUrl': '.', 'paths': { - '@blackbaud/skyux-builder/*': [ + '@skyux-sdk/builder/*': [ '*' ], '.skypageslocales/*': [ diff --git a/cli/e2e.js b/cli/e2e.js index 84ac5772..36241295 100644 --- a/cli/e2e.js +++ b/cli/e2e.js @@ -33,12 +33,6 @@ function killServers(exitCode) { seleniumServer = null; } - // Catch protractor's "Kitchen Sink" error. - if (exitCode === 199) { - logger.warn('Supressing protractor\'s "kitchen sink" error 199'); - exitCode = 0; - } - server.stop(); logger.info(`Execution Time: ${(new Date().getTime() - start) / 1000} seconds`); logger.info(`Exiting process with ${exitCode}`); diff --git a/cli/generate.js b/cli/generate.js index d9e057b0..bd2e7d5a 100644 --- a/cli/generate.js +++ b/cli/generate.js @@ -87,7 +87,7 @@ function generateComponentSpec(pathParts, fileName, name, nameSnakeCase, force) import { expect, SkyAppTestModule -} from '@blackbaud/skyux-builder/runtime/testing/browser'; +} from '@skyux-sdk/testing'; import { ${name} diff --git a/cli/pact.js b/cli/pact.js index df307776..59aeee33 100644 --- a/cli/pact.js +++ b/cli/pact.js @@ -103,7 +103,7 @@ function pact(command, argv) { .on('connect', () => { logger .info( - `Pact proxy server successfully started on http://localhost:${ports[ports.length - 1]}` + `Pact proxy server successfully started on http://localhost:${ports[ports.length - 1]}` ); }) .listen(ports[ports.length - 1], 'localhost'); diff --git a/cli/utils/browser.js b/cli/utils/browser.js index fba8845a..443ca101 100644 --- a/cli/utils/browser.js +++ b/cli/utils/browser.js @@ -2,7 +2,7 @@ 'use strict'; const util = require('util'); -const open = require('open'); +const open = require('opn'); const logger = require('@blackbaud/skyux-logger'); const hostUtils = require('../../utils/host-utils'); const skyPagesConfigUtil = require('../../config/sky-pages/sky-pages.config'); @@ -79,12 +79,16 @@ function browser(argv, skyPagesConfig, stats, port) { localUrl += queryStringBase; logger.info(`Launching Local URL: ${localUrl}`); - open(localUrl, argv.browser); + open(localUrl, { + app: argv.browser + }); break; case 'host': logger.info(`Launching Host URL: ${hostUrl}`); - open(hostUrl, argv.browser); + open(hostUrl, { + app: argv.browser + }); break; default: diff --git a/cli/utils/run-build.js b/cli/utils/run-build.js index a5621d5e..cafb52ad 100644 --- a/cli/utils/run-build.js +++ b/cli/utils/run-build.js @@ -16,7 +16,7 @@ const runCompiler = require('./run-compiler'); const tsLinter = require('./ts-linter'); function writeTSConfig() { - var config = { + const config = { 'compilerOptions': { 'target': 'es5', 'module': 'es2015', @@ -24,9 +24,9 @@ function writeTSConfig() { 'emitDecoratorMetadata': true, 'experimentalDecorators': true, 'sourceMap': true, + 'importHelpers': true, 'noEmitHelpers': true, 'noImplicitAny': true, - 'rootDir': '.', 'inlineSources': true, 'declaration': true, 'skipLibCheck': true, @@ -34,13 +34,14 @@ function writeTSConfig() { 'es2015', 'dom' ], - 'types': [ - 'jasmine', - 'node' + 'typeRoots': [ + skyPagesConfigUtil.spaPath('node_modules/@types') ] }, - 'files': [ - './app/app.module.ts' + 'include': [ + skyPagesConfigUtil.outPath('runtime', '**', '*'), + skyPagesConfigUtil.outPath('src', '**', '*'), + skyPagesConfigUtil.spaPathTempSrc('**', '*') ], 'exclude': [ 'node_modules', @@ -48,12 +49,7 @@ function writeTSConfig() { '**/*.spec.ts' ], 'compileOnSave': false, - 'buildOnSave': false, - 'angularCompilerOptions': { - 'debug': true, - 'genDir': './ngfactory', - 'skipMetadataEmit': true - } + 'buildOnSave': false }; fs.writeJSONSync(skyPagesConfigUtil.spaPathTempSrc('tsconfig.json'), config); @@ -69,15 +65,11 @@ function stageAot(skyPagesConfig, assetsBaseUrl, assetsRel) { // Node package name rather than a local path; otherwise TypeScript will treat them as // different types and Angular will throw an error when trying to inject an instance // of a class (such as SkyAuthHttp) by its type. - runtimeAlias: '@blackbaud/skyux-builder/runtime', + runtimeAlias: '@skyux-sdk/builder/runtime', useTemplateUrl: true } }; - if (skyPagesConfig && skyPagesConfig.skyux && skyPagesConfig.skyux.importPath) { - skyPagesConfigOverrides.runtime.skyuxPathAlias = '../../' + skyPagesConfig.skyux.importPath; - } - const spaPathTempSrc = skyPagesConfigUtil.spaPathTempSrc(); fs.ensureDirSync(spaPathTempSrc); @@ -92,7 +84,23 @@ function stageAot(skyPagesConfig, assetsBaseUrl, assetsRel) { // before writing the file to disk. skyPagesModuleSource = assetsProcessor.processAssets( skyPagesModuleSource, - assetsProcessor.getAssetsUrl(skyPagesConfig, assetsBaseUrl, assetsRel) + assetsProcessor.getAssetsUrl(skyPagesConfig, assetsBaseUrl, assetsRel), + (filePathWithHash, physicalFilePath) => { + + // File contents are not respected by @ngtools/webpack, + // so we need to write the locale files ourselves. + // See: https://github.com/angular/angular-cli/issues/6701 + // See: https://github.com/angular/angular-cli/issues/8870 + const path = require('path'); + const newPath = path.resolve( + skyPagesConfigUtil.spaPath('dist'), + filePathWithHash + ); + + fs.ensureFileSync(newPath); + const contents = fs.readFileSync(physicalFilePath, { encoding: 'utf-8' }); + fs.writeFileSync(newPath, contents); + } ); fs.copySync( @@ -121,6 +129,10 @@ function cleanupAot() { fs.removeSync(skyPagesConfigUtil.spaPathTemp()); } +function cleanupDist() { + fs.removeSync(skyPagesConfigUtil.spaPath('dist')); +} + function buildServe(argv, skyPagesConfig, webpack, isAot) { const base = skyPagesConfigUtil.getAppBase(skyPagesConfig); return server @@ -170,6 +182,7 @@ function buildCompiler(argv, skyPagesConfig, webpack, isAot) { * @param {*} cancelProcessExit */ function build(argv, skyPagesConfig, webpack) { + cleanupDist(); const lintResult = tsLinter.lintSync(); const isAot = skyPagesConfig && @@ -178,12 +191,12 @@ function build(argv, skyPagesConfig, webpack) { if (lintResult.exitCode > 0) { return Promise.reject(lintResult.errors); - } else { - localeAssetsProcessor.prepareLocaleFiles(); - const name = argv.serve ? buildServe : buildCompiler; - - return name(argv, skyPagesConfig, webpack, isAot); } + + localeAssetsProcessor.prepareLocaleFiles(); + const name = argv.serve ? buildServe : buildCompiler; + + return name(argv, skyPagesConfig, webpack, isAot); } module.exports = build; diff --git a/cli/utils/ts-linter.js b/cli/utils/ts-linter.js index da6f353b..61ca1e4a 100644 --- a/cli/utils/ts-linter.js +++ b/cli/utils/ts-linter.js @@ -6,7 +6,6 @@ const logger = require('@blackbaud/skyux-logger'); const skyPagesConfigUtil = require('../../config/sky-pages/sky-pages.config'); const flags = [ - '--type-check', '--project', skyPagesConfigUtil.spaPath('tsconfig.json'), '--config', diff --git a/cli/version.js b/cli/version.js index 0a0a6f03..013cf9dd 100644 --- a/cli/version.js +++ b/cli/version.js @@ -10,7 +10,7 @@ const logger = require('@blackbaud/skyux-logger'); */ function version() { const packageJson = require(path.resolve(__dirname, '..', 'package.json')); - logger.info('@blackbaud/skyux-builder: %s', packageJson.version); + logger.info('@skyux-sdk/builder: %s', packageJson.version); } module.exports = version; diff --git a/config/karma/dev-runtime.karma.conf.js b/config/karma/dev-runtime.karma.conf.js index 619fe91c..101f90a1 100644 --- a/config/karma/dev-runtime.karma.conf.js +++ b/config/karma/dev-runtime.karma.conf.js @@ -2,7 +2,7 @@ 'use strict'; function addRuntimeAlias(webpackConfig, runtimePath, path) { - webpackConfig.resolve.alias['@blackbaud/skyux-builder/runtime' + path] = runtimePath + path; + webpackConfig.resolve.alias['@skyux-sdk/builder/runtime' + path] = runtimePath + path; } /** diff --git a/config/karma/dev-src-app.karma.conf.js b/config/karma/dev-src-app.karma.conf.js index 16456633..d869d1e4 100644 --- a/config/karma/dev-src-app.karma.conf.js +++ b/config/karma/dev-src-app.karma.conf.js @@ -36,11 +36,7 @@ function getConfig(config) { // This is needed exclusively for internal runtime unit tests, // which is why it's here instead of alias-builder or the shared test.webpack.config.js // It's relative from src/app/ - webpackConfig.resolve.alias['@blackbaud/skyux-builder/runtime'] = runtimePath; - - // Instead of adding skyux2 as a dependency of skyux-builder - webpackConfig.resolve.alias['@skyux/theme/css/sky.css'] = - '../../utils/runtime-test-skyux.css'; + webpackConfig.resolve.alias['@skyux-sdk/builder/runtime'] = runtimePath; // Remove sky-style-loader delete config.preprocessors['../../utils/spec-styles.js']; diff --git a/config/karma/pact.karma.conf.js b/config/karma/pact.karma.conf.js index fc29e3de..3ec7d3fa 100644 --- a/config/karma/pact.karma.conf.js +++ b/config/karma/pact.karma.conf.js @@ -21,7 +21,6 @@ function getConfig(config) { skyPagesConfig.runtime.pactConfig.pactProxyServer = pactServers.getPactProxyServer(); if (skyPagesConfig.skyux.pacts) { - var i = 0; skyPagesConfig.skyux.pacts.forEach((pact) => { // set pact settings not specified in config file pact.log = pact.log || path.resolve(process.cwd(), 'logs', `pact-${pact.provider}.log`); @@ -29,8 +28,6 @@ function getConfig(config) { pact.host = pactServers.getPactServer(pact.provider).host; pact.port = pactServers.getPactServer(pact.provider).port; pact.pactFileWriteMode = pact.pactFileWriteMode || 'overwrite'; - - i++; }); } else { logger.error('No pact entry in configuration!'); @@ -38,8 +35,11 @@ function getConfig(config) { config.set({ frameworks: config.frameworks.concat('pact'), - files: config.files.concat(path.resolve(process.cwd(), 'node_modules/@pact-foundation/pact-web', - `pact-web.js`)), + files: config.files.concat(path.resolve( + process.cwd(), + 'node_modules/@pact-foundation/pact-web', + `pact-web.js` + )), pact: skyPagesConfig.skyux.pacts, plugins: config.plugins.concat('@pact-foundation/karma-pact'), webpack: testWebpackConfig.getWebpackConfig(skyPagesConfig, argv) diff --git a/config/protractor/protractor-dev.conf.js b/config/protractor/protractor-dev.conf.js index e494387a..0b550f68 100644 --- a/config/protractor/protractor-dev.conf.js +++ b/config/protractor/protractor-dev.conf.js @@ -35,7 +35,7 @@ let config = { } else { const url = 'https://github.com/blackbaud/skyux-template'; - const branch = 'builder-dev'; + const branch = 'builder-dev-rc-rename-package'; console.log('Running command using full install.'); common.rimrafPromise(common.tmp) @@ -62,7 +62,7 @@ let config = { }); // Remove any installed versions of Builder. - delete spaPkgJson.devDependencies['@blackbaud/skyux-builder']; + delete spaPkgJson.devDependencies['@skyux-sdk/builder']; fs.writeJsonSync(spaPkgPath, spaPkgJson, { spaces: 2 }); }) @@ -92,7 +92,7 @@ let config = { file, path.resolve( common.tmp, - `node_modules/@blackbaud/skyux-builder/${file}` + `node_modules/@skyux-sdk/builder/${file}` ) ); }); diff --git a/config/sky-pages/sky-pages.config.js b/config/sky-pages/sky-pages.config.js index 39f08afb..32fc8825 100644 --- a/config/sky-pages/sky-pages.config.js +++ b/config/sky-pages/sky-pages.config.js @@ -78,7 +78,6 @@ module.exports = { srcPath: 'src/app/', spaPathAlias: 'sky-pages-spa', skyPagesOutAlias: 'sky-pages-internal', - skyuxPathAlias: '@blackbaud/skyux/dist', useTemplateUrl: false }, skyux: skyuxConfig @@ -117,7 +116,7 @@ module.exports = { /** * Takes one or more path parts and returns the fully-qualified path to the file - * contained in this project (@blackbaud/skyux-builder). + * contained in this project (@skyux-sdk/builder). * @returns {String} The fully-qualified path. */ outPath: function () { diff --git a/config/webpack/alias-builder.js b/config/webpack/alias-builder.js index 8f71c5c5..c65aa3f2 100644 --- a/config/webpack/alias-builder.js +++ b/config/webpack/alias-builder.js @@ -5,6 +5,11 @@ const fs = require('fs'); const path = require('path'); const skyPagesConfigUtil = require('../sky-pages/sky-pages.config'); +// This will fix a mapping bug for the latest version of rxjs-compat. +// See: https://github.com/ReactiveX/rxjs/issues/4070#issuecomment-429191227 +const rxPaths = require('rxjs/_esm5/path-mapping')(); +rxPaths['rxjs/internal/Observable'] = 'rxjs/_esm5/internal/Observable'; + function spaPath() { return skyPagesConfigUtil.spaPath.apply(skyPagesConfigUtil, arguments); } @@ -21,33 +26,23 @@ function outPath() { * @param {String} moduleName * @param {String} path */ -function setSpaAlias(alias, moduleName, path) { - let resolvedPath = spaPath(path); +function setSpaAlias(alias, moduleName, filePath) { + let resolvedPath = spaPath(filePath); if (!fs.existsSync(resolvedPath)) { - resolvedPath = outPath(path); + resolvedPath = outPath(filePath); } alias['sky-pages-internal/' + moduleName] = resolvedPath; } module.exports = { - buildAliasList: function (skyPagesConfig) { + buildAliasList: function () { let alias = { 'sky-pages-spa/src': spaPath('src'), 'sky-pages-internal/runtime': outPath('runtime') }; - // Order here is very important; the more specific CSS alias must go before - // the more generic dist one. - if (skyPagesConfig.skyux.cssPath) { - alias['@skyux/theme/css/sky.css'] = spaPath(skyPagesConfig.skyux.cssPath); - } - - if (skyPagesConfig.skyux.importPath) { - alias['@blackbaud/skyux/dist'] = spaPath(skyPagesConfig.skyux.importPath); - } - setSpaAlias( alias, 'src/app/app-extras.module', @@ -56,6 +51,8 @@ module.exports = { setSpaAlias(alias, 'src/main', path.join('src', 'main.ts')); + Object.assign(alias, rxPaths); + return alias; } }; diff --git a/config/webpack/build-aot.webpack.config.js b/config/webpack/build-aot.webpack.config.js index 8a65bfd2..af95577a 100644 --- a/config/webpack/build-aot.webpack.config.js +++ b/config/webpack/build-aot.webpack.config.js @@ -1,9 +1,8 @@ /*jslint node: true */ 'use strict'; -const webpack = require('webpack'); const webpackMerge = require('webpack-merge'); -const ngtools = require('@ngtools/webpack'); +const { AngularCompilerPlugin } = require('@ngtools/webpack'); const skyPagesConfigUtil = require('../sky-pages/sky-pages.config'); const SaveMetadata = require('../../plugin/save-metadata'); @@ -28,39 +27,40 @@ function getWebpackConfig(skyPagesConfig, argv) { }); return webpackMerge(commonConfig, { + mode: 'production', + entry: { polyfills: [skyPagesConfigUtil.spaPathTempSrc('polyfills.ts')], - vendor: [skyPagesConfigUtil.spaPathTempSrc('vendor.ts')], - skyux: [skyPagesConfigUtil.spaPathTempSrc('skyux.ts')], app: [skyPagesConfigUtil.spaPathTempSrc('main-internal.aot.ts')] }, - + // Disable sourcemaps for production: // https://webpack.js.org/configuration/devtool/#production - devtool: undefined, - + devtool: false, + module: { rules: [ { - test: /\.ts$/, - loader: '@ngtools/webpack' + test: /(?:\.ngfactory\.js|\.ngstyle\.js|\.ts)$/, + loaders: ['@ngtools/webpack'] + }, + { + test: /\.js$/, + loader: '@angular-devkit/build-optimizer/webpack-loader', + options: { + sourceMap: false + } } ] }, plugins: [ - new ngtools.AotPlugin({ + new AngularCompilerPlugin({ tsConfigPath: skyPagesConfigUtil.spaPathTempSrc('tsconfig.json'), - entryModule: skyPagesConfigUtil.spaPathTempSrc('app', 'app.module') + '#AppModule', + mainPath: skyPagesConfigUtil.spaPathTempSrc('main-internal.aot.ts'), // Type checking handled by Builder's ts-linter utility. typeChecking: false }), - SaveMetadata, - new webpack.optimize.UglifyJsPlugin({ - beautify: false, - comments: false, - compress: { warnings: false }, - mangle: { screw_ie8: true, keep_fnames: true } - }) + SaveMetadata ] }); } diff --git a/config/webpack/build-public-library.webpack.config.js b/config/webpack/build-public-library.webpack.config.js index b86a892f..f2ee62eb 100644 --- a/config/webpack/build-public-library.webpack.config.js +++ b/config/webpack/build-public-library.webpack.config.js @@ -1,9 +1,8 @@ /*jslint node: true */ 'use strict'; -const ngtools = require('@ngtools/webpack'); +const { AngularCompilerPlugin } = require('@ngtools/webpack'); const fs = require('fs-extra'); -const webpack = require('webpack'); const skyPagesConfigUtil = require('../sky-pages/sky-pages.config'); function parseRegExp(name) { @@ -48,6 +47,8 @@ function getWebpackConfig(skyPagesConfig) { .map(key => parseRegExp(key)); return { + mode: 'production', + entry: skyPagesConfigUtil.spaPathTemp('index.ts'), output: { path: skyPagesConfigUtil.spaPath('dist', 'bundles'), @@ -82,19 +83,11 @@ function getWebpackConfig(skyPagesConfig) { }, plugins: [ // Generates an AoT JavaScript bundle. - // TODO: Remove this in favor of Angular's native library bundler, - // once we've upgraded to Angular version 6. - new ngtools.AotPlugin({ + new AngularCompilerPlugin({ tsConfigPath: skyPagesConfigUtil.spaPathTemp('tsconfig.json'), entryModule: skyPagesConfigUtil.spaPathTemp('main.ts') + '#SkyLibPlaceholderModule', - sourceMap: true - }), - - new webpack.optimize.UglifyJsPlugin({ - beautify: false, - comments: false, - compress: { warnings: false }, - mangle: { screw_ie8: true, keep_fnames: true } + sourceMap: false, + typeChecking: false }) ] }; diff --git a/config/webpack/build.webpack.config.js b/config/webpack/build.webpack.config.js index 029eb2c3..e118a722 100644 --- a/config/webpack/build.webpack.config.js +++ b/config/webpack/build.webpack.config.js @@ -1,7 +1,6 @@ /*jslint node: true */ 'use strict'; -const webpack = require('webpack'); const webpackMerge = require('webpack-merge'); const SaveMetadata = require('../../plugin/save-metadata'); @@ -12,9 +11,13 @@ const SaveMetadata = require('../../plugin/save-metadata'); */ function getWebpackConfig(skyPagesConfig, argv) { const common = require('./common.webpack.config'); + const commonConfig = common.getWebpackConfig(skyPagesConfig, argv); + + return webpackMerge(commonConfig, { + mode: 'production', + + devtool: false, - return webpackMerge(common.getWebpackConfig(skyPagesConfig, argv), { - devtool: 'source-map', module: { rules: [ { @@ -38,13 +41,7 @@ function getWebpackConfig(skyPagesConfig, argv) { ] }, plugins: [ - SaveMetadata, - new webpack.optimize.UglifyJsPlugin({ - beautify: false, - comments: false, - mangle: { screw_ie8: true, keep_fnames: true }, - sourceMap: true - }) + SaveMetadata ] }); } diff --git a/config/webpack/common.webpack.config.js b/config/webpack/common.webpack.config.js index 9c63030b..37ab00fc 100644 --- a/config/webpack/common.webpack.config.js +++ b/config/webpack/common.webpack.config.js @@ -6,7 +6,6 @@ const webpack = require('webpack'); const HtmlWebpackPlugin = require('html-webpack-plugin'); const SimpleProgressWebpackPlugin = require('simple-progress-webpack-plugin'); const LoaderOptionsPlugin = require('webpack/lib/LoaderOptionsPlugin'); -const CommonsChunkPlugin = require('webpack/lib/optimize/CommonsChunkPlugin'); const ContextReplacementPlugin = require('webpack/lib/ContextReplacementPlugin'); const { OutputKeepAlivePlugin } = require('../../plugin/output-keep-alive'); const skyPagesConfigUtil = require('../sky-pages/sky-pages.config'); @@ -21,6 +20,7 @@ function outPath() { } function getLogFormat(skyPagesConfig, argv) { + // eslint-disable-next-line no-prototype-builtins if (argv.hasOwnProperty('logFormat')) { return argv.logFormat; } @@ -71,10 +71,6 @@ function getWebpackConfig(skyPagesConfig, argv = {}) { skyux: skyPagesConfig.skyux }), - new CommonsChunkPlugin({ - name: ['skyux', 'vendor', 'polyfills'] - }), - new webpack.DefinePlugin({ 'skyPagesConfig': JSON.stringify(skyPagesConfig) }), @@ -93,6 +89,13 @@ function getWebpackConfig(skyPagesConfig, argv = {}) { {} ), + // See: https://github.com/angular/angular/issues/20357#issuecomment-343683491 + new ContextReplacementPlugin( + /\@angular(\\|\/)core(\\|\/)fesm5/, + spaPath('src'), + {} + ), + new OutputKeepAlivePlugin({ enabled: argv['output-keep-alive'] }) @@ -109,14 +112,12 @@ function getWebpackConfig(skyPagesConfig, argv = {}) { return { entry: { polyfills: [outPath('src', 'polyfills.ts')], - vendor: [outPath('src', 'vendor.ts')], - skyux: [outPath('src', 'skyux.ts')], app: [appPath] }, output: { - filename: '[name].js', - chunkFilename: '[id].chunk.js', - path: spaPath('dist'), + filename: '[name].[contenthash].js', + chunkFilename: '[name].[contenthash].chunk.js', + path: spaPath('dist') }, resolveLoader: { modules: resolves @@ -168,12 +169,41 @@ function getWebpackConfig(skyPagesConfig, argv = {}) { loader: 'raw-loader' }, { - test: /\.json$/, - loader: 'json-loader' + // Mark files inside `@angular/core` as using SystemJS style dynamic imports. + // Removing this will cause deprecation warnings to appear. + // See: https://github.com/angular/angular/issues/21560#issuecomment-433601967 + test: /[\/\\]@angular[\/\\]core[\/\\].+\.js$/, + parser: { + system: true + } } ] }, - plugins + plugins, + optimization: { + moduleIds: 'hashed', + noEmitOnErrors: true, + splitChunks: { + chunks: 'all', + cacheGroups: { + vendor: { + test: /[\\/]node_modules[\\/]/, + name: 'vendor', + priority: -3 // zero is default + }, + polyfill: { + test: /[\\/]node_modules[\\/](core-js|web-animations-js|zone\.js)[\\/]/, + name: 'pollyfill', // Chunk names cannot match an entry point. + priority: -2 + }, + skyux: { + test: /[\\/]node_modules[\\/]@skyux[\\/]/, + name: 'skyux', + priority: -1 + } + } + } + } }; } diff --git a/config/webpack/serve.webpack.config.js b/config/webpack/serve.webpack.config.js index bd55af22..94e72fc0 100644 --- a/config/webpack/serve.webpack.config.js +++ b/config/webpack/serve.webpack.config.js @@ -35,8 +35,22 @@ function getWebpackConfig(argv, skyPagesConfig) { const common = require('./common.webpack.config').getWebpackConfig(skyPagesConfig, argv); + // Revert to environment defaults when serving. + delete common.optimization; + return webpackMerge(common, { + mode: 'development', + + devtool: 'source-map', + watch: true, + + // Do not use hashes during a serve. + output: { + filename: '[name].js', + chunkFilename: '[name].chunk.js' + }, + module: { rules: [ { @@ -61,11 +75,13 @@ function getWebpackConfig(argv, skyPagesConfig) { } ] }, + devServer: { compress: true, inline: true, stats: false, hot: argv.hmr, + disableHostCheck: true, contentBase: path.join(process.cwd(), 'src', 'app'), headers: { 'Access-Control-Allow-Origin': '*' @@ -77,9 +93,13 @@ function getWebpackConfig(argv, skyPagesConfig) { key: fs.readFileSync(path.join(__dirname, '../../ssl/server.key')), cert: fs.readFileSync(path.join(__dirname, '../../ssl/server.crt')) }, + watchOptions: { + aggregateTimeout: 300, + poll: 1000 + }, publicPath: skyPagesConfigUtil.getAppBase(skyPagesConfig) }, - devtool: 'source-map', + plugins: [ new NamedModulesPlugin(), WebpackPluginDone, diff --git a/config/webpack/test.webpack.config.js b/config/webpack/test.webpack.config.js index 1aaebc97..dd70c587 100644 --- a/config/webpack/test.webpack.config.js +++ b/config/webpack/test.webpack.config.js @@ -44,6 +44,8 @@ function getWebpackConfig(skyPagesConfig, argv) { let alias = aliasBuilder.buildAliasList(skyPagesConfig); let config = { + mode: 'development', + devtool: 'inline-source-map', resolveLoader: { @@ -100,7 +102,7 @@ function getWebpackConfig(skyPagesConfig, argv) { loader: 'angular2-template-loader' } ], - exclude: [/\.e2e\.ts$/] + exclude: [/\.e2e-spec\.ts$/] }, { test: /\.s?css$/, @@ -111,8 +113,13 @@ function getWebpackConfig(skyPagesConfig, argv) { loader: 'raw-loader' }, { - test: /\.json$/, - loader: 'json-loader' + // Mark files inside `@angular/core` as using SystemJS style dynamic imports. + // Removing this will cause deprecation warnings to appear. + // See: https://github.com/angular/angular/issues/21560#issuecomment-433601967 + test: /[\/\\]@angular[\/\\]core[\/\\].+\.js$/, + parser: { + system: true + } } ] }, @@ -143,6 +150,14 @@ function getWebpackConfig(skyPagesConfig, argv) { /angular(\\|\/)core(\\|\/)@angular/, skyPagesConfigUtil.spaPath('src'), {} + ), + + // Suppress the "request of a dependency is an expression" warnings. + // See: https://github.com/angular/angular/issues/20357#issuecomment-343683491 + new ContextReplacementPlugin( + /\@angular(\\|\/)core(\\|\/)fesm5/, + spaPath('src'), + {} ) ] }; diff --git a/e2e/shared/cli.js b/e2e/shared/cli.js index bf65ed7b..771f3381 100644 --- a/e2e/shared/cli.js +++ b/e2e/shared/cli.js @@ -2,7 +2,7 @@ 'use strict'; const minimist = require('minimist'); -const cli = require('../../.e2e-tmp/node_modules/@blackbaud/skyux-builder/index'); +const cli = require('../../.e2e-tmp/node_modules/@skyux-sdk/builder/index'); const argv = minimist(process.argv.slice(2)); cli.runCommand(argv._[0], argv); diff --git a/e2e/shared/common.js b/e2e/shared/common.js index 0291065e..e4b3af73 100644 --- a/e2e/shared/common.js +++ b/e2e/shared/common.js @@ -54,10 +54,10 @@ function bindServe() { webpackServer.stderr.on('data', data => log(data)); webpackServer.stdout.on('data', data => { const dataAsString = log(data); - if (dataAsString.indexOf('webpack: Compiled successfully.') > -1) { + if (dataAsString.indexOf('Compiled successfully.') > -1) { resolve(_port); } - if (dataAsString.indexOf('webpack: Failed to compile.') > -1) { + if (dataAsString.indexOf('Failed to compile.') > -1) { reject(dataAsString); } }); diff --git a/e2e/shared/tests.js b/e2e/shared/tests.js index 8cedfb0a..94e0b294 100644 --- a/e2e/shared/tests.js +++ b/e2e/shared/tests.js @@ -3,6 +3,7 @@ 'use strict'; const fs = require('fs'); +const glob = require('glob'); const path = require('path'); const common = require('./common'); @@ -15,15 +16,22 @@ module.exports = { verifyFiles: (done) => { [ - 'app.js', 'index.html', - 'metadata.json', - 'polyfills.js', - 'skyux.js', - 'vendor.js' + 'metadata.json' ].forEach(file => { expect(fs.existsSync(path.resolve(common.tmp, 'dist', file))).toEqual(true); }); + + [ + 'app.*.js', + 'polyfills.*.js', + 'skyux.*.chunk.js', + 'vendor.*.chunk.js' + ].forEach((file) => { + const files = glob.sync(path.resolve(common.tmp, 'dist', file)); + expect(files.length).toEqual(1); + }); + done(); }, diff --git a/e2e/skyux-lib-help-tests/fixtures/skyux-modal/modal-form-fixture.component.ts b/e2e/skyux-lib-help-tests/fixtures/skyux-modal/modal-form-fixture.component.ts index 5fa8e27d..e3dd130f 100644 --- a/e2e/skyux-lib-help-tests/fixtures/skyux-modal/modal-form-fixture.component.ts +++ b/e2e/skyux-lib-help-tests/fixtures/skyux-modal/modal-form-fixture.component.ts @@ -1,6 +1,10 @@ -import { Component } from '@angular/core'; +import { + Component +} from '@angular/core'; -import { SkyModalInstance } from '@blackbaud/skyux/dist/core'; +import { + SkyModalInstance +} from '@skyux/modals'; @Component({ selector: 'sky-modal-form', @@ -18,5 +22,7 @@ import { SkyModalInstance } from '@blackbaud/skyux/dist/core'; ` }) export class SkyModalDemoFormComponent { - constructor(public instance: SkyModalInstance) { } + constructor( + public instance: SkyModalInstance + ) { } } diff --git a/e2e/skyux-lib-help-tests/fixtures/skyux-modal/modal-launcher-fixture.component.ts b/e2e/skyux-lib-help-tests/fixtures/skyux-modal/modal-launcher-fixture.component.ts index 76681a87..2d66bf18 100644 --- a/e2e/skyux-lib-help-tests/fixtures/skyux-modal/modal-launcher-fixture.component.ts +++ b/e2e/skyux-lib-help-tests/fixtures/skyux-modal/modal-launcher-fixture.component.ts @@ -1,10 +1,18 @@ -import { Component } from '@angular/core'; +import { + Component +} from '@angular/core'; -import { SkyModalService } from '@blackbaud/skyux/dist/core'; +import { + SkyModalService +} from '@skyux/modals'; -import { SkyModalDemoFormComponent } from './modal-form-fixture.component'; +import { + HelpWidgetService +} from '@blackbaud/skyux-lib-help'; -import { HelpWidgetService } from '@blackbaud/skyux-lib-help'; +import { + SkyModalDemoFormComponent +} from './modal-form-fixture.component'; @Component({ selector: 'help-modal-launcher', @@ -20,11 +28,11 @@ import { HelpWidgetService } from '@blackbaud/skyux-lib-help'; export class HelpModalDemoComponent { constructor( private helpService: HelpWidgetService, - private modal: SkyModalService) { } + private modal: SkyModalService + ) { } - public openModal(modalType: string) { - - let modalOptions = { + public openModal(modalType: string): void { + const modalOptions = { fullPage: false, helpKey: 'modal-header' }; @@ -37,7 +45,10 @@ export class HelpModalDemoComponent { break; } - let modalInstance = this.modal.open(SkyModalDemoFormComponent, modalOptions); + const modalInstance = this.modal.open( + SkyModalDemoFormComponent, + modalOptions + ); modalInstance.helpOpened.subscribe((helpKey: string) => { this.helpService.openToHelpKey(helpKey); diff --git a/e2e/skyux-lib-help-tests/skyux-lib-help.e2e-spec.js b/e2e/skyux-lib-help-tests/skyux-lib-help.e2e-spec.js index 2e4d939f..72030da1 100644 --- a/e2e/skyux-lib-help-tests/skyux-lib-help.e2e-spec.js +++ b/e2e/skyux-lib-help-tests/skyux-lib-help.e2e-spec.js @@ -1,11 +1,10 @@ /*jshint jasmine: true, node: true */ -/*global browser, element, by, $$*/ +/*global element, by*/ 'use strict'; const fs = require('fs'); const path = require('path'); const common = require('../shared/common'); -const tests = require('../shared/tests'); const tmpSrcApp = path.resolve(process.cwd(), common.tmp, 'src/app'); const e2eRootPath = path.resolve(process.cwd(), 'e2e/skyux-lib-help-tests'); @@ -14,11 +13,46 @@ let originalHomePage; // Add the SkyModalDemoFormComponent to the entryComponents in the app-extras module. const mockAppExtras = ` -import { NgModule } from '@angular/core'; +import { + NgModule +} from '@angular/core'; -import { SkyModalDemoFormComponent } from './modal-fixtures/modal-form-fixture.component'; +import { + SkyAvatarModule +} from '@skyux/avatar'; + +import { + SkyErrorModule +} from '@skyux/errors'; + +import { + SkyAlertModule, + SkyKeyInfoModule +} from '@skyux/indicators'; + +import { + SkyModalModule +} from '@skyux/modals'; + +import { + SkyModalDemoFormComponent +} from './modal-fixtures/modal-form-fixture.component'; @NgModule({ + imports: [ + SkyAlertModule, + SkyAvatarModule, + SkyErrorModule, + SkyKeyInfoModule, + SkyModalModule + ], + exports: [ + SkyAlertModule, + SkyAvatarModule, + SkyErrorModule, + SkyKeyInfoModule, + SkyModalModule + ], providers: [], entryComponents: [ SkyModalDemoFormComponent diff --git a/e2e/skyux-serve.e2e-spec.js b/e2e/skyux-serve.e2e-spec.js index 1e553e83..da453ae7 100644 --- a/e2e/skyux-serve.e2e-spec.js +++ b/e2e/skyux-serve.e2e-spec.js @@ -31,14 +31,12 @@ describe('skyux serve', () => { it('should render shared nav component', tests.renderSharedNavComponent); it('should follow routerLink and render about component', tests.followRouterLinkRenderAbout); - it('should should include script tags', (done) => { + it('should include script tags', (done) => { browser.getPageSource() .then(source => { let previousIndex = -1; [ 'polyfills.js', - 'vendor.js', - 'skyux.js', 'app.js' ].forEach(file => { const currentIndex = source.indexOf(``); diff --git a/lib/locale-assets-processor.js b/lib/locale-assets-processor.js index 8501f109..09a38c29 100644 --- a/lib/locale-assets-processor.js +++ b/lib/locale-assets-processor.js @@ -53,10 +53,9 @@ function readJson(file) { } function extendJson(...files) { - return files.reduce((accumulator, file) => - Object.assign(accumulator, readJson(file)), - {} - ); + return files.reduce((accumulator, file) => { + return Object.assign(accumulator, readJson(file)); + }, {}); } function isLocaleFile(file) { @@ -95,10 +94,11 @@ function getNonDefaultLocaleFiles(dirname) { } function mergeDefaultLocaleFiles() { - const libFiles = libPaths.reduce((accumulator, libPath) => - accumulator.concat( + const libFiles = libPaths.reduce((accumulator, libPath) => { + return accumulator.concat( getDefaultLocaleFiles(libPath) - ), []); + ); + }, []); const contents = extendJson(...libFiles, defaultFile); fs.writeJsonSync(defaultFile, contents); } @@ -112,10 +112,11 @@ function mergeNonDefaultLocaleFiles() { }); // Extend all SPA files with library files. - libPaths.reduce((accumulator, libPath) => - accumulator.concat( + libPaths.reduce((accumulator, libPath) => { + return accumulator.concat( getNonDefaultLocaleFiles(libPath) - ), []) + ); + }, []) .forEach(libFile => { const basename = path.basename(libFile); const spaFile = tempPath(basename); diff --git a/lib/sky-pages-module-generator.js b/lib/sky-pages-module-generator.js index af1e7f26..20861bae 100644 --- a/lib/sky-pages-module-generator.js +++ b/lib/sky-pages-module-generator.js @@ -63,18 +63,10 @@ function getSource(skyAppConfig) { const skyAppConfigAsString = JSON.stringify(skyAppConfig); let runtimeImports = [ - 'SkyAppBootstrapper', - 'SkyAppConfig', - 'SkyAppRuntimeConfigParams', - 'SkyAppWindowRef', - 'SkyAuthTokenProvider', - 'SkyAppStyleLoader', - 'SkyAppViewportService' + 'SkyAppBootstrapper' ]; let runtimeProviders = [ - 'SkyAppWindowRef', - 'SkyAppStyleLoader', `{ provide: SkyAppConfig, deps: [ @@ -89,8 +81,7 @@ function getSource(skyAppConfig) { `{ provide: SkyAppLocaleProvider, useClass: SkyAppHostLocaleProvider - }`, - 'SkyAppViewportService' + }` ]; let nodeModuleImports = [ @@ -99,25 +90,28 @@ function getSource(skyAppConfig) { `import { HttpModule } from '@angular/http';`, `import { FormsModule, ReactiveFormsModule } from '@angular/forms';`, `import { ActivatedRoute, RouterModule, Routes } from '@angular/router';`, + `import { SkyAppAssetsService } from '@skyux/assets';`, `import { SkyAppLocaleProvider } from '@skyux/i18n';`, + `import { SkyAppRuntimeConfigParams, SkyAppConfig } from '@skyux/config';`, + `import { SkyAppWindowRef } from '@skyux/core';`, + `import { SkyAuthTokenProvider } from '@skyux/http';`, + `import { SkyThemeModule } from '@skyux/theme';`, + `import { SkyI18nModule } from '@skyux/i18n';`, `import { Subscription } from 'rxjs/Subscription';` ]; let runtimeModuleExports = [ - ...names, - 'SkyAppRuntimeModule' + ...names ]; - let skyuxModules = skyAppConfig.skyux.skyuxModules || []; - let runtimeModuleImports = [ 'CommonModule', 'HttpModule', 'FormsModule', 'ReactiveFormsModule', - ...skyuxModules, 'AppExtrasModule', - 'SkyAppRuntimeModule' + 'SkyI18nModule', + 'SkyThemeModule' ]; let authTokenProvider = 'SkyAuthTokenProvider'; @@ -195,16 +189,18 @@ BBAuth.mock = true; ${nodeModuleImports.join('\n')} import '${skyAppConfig.runtime.skyPagesOutAlias}/src/main'; -import { - ${skyuxModules.join(',\n' + codegen.indent(1))} -} from '${skyAppConfig.runtime.skyuxPathAlias}/core'; + import { AppExtrasModule } from '${skyAppConfig.runtime.skyPagesOutAlias}/src/app/app-extras.module'; -import { ${runtimeImports.join(', ')} } from '${skyAppConfig.runtime.runtimeAlias}'; -import { SkyAppRuntimeModule } from '${skyAppConfig.runtime.runtimeAlias}/runtime.module'; -import { SkyAppAssetsService } from '${skyAppConfig.runtime.runtimeAlias}/assets.service'; -import { SkyAppHostLocaleProvider } from '${skyAppConfig.runtime.runtimeAlias}/i18n'; + +import { + ${runtimeImports.join(', ')} +} from '${skyAppConfig.runtime.runtimeAlias}'; + +import { + SkyAppHostLocaleProvider +} from '${skyAppConfig.runtime.runtimeAlias}/i18n/host-locale-provider'; ${assetsGenerator.getSource()} diff --git a/lib/sky-pages-route-generator.js b/lib/sky-pages-route-generator.js index 859a8f7a..ad0cc8cf 100644 --- a/lib/sky-pages-route-generator.js +++ b/lib/sky-pages-route-generator.js @@ -69,17 +69,17 @@ function parseFileIntoEntity(skyAppConfig, file, index) { .slice(skyAppConfig.runtime.srcPath.split('/').length - 1, -1) .forEach(pathPart => { - const possibleParam = /^_(.*)$/.exec(pathPart); - const param = possibleParam ? possibleParam[1] : pathPart; + const possibleParam = /^_(.*)$/.exec(pathPart); + const param = possibleParam ? possibleParam[1] : pathPart; - // This means we found a route param, ex: "{id}" - if (param !== pathPart) { - routePath.push(':' + param); - routeParams.push(param); - } else { - routePath.push(param); - } - }); + // This means we found a route param, ex: "{id}" + if (param !== pathPart) { + routePath.push(':' + param); + routeParams.push(param); + } else { + routePath.push(param); + } + }); const componentName = `SPR_${index}_IndexComponent`; const componentDefinition = generateDefinition( @@ -101,11 +101,12 @@ function parseFileIntoEntity(skyAppConfig, file, index) { function generateRedirects(skyAppConfig) { let redirects = []; if (skyAppConfig.skyux && skyAppConfig.skyux.redirects) { - redirects = Object.keys(skyAppConfig.skyux.redirects).map(key => -`{ + redirects = Object.keys(skyAppConfig.skyux.redirects).map(key => { + return `{ path: '${key}', redirectTo: '${skyAppConfig.skyux.redirects[key]}' -}`); +}`; + }); } return redirects; @@ -288,7 +289,7 @@ function generateRuntimeImports(skyAppConfig, routes) { const alias = skyAppConfig.runtime.spaPathAlias; return routes .filter(r => r.guard) - .map(r =>`import { ${r.guard.name} } from '${alias}/${r.guard.path.replace(/\.ts$/, '')}';`); + .map(r => `import { ${r.guard.name} } from '${alias}/${r.guard.path.replace(/\.ts$/, '')}';`); } function generateProviders(routes) { @@ -328,6 +329,7 @@ function extractGuard(file) { let result; let match; + // eslint-disable-next-line no-cond-assign while ((match = matchRegexp.exec(content))) { if (result !== undefined) { throw new Error(`As a best practice, only export one guard per file in ${file}`); diff --git a/loader/sky-pages-module/index.js b/loader/sky-pages-module/index.js index a24d310c..b3e6be95 100644 --- a/loader/sky-pages-module/index.js +++ b/loader/sky-pages-module/index.js @@ -19,6 +19,7 @@ module.exports = function () { fs.writeFileSync(moduleResolved, template.replace(regex, `// TS (${ts}`)); } + // eslint-disable-next-line no-underscore-dangle this._compiler.plugin('invalid', function (filename) { const filenameParsed = path.parse(filename); switch (filenameParsed.ext) { diff --git a/package.json b/package.json index 2ec7c87b..c728ae07 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "name": "@blackbaud/skyux-builder", + "name": "@skyux-sdk/builder", "version": "1.30.0", "description": "Builds the output of a SKY UX application.", "main": "index.js", @@ -10,9 +10,7 @@ "coverage:src-app": "node ./utils/cli-test.js dev-src-app", "e2e": "webdriver-manager update --standalone false --gecko false && npm run protractor", "protractor": "protractor ./config/protractor/protractor-dev.conf.js", - "jscs": "jscs cli config lib loader plugin src utils index.js", - "jshint": "jshint cli config lib loader plugin src utils index.js", - "lint": "npm run jshint && npm run jscs", + "lint": "node ./node_modules/.bin/eslint -c .eslintrc.json cli config lib loader plugin utils index.js", "test": "npm run lint && npm run coverage && npm run e2e" }, "repository": { @@ -27,101 +25,136 @@ }, "homepage": "https://github.com/blackbaud/skyux-builder#readme", "peerDependencies": { - "@blackbaud/skyux": "^2.30.1" + "@angular/compiler-cli": "^7.2.0", + "@angular/compiler": "^7.2.0", + "@angular/common": "^7.2.0", + "@angular/core": "^7.2.0", + "@angular/forms": "^7.2.0", + "@angular/http": "^7.2.0", + "@angular/platform-browser": "^7.2.0", + "@angular/platform-browser-dynamic": "^7.2.0", + "@angular/router": "^7.2.0", + "@blackbaud/auth-client": "^2.12.0", + "@skyux-sdk/pact": "^3.1.0", + "@skyux-sdk/testing": "^3.0.0", + "@skyux/assets": "^3.0.0", + "@skyux/config": "^3.2.0", + "@skyux/core": "^3.4.0", + "@skyux/http": "^3.2.0", + "@skyux/i18n": "^3.5.0", + "@skyux/omnibar-interop": "^3.1.0", + "@skyux/router": "^3.1.0", + "@skyux/theme": "^3.4.0", + "@types/core-js": "^2.5.0", + "codelyzer": "^4.5.0", + "core-js": "^2.6.2", + "rxjs": "^6.3.3", + "rxjs-compat": "^6.3.3", + "ts-node": "^7.0.1", + "tslint": "^5.12.1", + "typescript": "^3.2.2", + "zone.js": "^0.8.27" }, "dependencies": { - "@angular/animations": "4.3.6", - "@angular/common": "4.3.6", - "@angular/compiler": "4.3.6", - "@angular/compiler-cli": "4.3.6", - "@angular/core": "4.3.6", - "@angular/forms": "4.3.6", - "@angular/http": "4.3.6", - "@angular/platform-browser": "4.3.6", - "@angular/platform-browser-dynamic": "4.3.6", - "@angular/router": "4.3.6", - "@blackbaud/auth-client": "2.12.0", + "@angular-devkit/build-optimizer": "0.12.1", "@blackbaud/skyux-lib-help": "1.3.1", - "@blackbaud/skyux-logger": "1.0.2", - "@ngtools/webpack": "1.3.1", - "@pact-foundation/karma-pact": "2.1.3", - "@pact-foundation/pact": "5.3.0", - "@pact-foundation/pact-node": "6.7.0", - "@pact-foundation/pact-web": "5.3.0", - "@skyux-sdk/e2e": "3.0.1", - "@skyux-sdk/pact": "3.0.1", - "@skyux-sdk/testing": "3.0.0", - "@skyux/assets": "3.0.0", - "@skyux/config": "3.2.0", - "@skyux/http": "3.2.0", - "@skyux/i18n": "3.5.0", - "@skyux/omnibar-interop": "3.1.0", - "@skyux/router": "3.1.0", - "@types/core-js": "0.9.41", - "@types/jasmine": "2.5.47", - "@types/node": "7.0.18", + "@blackbaud/skyux-logger": "1.1.0", + "@ngtools/webpack": "7.2.1", + "@pact-foundation/karma-pact": "2.1.9", + "@pact-foundation/pact-node": "6.21.2", + "@types/jasmine": "3.3.5", + "@types/node": "10.12.18", "angular2-template-loader": "0.6.2", - "awesome-typescript-loader": "3.1.3", + "async": "2.6.1", + "awesome-typescript-loader": "5.2.1", "chromedriver-version-matcher": "^1.0.0-alpha.2", - "codelyzer": "3.0.1", - "core-js": "2.4.1", - "cors": "2.8.4", - "enhanced-resolve": "3.3.0", - "express": "4.15.3", - "fs-extra": "3.0.1", - "glob": "7.1.1", + "cors": "2.8.5", + "cross-spawn": "6.0.5", + "enhanced-resolve": "4.1.0", + "express": "4.16.4", + "fs-extra": "7.0.1", + "glob": "7.1.3", "hash-file": "3.0.0", - "html-webpack-plugin": "2.28.0", - "http-server": "0.10.0", - "istanbul-instrumenter-loader": "2.0.0", - "jasmine-spec-reporter": "4.1.0", - "karma": "1.7.0", - "karma-chrome-launcher": "2.1.1", - "karma-coverage": "1.1.1", - "karma-jasmine": "1.1.0", - "karma-mocha-reporter": "2.2.3", + "html-webpack-plugin": "3.2.0", + "http-proxy": "1.17.0", + "http-server": "0.11.1", + "istanbul": "0.4.5", + "istanbul-instrumenter-loader": "3.0.1", + "jasmine": "2.99.0", + "jasmine-spec-reporter": "4.2.1", + "karma": "3.1.4", + "karma-chrome-launcher": "2.2.0", + "karma-coverage": "1.1.2", + "karma-jasmine": "1.1.2", + "karma-mocha-reporter": "2.2.5", "karma-sourcemap-loader": "0.3.7", - "karma-webpack": "2.0.3", - "loader-utils": "1.1.0", + "karma-webpack": "4.0.0-rc.5", + "loader-utils": "1.2.3", "lodash.get": "4.4.2", - "lodash.mergewith": "4.6.0", - "node-sass": "4.5.3", + "lodash.mergewith": "4.6.1", + "minimist": "1.2.0", + "node-sass": "4.11.0", "node-sass-tilde-importer": "1.0.2", - "open": "0.0.5", - "portfinder": "1.0.13", - "protractor": "5.1.2", - "raw-loader": "0.5.1", - "reflect-metadata": "0.1.10", - "remap-istanbul": "0.9.5", - "rxjs": "5.4.3", - "sass-loader": "6.0.5", - "selenium-standalone": "6.4.1", - "selenium-webdriver": "3.5.0", + "opn": "5.4.0", + "portfinder": "1.0.20", + "protractor": "5.4.2", + "raw-loader": "1.0.0", + "reflect-metadata": "0.1.12", + "remap-istanbul": "0.13.0", + "rimraf": "2.6.3", + "sass-loader": "7.1.0", + "selenium-standalone": "6.15.4", "simple-progress-webpack-plugin": "1.1.2", "source-map-inline-loader": "1.0.0", - "source-map-loader": "0.2.1", - "style-loader": "0.17.0", - "ts-helpers": "1.1.2", - "ts-node": "3.0.4", - "tslint": "5.2.0", - "typescript": "2.3.2", - "web-animations-js": "2.2.5", - "webpack": "2.5.1", - "webpack-dev-server": "2.4.5", - "webpack-merge": "4.1.0", - "winston": "2.3.1", - "zone.js": "0.8.10" + "source-map-loader": "0.2.4", + "style-loader": "0.23.1", + "url": "0.11.0", + "util": "0.11.1", + "web-animations-js": "2.3.1", + "webpack": "4.28.4", + "webpack-cli": "3.2.1", + "webpack-dev-middleware": "3.5.0", + "webpack-dev-server": "3.1.14", + "webpack-merge": "4.2.1" }, "devDependencies": { - "@blackbaud/skyux": "2.30.1", - "cross-spawn": "5.1.0", - "istanbul": "0.4.5", - "jasmine": "2.6.0", - "jscs": "3.0.7", - "jshint": "2.9.4", - "json-loader": "0.5.7", - "mock-require": "2.0.2", - "proxyquire": "1.8.0", - "rimraf": "2.6.1" + "@angular/animations": "7.2.0", + "@angular/common": "7.2.0", + "@angular/compiler": "7.2.0", + "@angular/compiler-cli": "7.2.0", + "@angular/core": "7.2.0", + "@angular/forms": "7.2.0", + "@angular/http": "7.2.0", + "@angular/platform-browser": "7.2.0", + "@angular/platform-browser-dynamic": "7.2.0", + "@angular/router": "7.2.0", + "@blackbaud/auth-client": "2.12.0", + "@pact-foundation/pact-web": "7.2.0", + "@skyux-sdk/pact": "3.1.0", + "@skyux-sdk/testing": "3.1.0", + "@skyux/assets": "3.0.0", + "@skyux/config": "3.2.0", + "@skyux/core": "3.5.1", + "@skyux/http": "3.2.0", + "@skyux/i18n": "3.5.0", + "@skyux/indicators": "3.0.1", + "@skyux/modals": "3.0.0", + "@skyux/omnibar-interop": "3.1.0", + "@skyux/router": "3.1.0", + "@skyux/theme": "3.4.0", + "@types/core-js": "2.5.0", + "codelyzer": "4.5.0", + "core-js": "2.6.2", + "eslint": "5.12.0", + "eslint-config-airbnb-base": "13.1.0", + "eslint-plugin-import": "2.14.0", + "mock-require": "3.0.2", + "proxyquire": "2.1.0", + "rxjs": "6.3.3", + "rxjs-compat": "6.3.3", + "ts-node": "7.0.1", + "tslint": "5.12.1", + "typescript": "3.2.2", + "zone.js": "0.8.27" } } diff --git a/plugin/save-metadata/index.js b/plugin/save-metadata/index.js index 719eea07..8b475fbf 100644 --- a/plugin/save-metadata/index.js +++ b/plugin/save-metadata/index.js @@ -1,7 +1,7 @@ /*jslint node: true */ 'use strict'; -const fs = require('fs'); +const fs = require('fs-extra'); const path = require('path'); const util = require('util'); const hostUtils = require('../../utils/host-utils'); diff --git a/runtime/assets.service.ts b/runtime/assets.service.ts deleted file mode 100644 index 2ab74792..00000000 --- a/runtime/assets.service.ts +++ /dev/null @@ -1,3 +0,0 @@ -export { - SkyAppAssetsService -} from '@skyux/assets/assets.service'; diff --git a/runtime/auth-http.ts b/runtime/auth-http.ts deleted file mode 100644 index edcce1cc..00000000 --- a/runtime/auth-http.ts +++ /dev/null @@ -1,3 +0,0 @@ -export { - SkyAuthHttp -} from '@skyux/http/modules/auth-http/auth-http'; diff --git a/runtime/auth-token-provider.ts b/runtime/auth-token-provider.ts deleted file mode 100644 index ee8b1359..00000000 --- a/runtime/auth-token-provider.ts +++ /dev/null @@ -1,3 +0,0 @@ -export { - SkyAuthTokenProvider -} from '@skyux/http/modules/auth-http/auth-token-provider'; diff --git a/runtime/bootstrapper.ts b/runtime/bootstrapper.ts index 69e60200..b4916f89 100644 --- a/runtime/bootstrapper.ts +++ b/runtime/bootstrapper.ts @@ -1,5 +1,4 @@ //#region imports - import { BBAuth, BBContextArgs, @@ -7,13 +6,9 @@ import { } from '@blackbaud/auth-client'; import { + SkyAppRuntimeConfigParams, SkyuxConfig -} from './config'; - -import { - SkyAppRuntimeConfigParams -} from './params'; - +} from '@skyux/config'; //#endregion export class SkyAppBootstrapper { diff --git a/runtime/config-params.ts b/runtime/config-params.ts deleted file mode 100644 index 77cf6ed7..00000000 --- a/runtime/config-params.ts +++ /dev/null @@ -1,3 +0,0 @@ -export { - SkyuxConfigParams -} from '@skyux/config/config-params'; diff --git a/runtime/config.ts b/runtime/config.ts index c0c8f212..18eb49ff 100644 --- a/runtime/config.ts +++ b/runtime/config.ts @@ -1,12 +1,3 @@ export { - RuntimeConfigApp, - RuntimeConfig, - SkyAppConfig, - SkyuxConfig, - SkyuxConfigA11y, - SkyuxConfigApp, - SkyuxConfigHost, - SkyuxConfigTestSettings, - SkyuxConfigUnitTestSettings, - SkyuxPactConfig -} from '@skyux/config'; + SkyAppConfig +} from '@skyux/config/config'; diff --git a/runtime/directives/index.ts b/runtime/directives/index.ts deleted file mode 100644 index 9c094378..00000000 --- a/runtime/directives/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './sky-app-link.directive'; -export * from './sky-app-link-external.directive'; diff --git a/runtime/directives/sky-app-link-external.directive.ts b/runtime/directives/sky-app-link-external.directive.ts deleted file mode 100644 index c831d603..00000000 --- a/runtime/directives/sky-app-link-external.directive.ts +++ /dev/null @@ -1,3 +0,0 @@ -export { - SkyAppLinkExternalDirective -} from '@skyux/router/modules/link/link-external.directive'; diff --git a/runtime/directives/sky-app-link.directive.ts b/runtime/directives/sky-app-link.directive.ts deleted file mode 100644 index 877ec412..00000000 --- a/runtime/directives/sky-app-link.directive.ts +++ /dev/null @@ -1,3 +0,0 @@ -export { - SkyAppLinkDirective -} from '@skyux/router/modules/link/link.directive'; diff --git a/runtime/format.ts b/runtime/format.ts deleted file mode 100644 index ffca9711..00000000 --- a/runtime/format.ts +++ /dev/null @@ -1,3 +0,0 @@ -export { - SkyAppFormat -} from '@skyux/core/modules/format'; diff --git a/runtime/i18n/host-locale-provider.ts b/runtime/i18n/host-locale-provider.ts index 46e446ce..f695f6e1 100644 --- a/runtime/i18n/host-locale-provider.ts +++ b/runtime/i18n/host-locale-provider.ts @@ -4,19 +4,17 @@ import { import { SkyAppWindowRef -} from '../window-ref'; +} from '@skyux/core'; import { - Observable -} from 'rxjs/Observable'; - -import { - SkyAppLocaleInfo -} from './locale-info'; + SkyAppLocaleInfo, + SkyAppLocaleProvider +} from '@skyux/i18n'; import { - SkyAppLocaleProvider -} from './locale-provider'; + Observable, + of +} from 'rxjs'; @Injectable() export class SkyAppHostLocaleProvider extends SkyAppLocaleProvider { @@ -38,7 +36,7 @@ export class SkyAppHostLocaleProvider extends SkyAppLocaleProvider { locale = locale || this.defaultLocale; - return Observable.of({ + return of({ locale: locale }); } diff --git a/runtime/i18n/index.ts b/runtime/i18n/index.ts deleted file mode 100644 index 7453b964..00000000 --- a/runtime/i18n/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -export * from './host-locale-provider'; -export * from './locale-provider'; -export * from './resources.pipe'; -export * from './resources.service'; diff --git a/runtime/i18n/locale-info.ts b/runtime/i18n/locale-info.ts deleted file mode 100644 index 0c949620..00000000 --- a/runtime/i18n/locale-info.ts +++ /dev/null @@ -1,3 +0,0 @@ -export { - SkyAppLocaleInfo -} from '@skyux/i18n/modules/i18n/locale-info'; diff --git a/runtime/i18n/locale-provider.ts b/runtime/i18n/locale-provider.ts deleted file mode 100644 index 78d746be..00000000 --- a/runtime/i18n/locale-provider.ts +++ /dev/null @@ -1,3 +0,0 @@ -export { - SkyAppLocaleProvider -} from '@skyux/i18n/modules/i18n/locale-provider'; diff --git a/runtime/i18n/resources.pipe.ts b/runtime/i18n/resources.pipe.ts deleted file mode 100644 index 6dcce470..00000000 --- a/runtime/i18n/resources.pipe.ts +++ /dev/null @@ -1,3 +0,0 @@ -export { - SkyAppResourcesPipe -} from '@skyux/i18n/modules/i18n/resources.pipe'; diff --git a/runtime/i18n/resources.service.ts b/runtime/i18n/resources.service.ts deleted file mode 100644 index c4068119..00000000 --- a/runtime/i18n/resources.service.ts +++ /dev/null @@ -1,3 +0,0 @@ -export { - SkyAppResourcesService -} from '@skyux/i18n/modules/i18n/resources.service'; diff --git a/runtime/i18n/resources.ts b/runtime/i18n/resources.ts deleted file mode 100644 index 1ca93563..00000000 --- a/runtime/i18n/resources.ts +++ /dev/null @@ -1,3 +0,0 @@ -export { - SkyAppResources -} from '@skyux/i18n/modules/i18n/resources'; diff --git a/runtime/index.ts b/runtime/index.ts index 7ffa4636..ad9ba6ae 100644 --- a/runtime/index.ts +++ b/runtime/index.ts @@ -1,16 +1,3 @@ -export * from './assets.service'; -export * from './auth-http'; -export * from './auth-token-provider'; -export * from './pact-auth-token-provider'; -export * from './pact.service'; export * from './bootstrapper'; export * from './config'; -export * from './params'; -export * from './directives'; -export * from './search-results-provider'; -export * from './window-ref'; -export * from './style-loader'; -export * from './viewport.service'; -export * from './omnibar-provider'; -export * from './omnibar-ready-args'; export * from './runtime.module'; diff --git a/runtime/omnibar-provider.ts b/runtime/omnibar-provider.ts deleted file mode 100644 index a8da91b2..00000000 --- a/runtime/omnibar-provider.ts +++ /dev/null @@ -1,3 +0,0 @@ -export { - SkyAppOmnibarProvider -} from '@skyux/omnibar-interop/omnibar-provider'; diff --git a/runtime/omnibar-ready-args.ts b/runtime/omnibar-ready-args.ts deleted file mode 100644 index bc593da2..00000000 --- a/runtime/omnibar-ready-args.ts +++ /dev/null @@ -1,3 +0,0 @@ -export { - SkyAppOmnibarReadyArgs -} from '@skyux/omnibar-interop/omnibar-ready-args'; diff --git a/runtime/pact-auth-token-provider.ts b/runtime/pact-auth-token-provider.ts deleted file mode 100644 index afed4d40..00000000 --- a/runtime/pact-auth-token-provider.ts +++ /dev/null @@ -1,3 +0,0 @@ -export { - SkyPactAuthTokenProvider -} from '@skyux-sdk/pact/modules/pact/pact-auth-token-provider'; diff --git a/runtime/pact.service.ts b/runtime/pact.service.ts deleted file mode 100644 index ab8b8b90..00000000 --- a/runtime/pact.service.ts +++ /dev/null @@ -1,3 +0,0 @@ -export { - SkyPactService -} from '@skyux-sdk/pact/modules/pact/pact.service'; diff --git a/runtime/params.ts b/runtime/params.ts deleted file mode 100644 index 7263fd91..00000000 --- a/runtime/params.ts +++ /dev/null @@ -1,3 +0,0 @@ -export { - SkyAppRuntimeConfigParams -} from '@skyux/config/params'; diff --git a/runtime/search-results-provider.ts b/runtime/search-results-provider.ts deleted file mode 100644 index 5e0490ee..00000000 --- a/runtime/search-results-provider.ts +++ /dev/null @@ -1,3 +0,0 @@ -export { - SkyAppSearchResultsProvider -} from '@skyux/omnibar-interop/search-results-provider'; diff --git a/runtime/style-loader.ts b/runtime/style-loader.ts deleted file mode 100644 index 034d33eb..00000000 --- a/runtime/style-loader.ts +++ /dev/null @@ -1,3 +0,0 @@ -export { - SkyAppStyleLoader -} from '@skyux/theme/style-loader'; diff --git a/runtime/testing/browser/i18n/resources-test.service.ts b/runtime/testing/browser/i18n/resources-test.service.ts deleted file mode 100644 index 186e1f97..00000000 --- a/runtime/testing/browser/i18n/resources-test.service.ts +++ /dev/null @@ -1,3 +0,0 @@ -export { - SkyAppResourcesTestService -} from '@skyux/i18n/testing/resources-test.service'; diff --git a/runtime/testing/browser/index.ts b/runtime/testing/browser/index.ts index 89db5e67..cb67cd1a 100644 --- a/runtime/testing/browser/index.ts +++ b/runtime/testing/browser/index.ts @@ -1,3 +1 @@ -export * from './matchers'; export * from './test-module'; -export * from './test-utility'; diff --git a/runtime/testing/browser/matchers.ts b/runtime/testing/browser/matchers.ts deleted file mode 100644 index add9da7d..00000000 --- a/runtime/testing/browser/matchers.ts +++ /dev/null @@ -1,3 +0,0 @@ -export { - expect -} from '@skyux-sdk/testing/matchers/matchers'; diff --git a/runtime/testing/browser/test-module.ts b/runtime/testing/browser/test-module.ts index a2a7f74b..c1220318 100644 --- a/runtime/testing/browser/test-module.ts +++ b/runtime/testing/browser/test-module.ts @@ -6,8 +6,8 @@ import { RouterTestingModule } from '@angular/router/testing'; import { SkyPagesModule } from '../../../src/app/sky-pages.module'; -import { SkyAppResourcesService } from '../../../runtime/i18n'; -import { SkyAppResourcesTestService } from './i18n/resources-test.service'; +import { SkyAppResourcesService } from '@skyux/i18n'; +import { SkyAppResourcesTestService } from '@skyux/i18n/testing'; @NgModule({ imports: [ diff --git a/runtime/testing/browser/test-utility-dom-event-options.ts b/runtime/testing/browser/test-utility-dom-event-options.ts deleted file mode 100644 index 9e5a7b7d..00000000 --- a/runtime/testing/browser/test-utility-dom-event-options.ts +++ /dev/null @@ -1,3 +0,0 @@ -export { - SkyAppTestUtilityDomEventOptions -} from '@skyux-sdk/testing/test-utility/test-utility-dom-event-options'; diff --git a/runtime/testing/browser/test-utility.ts b/runtime/testing/browser/test-utility.ts deleted file mode 100644 index e388dca7..00000000 --- a/runtime/testing/browser/test-utility.ts +++ /dev/null @@ -1,3 +0,0 @@ -export { - SkyAppTestUtility -} from '@skyux-sdk/testing/test-utility/test-utility'; diff --git a/runtime/testing/e2e/a11y.ts b/runtime/testing/e2e/a11y.ts deleted file mode 100644 index d9fa53aa..00000000 --- a/runtime/testing/e2e/a11y.ts +++ /dev/null @@ -1,3 +0,0 @@ -export { - SkyA11y -} from '@skyux-sdk/e2e/a11y'; diff --git a/runtime/testing/e2e/host-browser.ts b/runtime/testing/e2e/host-browser.ts deleted file mode 100644 index 9de1b5d6..00000000 --- a/runtime/testing/e2e/host-browser.ts +++ /dev/null @@ -1,3 +0,0 @@ -export { - SkyHostBrowser -} from '@skyux-sdk/e2e/host-browser'; diff --git a/runtime/testing/e2e/index.ts b/runtime/testing/e2e/index.ts deleted file mode 100644 index 97d36f6d..00000000 --- a/runtime/testing/e2e/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './host-browser'; -export * from './a11y'; diff --git a/runtime/viewport.service.ts b/runtime/viewport.service.ts deleted file mode 100644 index 49a8096f..00000000 --- a/runtime/viewport.service.ts +++ /dev/null @@ -1,3 +0,0 @@ -export { - SkyAppViewportService -} from '@skyux/theme/viewport.service'; diff --git a/runtime/window-ref.ts b/runtime/window-ref.ts deleted file mode 100644 index e201fba2..00000000 --- a/runtime/window-ref.ts +++ /dev/null @@ -1,3 +0,0 @@ -export { - SkyAppWindowRef -} from '@skyux/core/modules/window/window-ref'; diff --git a/skyuxconfig.json b/skyuxconfig.json index 65014e79..c932f176 100644 --- a/skyuxconfig.json +++ b/skyuxconfig.json @@ -13,8 +13,5 @@ "envid": true, "leid": true, "svcid": true - }, - "skyuxModules": [ - "SkyModule" - ] + } } diff --git a/src/app/app.component.spec.ts b/src/app/app.component.spec.ts index debe92ab..2c651094 100644 --- a/src/app/app.component.spec.ts +++ b/src/app/app.component.spec.ts @@ -10,37 +10,55 @@ import { tick } from '@angular/core/testing'; -import { RouterTestingModule } from '@angular/router/testing'; -import { NavigationEnd, NavigationStart, Router } from '@angular/router'; - import { - SkyAppConfig, - SkyAppOmnibarProvider, - SkyAppOmnibarReadyArgs, - SkyAppSearchResultsProvider, - SkyAppStyleLoader, - SkyAppWindowRef, - SkyAppViewportService -} from '@blackbaud/skyux-builder/runtime'; + NavigationEnd, + NavigationStart, + Router +} from '@angular/router'; -import { HelpInitializationService } from '@blackbaud/skyux-lib-help'; +import { + RouterTestingModule +} from '@angular/router/testing'; import { BBOmnibar, BBOmnibarConfig, - BBOmnibarLegacy, BBOmnibarNavigationItem, BBOmnibarSearchArgs } from '@blackbaud/auth-client'; -import { AppComponent } from './app.component'; +import { + HelpInitializationService +} from '@blackbaud/skyux-lib-help'; + +import { + SkyAppConfig +} from '@skyux/config'; + +import { + SkyAppWindowRef +} from '@skyux/core'; + +import { + SkyAppOmnibarProvider, + SkyAppOmnibarReadyArgs, + SkyAppSearchResultsProvider +} from '@skyux/omnibar-interop'; + +import { + SkyAppStyleLoader, + SkyAppViewportService +} from '@skyux/theme'; + +import { + AppComponent +} from './app.component'; describe('AppComponent', () => { let mockSkyuxHost: any; let mockWindow: any; let comp: AppComponent; let fixture: ComponentFixture; - let parseParams: any; let searchArgs: BBOmnibarSearchArgs; let navigateParams: any; let navigateByUrlParams: any; @@ -74,7 +92,7 @@ describe('AppComponent', () => { omnibarProvider?: any ) { mockWindow = new MockWindow(); - let providers: any[] = [ + const providers: any[] = [ { provide: Router, useValue: { @@ -150,11 +168,9 @@ describe('AppComponent', () => { readyArgs: SkyAppOmnibarReadyArgs, expectedNotCalledWith?: any ) { - let spyOmnibar = spyOn(BBOmnibar, 'load'); + const spyOmnibar = spyOn(BBOmnibar, 'load'); - skyAppConfig.skyux.omnibar = { - experimental: true - }; + skyAppConfig.skyux.omnibar = {}; let readyPromiseResolve: (args: SkyAppOmnibarReadyArgs) => void; @@ -194,7 +210,7 @@ describe('AppComponent', () => { get: (key: any) => false, has: (key: any) => false, hasAllRequiredParams: () => true, - parse: (p: any) => parseParams = p + parse: (p: any) => p } }, skyux: { @@ -240,50 +256,22 @@ describe('AppComponent', () => { })); it('should not call BBOmnibar.load if config.skyux.omnibar does not exist', async(() => { - let spyOmnibar = spyOn(BBOmnibar, 'load'); - let spyOmnibarLegacy = spyOn(BBOmnibarLegacy, 'load'); + const spyOmnibar = spyOn(BBOmnibar, 'load'); setup(skyAppConfig).then(() => { fixture.detectChanges(); fixture.destroy(); expect(spyOmnibar).not.toHaveBeenCalled(); - expect(spyOmnibarLegacy).not.toHaveBeenCalled(); expect(spyOmnibarDestroy).not.toHaveBeenCalled(); }); })); - it('should load the legacy omnibar if "experimental" is not specified', async(() => { - let spyOmnibar = spyOn(BBOmnibarLegacy, 'load'); - - skyAppConfig.skyux.omnibar = {}; - - setup(skyAppConfig).then(() => { - fixture.detectChanges(); - expect(spyOmnibar).toHaveBeenCalled(); - }); - })); - - it('should load the default omnibar if "experimental" is specified', async(() => { - let spyOmnibar = spyOn(BBOmnibar, 'load'); - - skyAppConfig.skyux.omnibar = { - experimental: true - }; - - setup(skyAppConfig).then(() => { - fixture.detectChanges(); - expect(spyOmnibar).toHaveBeenCalled(); - }); - })); - it( 'should load the omnibar outside Angular to avoid change detection during user activity checks', async(() => { const spyOmnibar = spyOn(BBOmnibar, 'load'); - skyAppConfig.skyux.omnibar = { - experimental: true - }; + skyAppConfig.skyux.omnibar = {}; setup(skyAppConfig).then(() => { const zone = fixture.debugElement.injector.get(NgZone); @@ -324,9 +312,7 @@ describe('AppComponent', () => { beforeNavCallback = config.nav.beforeNavCallback; }); - skyAppConfig.skyux.omnibar = { - experimental: true - }; + skyAppConfig.skyux.omnibar = {}; setup(skyAppConfig).then(() => { const zone = fixture.debugElement.injector.get(NgZone); @@ -364,11 +350,9 @@ describe('AppComponent', () => { ); it('should call omnibar destroy if it was loaded', () => { - let spyOmnibarLoad = spyOn(BBOmnibar, 'load'); + const spyOmnibarLoad = spyOn(BBOmnibar, 'load'); - skyAppConfig.skyux.omnibar = { - experimental: true - }; + skyAppConfig.skyux.omnibar = {}; setup(skyAppConfig).then(() => { fixture.detectChanges(); @@ -379,8 +363,8 @@ describe('AppComponent', () => { }); it('should not load the omnibar or help widget if the addin param is 1', () => { - let spyOmnibar = spyOn(BBOmnibar, 'load'); - let spyHelp = spyOn(mockHelpInitService, 'load'); + const spyOmnibar = spyOn(BBOmnibar, 'load'); + const spyHelp = spyOn(mockHelpInitService, 'load'); skyAppConfig.runtime.params.get = (key: string) => key === 'addin' ? '1' : undefined; skyAppConfig.skyux.omnibar = true; @@ -393,11 +377,9 @@ describe('AppComponent', () => { }); it('should set the onSearch property if a search provider is provided', async(() => { - let spyOmnibar = spyOn(BBOmnibar, 'load'); + const spyOmnibar = spyOn(BBOmnibar, 'load'); - skyAppConfig.skyux.omnibar = { - experimental: true - }; + skyAppConfig.skyux.omnibar = {}; setup(skyAppConfig, true).then(() => { fixture.detectChanges(); @@ -406,11 +388,9 @@ describe('AppComponent', () => { })); it('should call the search provider getSearchResults in the onSearch callback', async(() => { - let spyOmnibar = spyOn(BBOmnibar, 'load'); + const spyOmnibar = spyOn(BBOmnibar, 'load'); - skyAppConfig.skyux.omnibar = { - experimental: true - }; + skyAppConfig.skyux.omnibar = {}; setup(skyAppConfig, true).then(() => { fixture.detectChanges(); @@ -425,11 +405,9 @@ describe('AppComponent', () => { })); it('should set the allow anonymous flag based on the app\'s auth configuration', async(() => { - let spyOmnibar = spyOn(BBOmnibar, 'load'); + const spyOmnibar = spyOn(BBOmnibar, 'load'); - skyAppConfig.skyux.omnibar = { - experimental: true - }; + skyAppConfig.skyux.omnibar = {}; skyAppConfig.skyux.auth = true; @@ -445,11 +423,9 @@ describe('AppComponent', () => { })); it('should set the known params on the omnibar config if they exist', async(() => { - let spyOmnibar = spyOn(BBOmnibar, 'load'); + const spyOmnibar = spyOn(BBOmnibar, 'load'); - skyAppConfig.skyux.omnibar = { - experimental: true - }; + skyAppConfig.skyux.omnibar = {}; skyAppConfig.skyux.params = ['envid', 'svcid', 'leid']; skyAppConfig.runtime.params.has = (key: any) => true; @@ -469,9 +445,8 @@ describe('AppComponent', () => { })); it('should not create BBOmnibarNavigation if omnibar.nav is set', async(() => { - let spyOmnibar = spyOn(BBOmnibar, 'load'); + const spyOmnibar = spyOn(BBOmnibar, 'load'); skyAppConfig.skyux.omnibar = { - experimental: true, nav: { junk: true } @@ -484,9 +459,8 @@ describe('AppComponent', () => { })); it('should mark first service as selected if no omnibar.nav.services are selected', async(() => { - let spyOmnibar = spyOn(BBOmnibar, 'load'); + const spyOmnibar = spyOn(BBOmnibar, 'load'); skyAppConfig.skyux.omnibar = { - experimental: true, nav: { services: [ {}, @@ -502,9 +476,8 @@ describe('AppComponent', () => { })); it('should not mark the first service as selected if another one is already marked', async(() => { - let spyOmnibar = spyOn(BBOmnibar, 'load'); + const spyOmnibar = spyOn(BBOmnibar, 'load'); skyAppConfig.skyux.omnibar = { - experimental: true, nav: { services: [ {}, @@ -520,12 +493,11 @@ describe('AppComponent', () => { })); it('should recursively set the url property to omnibar.nav.services.items', async(() => { - let spyOmnibar = spyOn(BBOmnibar, 'load'); + const spyOmnibar = spyOn(BBOmnibar, 'load'); skyAppConfig.skyux.host.url = 'base.com/'; skyAppConfig.runtime.app.base = 'custom-base/'; skyAppConfig.skyux.omnibar = { - experimental: true, nav: { services: [ { @@ -565,12 +537,9 @@ describe('AppComponent', () => { })); it('should add the beforeNavCallback', async(() => { - let spyOmnibar = spyOn(BBOmnibar, 'load'); - - skyAppConfig.skyux.omnibar = { - experimental: true - }; + const spyOmnibar = spyOn(BBOmnibar, 'load'); + skyAppConfig.skyux.omnibar = {}; skyAppConfig.skyux.host.url = 'base.com/'; skyAppConfig.runtime.app.base = 'custom-base/'; @@ -581,12 +550,9 @@ describe('AppComponent', () => { })); it('should enable help for the omnibar when help config is present', async(() => { - let spyOmnibar = spyOn(BBOmnibar, 'load'); - - skyAppConfig.skyux.omnibar = { - experimental: true - }; + const spyOmnibar = spyOn(BBOmnibar, 'load'); + skyAppConfig.skyux.omnibar = {}; skyAppConfig.skyux.help = { productId: 'test-config' }; @@ -601,12 +567,9 @@ describe('AppComponent', () => { })); it('should call navigateByUrl, return false in the beforeNavCallback if local link', async(() => { - let spyOmnibar = spyOn(BBOmnibar, 'load'); - - skyAppConfig.skyux.omnibar = { - experimental: true - }; + const spyOmnibar = spyOn(BBOmnibar, 'load'); + skyAppConfig.skyux.omnibar = {}; skyAppConfig.skyux.host.url = 'base.com/'; skyAppConfig.runtime.app.base = 'custom-base/'; @@ -625,12 +588,9 @@ describe('AppComponent', () => { })); it('should handle global links that start with the same base URL as the SPA', async(() => { - let spyOmnibar = spyOn(BBOmnibar, 'load'); - - skyAppConfig.skyux.omnibar = { - experimental: true - }; + const spyOmnibar = spyOn(BBOmnibar, 'load'); + skyAppConfig.skyux.omnibar = {}; skyAppConfig.skyux.host.url = 'base.com/'; skyAppConfig.runtime.app.base = 'custom-base/'; @@ -638,19 +598,16 @@ describe('AppComponent', () => { fixture.detectChanges(); const cb = spyOmnibar.calls.first().args[0].nav.beforeNavCallback; - let globalLink = cb({ url: 'base.com/custom-base-2' }); + const globalLink = cb({ url: 'base.com/custom-base-2' }); expect(globalLink).toEqual(true); expect(navigateByUrlParams).not.toBeDefined(); }); })); it('should use the original url casing if calling navigateByUrl', async(() => { - let spyOmnibar = spyOn(BBOmnibar, 'load'); - - skyAppConfig.skyux.omnibar = { - experimental: true - }; + const spyOmnibar = spyOn(BBOmnibar, 'load'); + skyAppConfig.skyux.omnibar = {}; skyAppConfig.skyux.host.url = 'base.com/'; skyAppConfig.runtime.app.base = 'custom-base/'; @@ -665,12 +622,9 @@ describe('AppComponent', () => { })); it('should handle no public routes during serve', async(() => { - let spyOmnibar = spyOn(BBOmnibar, 'load'); - - skyAppConfig.skyux.omnibar = { - experimental: true - }; + const spyOmnibar = spyOn(BBOmnibar, 'load'); + skyAppConfig.skyux.omnibar = {}; skyAppConfig.runtime.command = 'serve'; skyAppConfig.skyux.routes = {}; @@ -681,12 +635,9 @@ describe('AppComponent', () => { })); it('should add global public routes as localNavItems during serve', async(() => { - let spyOmnibar = spyOn(BBOmnibar, 'load'); - - skyAppConfig.skyux.omnibar = { - experimental: true - }; + const spyOmnibar = spyOn(BBOmnibar, 'load'); + skyAppConfig.skyux.omnibar = {}; skyAppConfig.skyux.host.url = 'base.com/'; skyAppConfig.runtime.app.base = 'custom-base/'; skyAppConfig.runtime.command = 'serve'; @@ -720,7 +671,7 @@ describe('AppComponent', () => { })); it('should not call HelpInitializationService.load if help config does not exist', async(() => { - let spyHelp = spyOn(mockHelpInitService, 'load'); + const spyHelp = spyOn(mockHelpInitService, 'load'); setup(skyAppConfig).then(() => { fixture.detectChanges(); expect(spyHelp).not.toHaveBeenCalled(); @@ -728,7 +679,7 @@ describe('AppComponent', () => { })); it('should pass help config to HelpInitializationService.load', async(() => { - let spyHelp = spyOn(mockHelpInitService, 'load'); + const spyHelp = spyOn(mockHelpInitService, 'load'); skyAppConfig.skyux.help = { productId: 'test-config' }; skyAppConfig.runtime.params.has = (key: any) => false; setup(skyAppConfig).then(() => { @@ -738,7 +689,7 @@ describe('AppComponent', () => { })); it('should assign help config extends key to the svcid if one exists', async(() => { - let spyHelp = spyOn(mockHelpInitService, 'load'); + const spyHelp = spyOn(mockHelpInitService, 'load'); const expectedCall = { productId: 'test-config', extends: 'help-extend' }; skyAppConfig.skyux.help = { productId: 'test-config' }; @@ -754,7 +705,7 @@ describe('AppComponent', () => { })); it('should assign help config locale key if none exist and host exposes the browser language', async(() => { - let spyHelp = spyOn(mockHelpInitService, 'load'); + const spyHelp = spyOn(mockHelpInitService, 'load'); skyAppConfig.runtime.params.has = (key: any) => key === false; @@ -772,7 +723,7 @@ describe('AppComponent', () => { })); it('should fallback to \'\' for the locale if SKYUX_HOST.acceptLanguage does not exist', async(() => { - let spyHelp = spyOn(mockHelpInitService, 'load'); + const spyHelp = spyOn(mockHelpInitService, 'load'); skyAppConfig.runtime.params.has = (key: any) => key === false; @@ -788,7 +739,7 @@ describe('AppComponent', () => { })); it('should not override a locale that has been passed into the config', async(() => { - let spyHelp = spyOn(mockHelpInitService, 'load'); + const spyHelp = spyOn(mockHelpInitService, 'load'); mockSkyuxHost = { acceptLanguage: 'fr-ca' }; @@ -819,7 +770,7 @@ describe('AppComponent', () => { viewport .visible - .subscribe((value) => { + .subscribe((value: boolean) => { viewportVisible = value; }); diff --git a/src/app/app.component.ts b/src/app/app.component.ts index 70be5b86..c17fcfc0 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -13,23 +13,33 @@ import { import { BBOmnibar, - BBOmnibarLegacy, BBOmnibarNavigation, BBOmnibarNavigationItem, BBOmnibarSearchArgs } from '@blackbaud/auth-client'; -import { HelpInitializationService } from '@blackbaud/skyux-lib-help'; +import { + HelpInitializationService +} from '@blackbaud/skyux-lib-help'; + +import { + SkyAppConfig +} from '@skyux/config'; + +import { + SkyAppWindowRef +} from '@skyux/core'; import { - SkyAppConfig, SkyAppOmnibarProvider, SkyAppOmnibarReadyArgs, - SkyAppSearchResultsProvider, + SkyAppSearchResultsProvider +} from '@skyux/omnibar-interop'; + +import { SkyAppStyleLoader, - SkyAppViewportService, - SkyAppWindowRef -} from '@blackbaud/skyux-builder/runtime'; + SkyAppViewportService +} from '@skyux/theme'; require('style-loader!@skyux/theme/css/sky.css'); require('style-loader!./app.component.scss'); @@ -209,7 +219,7 @@ export class AppComponent implements OnInit, OnDestroy { if (globalRoutes) { const localNavItems: BBOmnibarNavigationItem[] = []; - for (let route of globalRoutes) { + for (const route of globalRoutes) { localNavItems.push({ title: route.name, url: fixUpUrl(baseUrl, route.route, this.config), @@ -258,13 +268,7 @@ export class AppComponent implements OnInit, OnDestroy { // triggers change detection on each interval. Loading the omnibar outside // Angular will keep change detection from being triggered during each interval. this.zone.runOutsideAngular(() => { - if (omnibarConfig.experimental) { - // auth-client 2.0 made the "experimental" omnibar the default; maintain - // previous behavior until skyux-builder 2.0. - BBOmnibar.load(omnibarConfig); - } else { - BBOmnibarLegacy.load(omnibarConfig); - } + BBOmnibar.load(omnibarConfig); omnibarLoaded = true; }); }; @@ -292,7 +296,7 @@ export class AppComponent implements OnInit, OnDestroy { } if (skyuxHost && !helpConfig.locale) { - let browserLanguages = skyuxHost.acceptLanguage || ''; + const browserLanguages = skyuxHost.acceptLanguage || ''; helpConfig.locale = browserLanguages.split(',')[0]; } diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 4b256922..9923ba25 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -1,19 +1,36 @@ // This is only visible in EASY MODE -import { NgModule } from '@angular/core'; -import { RouterModule } from '@angular/router'; -import { BrowserModule } from '@angular/platform-browser'; -import { AppComponent } from './app.component'; +import { + NgModule +} from '@angular/core'; + +import { + BrowserModule +} from '@angular/platform-browser'; + +import { + RouterModule +} from '@angular/router'; + +import { + AppComponent +} from './app.component'; // File is dynamically built using webpack loader -import { SkyPagesModule } from './sky-pages.module'; +import { + SkyPagesModule +} from './sky-pages.module'; @NgModule({ - declarations: [ AppComponent ], - imports: [ - BrowserModule, - RouterModule, - SkyPagesModule - ], - bootstrap: [ AppComponent ] + declarations: [ + AppComponent + ], + imports: [ + BrowserModule, + RouterModule, + SkyPagesModule + ], + bootstrap: [ + AppComponent + ] }) export class AppModule { } diff --git a/src/app/sky-pages.module.ts b/src/app/sky-pages.module.ts index 04a5142f..7a048ac0 100644 --- a/src/app/sky-pages.module.ts +++ b/src/app/sky-pages.module.ts @@ -1,5 +1,10 @@ +import { + NgModule +} from '@angular/core'; + // File dynamically generated via webpack. // Matching definition makes IDE's happy. +@NgModule({}) export class SkyPagesModule {} // The following comment is used to track timestamps in `skyux serve` diff --git a/src/main-internal.aot.ts b/src/main-internal.aot.ts index c8008ab9..356e2e7b 100644 --- a/src/main-internal.aot.ts +++ b/src/main-internal.aot.ts @@ -1,8 +1,11 @@ -import { platformBrowser } from '@angular/platform-browser'; -import { AppModuleNgFactory } from './ngfactory/app/app.module.ngfactory'; +import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; +import { AppModule } from './app/app.module'; -import { SkyAppBootstrapper } from '@blackbaud/skyux-builder/runtime/bootstrapper'; +import { SkyAppBootstrapper } from '@skyux-sdk/builder/runtime/bootstrapper'; + +// We can now use the dynamic bootstrapper with @ngtools/webpack. +// See: https://blog.craftlab.hu/multiple-solutions-for-angular-ahead-of-time-aot-compilation-c474d9a0d508#71de SkyAppBootstrapper.processBootstrapConfig().then(() => { - platformBrowser().bootstrapModuleFactory(AppModuleNgFactory); + platformBrowserDynamic().bootstrapModule(AppModule); }); diff --git a/src/main-internal.ts b/src/main-internal.ts index 647058d8..85e6e310 100644 --- a/src/main-internal.ts +++ b/src/main-internal.ts @@ -1,9 +1,20 @@ declare var module: any; -import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; -import { NgModuleRef } from '@angular/core'; -import { AppModule } from './app/app.module'; -import { SkyAppBootstrapper } from '../runtime/bootstrapper'; +import { + NgModuleRef +} from '@angular/core'; + +import { + platformBrowserDynamic +} from '@angular/platform-browser-dynamic'; + +import { + SkyAppBootstrapper +} from '@skyux-sdk/builder/runtime/bootstrapper'; + +import { + AppModule +} from './app/app.module'; SkyAppBootstrapper .processBootstrapConfig() diff --git a/src/polyfills.ts b/src/polyfills.ts index bf1e21f5..7867a747 100644 --- a/src/polyfills.ts +++ b/src/polyfills.ts @@ -1,14 +1,33 @@ -import 'core-js/es6'; +/* IE9, IE10 and IE11 requires all of the following polyfills. */ +import 'core-js/es6/symbol'; +import 'core-js/es6/object'; +import 'core-js/es6/function'; +import 'core-js/es6/parse-int'; +import 'core-js/es6/parse-float'; +import 'core-js/es6/number'; +import 'core-js/es6/math'; +import 'core-js/es6/string'; +import 'core-js/es6/date'; +import 'core-js/es6/array'; +import 'core-js/es6/regexp'; +import 'core-js/es6/map'; +import 'core-js/es6/weak-map'; +import 'core-js/es6/set'; + +/* IE10 and IE11 requires the following for the Reflect API. */ +import 'core-js/es6/reflect'; + +/* Evergreen browsers require these. */ +// Used for reflect-metadata in JIT. If you use AOT (and only Angular decorators), you can remove. import 'core-js/es7/reflect'; -import 'zone.js/dist/zone'; -import 'ts-helpers'; -import 'web-animations-js/web-animations.min'; +/** + * Required to support Web Animations `@angular/platform-browser/animations`. + * Needed for: All but Chrome, Firefox and Opera. http://caniuse.com/#feat=web-animation + */ +import 'web-animations-js'; -if (process.env.ENV === 'production') { - // Production -} else { - // Development - Error['stackTraceLimit'] = Infinity; - require('zone.js/dist/long-stack-trace-zone'); -} +/** + * Zone JS is required by default for Angular itself. + */ +import 'zone.js/dist/zone'; diff --git a/src/vendor.ts b/src/vendor.ts deleted file mode 100644 index 204f8acd..00000000 --- a/src/vendor.ts +++ /dev/null @@ -1,11 +0,0 @@ -// Angular 2 -import '@angular/platform-browser-dynamic'; -import '@angular/core'; -import '@angular/common'; -import '@angular/http'; -import '@angular/router'; - -// RxJS -import 'rxjs'; -// Other vendors for example jQuery, Lodash or Bootstrap -// You can import js, ts, css, sass, ... diff --git a/test/cli-build-public-library.spec.js b/test/cli-build-public-library.spec.js index ca4eb38b..a81c360e 100644 --- a/test/cli-build-public-library.spec.js +++ b/test/cli-build-public-library.spec.js @@ -176,7 +176,7 @@ export class SkyLibPlaceholderModule {} it('should handle transpilation errors', (done) => { const cliCommand = mock.reRequire(requirePath); - const spy = spyOn(logger, 'error').and.callThrough(); + const spy = spyOn(logger, 'error'); spyOn(mockSpawn, 'sync').and.returnValue({ err: 'something bad happened' }); diff --git a/test/cli-build.spec.js b/test/cli-build.spec.js index 30cf1df0..09fbcff1 100644 --- a/test/cli-build.spec.js +++ b/test/cli-build.spec.js @@ -5,9 +5,12 @@ const mock = require('mock-require'); const logger = require('@blackbaud/skyux-logger'); describe('cli build', () => { + beforeEach(() => { + spyOn(logger, 'info'); + spyOn(logger, 'error'); + }); it('should log when the build is completed successfully', (done) => { - spyOn(logger, 'info'); mock('../cli/utils/run-build', () => Promise.resolve()); mock.reRequire('../cli/build')('build', {}, {}).then(() => { @@ -28,7 +31,6 @@ describe('cli build', () => { it('should log errors and set exit code to 1', (done) => { const errors = 'errors'; - spyOn(logger, 'error'); spyOn(process, 'exit'); mock('../cli/utils/run-build', () => Promise.reject(errors)); diff --git a/test/cli-e2e.spec.js b/test/cli-e2e.spec.js index d41e530b..68fac550 100644 --- a/test/cli-e2e.spec.js +++ b/test/cli-e2e.spec.js @@ -112,18 +112,6 @@ describe('cli e2e', () => { mock.reRequire('../cli/e2e')('e2e', ARGV, SKY_PAGES_CONFIG, WEBPACK); }); - it('should catch protractor kitchen sink error', (done) => { - spyOn(logger, 'warn'); - spyOn(process, 'exit').and.callFake(exitCode => { - expect(logger.warn).toHaveBeenCalledWith('Supressing protractor\'s "kitchen sink" error 199'); - expect(exitCode).toEqual(0); - done(); - }); - - EXIT_CODE = 199; - mock.reRequire('../cli/e2e')('e2e', ARGV, SKY_PAGES_CONFIG, WEBPACK); - }); - it('should install, start, and kill selenium only if a seleniumAddress is specified', (done) => { let killCalled = false; diff --git a/test/cli-utils-browser.spec.js b/test/cli-utils-browser.spec.js index 6c557160..55c41a0b 100644 --- a/test/cli-utils-browser.spec.js +++ b/test/cli-utils-browser.spec.js @@ -20,10 +20,10 @@ describe('browser utils', () => { openParamUrl = ''; openParamBrowser = undefined; - mock('open', (url, browser) => { + mock('opn', (url, options) => { openCalled = true; openParamUrl = url; - openParamBrowser = browser; + openParamBrowser = options.app; }); spyOn(logger, 'info'); diff --git a/test/cli-utils-config-resolver.spec.js b/test/cli-utils-config-resolver.spec.js index a6c56e8d..4e30397d 100644 --- a/test/cli-utils-config-resolver.spec.js +++ b/test/cli-utils-config-resolver.spec.js @@ -5,6 +5,11 @@ const mock = require('mock-require'); const logger = require('@blackbaud/skyux-logger'); describe('utils/config-resolver.js', () => { + beforeEach(() => { + spyOn(logger, 'info').and.callThrough(); + spyOn(logger, 'warn').and.callThrough(); + spyOn(logger, 'error').and.callThrough(); + }); afterEach(() => { mock.stopAll(); @@ -39,7 +44,6 @@ describe('utils/config-resolver.js', () => { }); it('should handle finding zero external configurations', () => { - spyOn(logger, 'error'); spyOn(process, 'exit'); const config = setup('test', [], false, {}); @@ -55,9 +59,6 @@ describe('utils/config-resolver.js', () => { }); it('should warn if multiple external config files found, but default to first', () => { - spyOn(logger, 'warn'); - spyOn(logger, 'info'); - const results = [ 'one-too.js', 'many-files.js' diff --git a/test/cli-utils-prepare-library-package.spec.js b/test/cli-utils-prepare-library-package.spec.js index 76c4ad2a..549e0de9 100644 --- a/test/cli-utils-prepare-library-package.spec.js +++ b/test/cli-utils-prepare-library-package.spec.js @@ -1,14 +1,35 @@ /*jshint jasmine: true, node: true */ 'use strict'; -const fs = require('fs-extra'); const mock = require('mock-require'); -const logger = require('@blackbaud/skyux-logger'); describe('cli utils prepare-library-package', () => { let util; + let mockFsExtra; + let mockLogger; beforeEach(() => { + mockFsExtra = { + copySync() {}, + existsSync() { + return true; + }, + readJsonSync() { + return {}; + }, + writeJsonSync() {} + }; + + mockLogger = { + error() {}, + info() {}, + warn() {} + }; + + mock('@blackbaud/skyux-logger', mockLogger); + + mock('fs-extra', mockFsExtra); + mock('../config/sky-pages/sky-pages.config', { spaPath: (...args) => args.join('/') }); @@ -24,37 +45,41 @@ describe('cli utils prepare-library-package', () => { }); it('should update the module property of package.json and write it to dist', () => { - spyOn(fs, 'copySync').and.returnValue(); - spyOn(fs, 'readJsonSync').and.returnValue({}); - spyOn(fs, 'writeJsonSync').and.callFake((filePath, contents) => { + const readSpy = spyOn(mockFsExtra, 'readJsonSync').and.returnValue({}); + const writeSpy = spyOn(mockFsExtra, 'writeJsonSync').and.callFake((filePath, contents) => { expect(filePath.match('dist')).not.toEqual(null); expect(contents.module).toEqual('index.js'); }); - spyOn(fs, 'existsSync').and.returnValue(true); + util(); - expect(fs.readJsonSync).toHaveBeenCalled(); - expect(fs.writeJsonSync).toHaveBeenCalled(); + + expect(readSpy).toHaveBeenCalled(); + expect(writeSpy).toHaveBeenCalled(); }); it('should copy readme, changelog, and assets to dist', () => { - spyOn(fs, 'readJsonSync').and.returnValue({}); - spyOn(fs, 'writeJsonSync').and.returnValue(); - spyOn(fs, 'copySync').and.returnValue(); - spyOn(fs, 'existsSync').and.returnValue(true); + const copySpy = spyOn(mockFsExtra, 'copySync').and.returnValue(); + util(); - expect(fs.copySync).toHaveBeenCalledWith('README.md', 'dist/README.md'); - expect(fs.copySync).toHaveBeenCalledWith('CHANGELOG.md', 'dist/CHANGELOG.md'); - expect(fs.copySync).toHaveBeenCalledWith('src/assets', 'dist/src/assets'); + + expect(copySpy).toHaveBeenCalledWith('README.md', 'dist/README.md'); + expect(copySpy).toHaveBeenCalledWith('CHANGELOG.md', 'dist/CHANGELOG.md'); + expect(copySpy).toHaveBeenCalledWith('src/assets', 'dist/src/assets'); }); it('should warn consumers if they do not include a readme, changelog, or assets', () => { - const loggerSpy = spyOn(logger, 'warn'); + spyOn(mockFsExtra, 'existsSync').and.callFake((file) => { + if (file === 'README.md') { + return false; + } + + return true; + }); + + const loggerSpy = spyOn(mockLogger, 'warn'); - spyOn(fs, 'readJsonSync').and.returnValue({}); - spyOn(fs, 'writeJsonSync').and.returnValue(); - spyOn(fs, 'copySync').and.callFake(() => {}); - spyOn(fs, 'existsSync').and.returnValue(false); util(); + expect(loggerSpy).toHaveBeenCalledWith('File(s) not found: README.md'); }); }); diff --git a/test/cli-utils-run-build.spec.js b/test/cli-utils-run-build.spec.js index fbe02d08..bdb47240 100644 --- a/test/cli-utils-run-build.spec.js +++ b/test/cli-utils-run-build.spec.js @@ -9,6 +9,7 @@ const localeAssetsProcessor = require('../lib/locale-assets-processor'); describe('cli utils run build', () => { let mockAssetsProcessor; let mockLocaleProcessor; + let mockFsExtra; beforeEach(() => { mockLocaleProcessor = { @@ -20,7 +21,24 @@ describe('cli utils run build', () => { mockAssetsProcessor = { setSkyAssetsLoaderUrl() {}, getAssetsUrl: () => '', - processAssets: (content) => content + processAssets: (content, assetsUrl, callback) => { + callback('file-with-hash.json', 'physical-file-path.json'); + return content; + } + }; + + mockFsExtra = { + copySync() {}, + emptyDirSync() {}, + ensureDirSync() {}, + ensureFileSync() {}, + readFileSync() { + return '{}'; + }, + removeSync() {}, + writeFileSync() {}, + writeJSONSync() {}, + writeJsonSync() {} }; spyOn(process, 'exit').and.callFake(() => {}); @@ -36,6 +54,7 @@ describe('cli utils run build', () => { }); mock('../lib/locale-assets-processor', mockLocaleProcessor); mock('../lib/assets-processor', mockAssetsProcessor); + mock('fs-extra', mockFsExtra); }); afterEach(() => { @@ -75,7 +94,6 @@ describe('cli utils run build', () => { }); it('should write files to disk in AoT compile mode', (done) => { - const fs = require('fs-extra'); const generator = require('../lib/sky-pages-module-generator'); const skyPagesConfigUtil = require('../config/sky-pages/sky-pages.config'); @@ -85,10 +103,10 @@ describe('cli utils run build', () => { getWebpackConfig: () => ({}) }); - const writeJSONSpy = spyOn(fs, 'writeJSONSync'); - const copySpy = spyOn(fs, 'copySync'); - const writeFileSpy = spyOn(fs, 'writeFileSync'); - const removeSpy = spyOn(fs, 'removeSync'); + const writeJSONSpy = spyOn(mockFsExtra, 'writeJSONSync'); + const copySpy = spyOn(mockFsExtra, 'copySync'); + const writeFileSpy = spyOn(mockFsExtra, 'writeFileSync'); + const removeSpy = spyOn(mockFsExtra, 'removeSync'); let passedConfig; spyOn(generator, 'getSource').and.callFake(function (c) { @@ -122,8 +140,6 @@ describe('cli utils run build', () => { expect(removeSpy).toHaveBeenCalledWith( skyPagesConfigUtil.spaPathTemp() ); - expect(passedConfig.hasOwnProperty('skyuxPathAlias')).toBe(false); - done(); }); @@ -153,61 +169,18 @@ describe('cli utils run build', () => { expect(writeJSONSpy).toHaveBeenCalledWith( skyPagesConfigUtil.spaPathTempSrc('tsconfig.json'), jasmine.objectContaining({ - 'files': [ - './app/app.module.ts' + 'include': [ + skyPagesConfigUtil.outPath('runtime', '**', '*'), + skyPagesConfigUtil.outPath('src', '**', '*'), + skyPagesConfigUtil.spaPathTempSrc('**', '*') ] }) ); - mock.stop(f); - }); - - it('should allow the SKY UX import path to be overridden', (done) => { - const generator = require('../lib/sky-pages-module-generator'); - - const f = '../config/webpack/build-aot.webpack.config'; - - mock(f, { - getWebpackConfig: () => ({}) - }); - - let calledConfig; - - spyOn(generator, 'getSource').and.callFake(function (c) { - calledConfig = c; - return 'TESTSOURCE'; - }); - - mock.reRequire('../cli/utils/run-build')( - {}, - { - runtime: runtimeUtils.getDefaultRuntime(), - skyux: { - compileMode: 'aot', - importPath: 'asdf' - } - }, - () => ({ - run: (cb) => { - cb( - null, - { - toJson: () => ({ - errors: [], - warnings: [] - }) - } - ); - - // The default SKY UX Builder source files should be written first. - expect(calledConfig.runtime.skyuxPathAlias).toEqual('../../asdf'); - - mock.stop(f); - done(); - } - }) + expect(writeFileSpy).toHaveBeenCalledWith( + skyPagesConfigUtil.outPath('dist', 'file-with-hash.json'), + '{}' ); - }); it('should allow the assets base URL to be specified', (done) => { @@ -226,8 +199,7 @@ describe('cli utils run build', () => { { runtime: runtimeUtils.getDefaultRuntime(), skyux: { - compileMode: 'aot', - importPath: 'asdf' + compileMode: 'aot' } }, () => ({ @@ -250,7 +222,6 @@ describe('cli utils run build', () => { undefined ); } finally { - mock.stop(f); done(); } } diff --git a/test/cli-utils-stage-library-ts.spec.js b/test/cli-utils-stage-library-ts.spec.js index 460002f8..d45bf99f 100644 --- a/test/cli-utils-stage-library-ts.spec.js +++ b/test/cli-utils-stage-library-ts.spec.js @@ -38,9 +38,9 @@ describe('cli utils prepare-library-package', () => { const spy = spyOn(glob, 'sync').and.callFake((pattern) => { if (pattern.match('.spec.')) { return ['index.spec.ts']; - } else { - return []; } + + return []; }); util(); @@ -54,9 +54,9 @@ describe('cli utils prepare-library-package', () => { const spy = spyOn(glob, 'sync').and.callFake(pattern => { if (pattern.match('.spec.')) { return []; - } else { - return ['index.component.ts']; } + + return ['index.component.ts']; }); spyOn(fs, 'readFileSync').and.callFake(filePath => { @@ -94,9 +94,50 @@ describe('cli utils prepare-library-package', () => { spyOn(glob, 'sync').and.callFake(pattern => { if (pattern.match('.spec.')) { return []; - } else { - return ['index.component.ts']; } + + return ['index.component.ts']; + }); + + spyOn(fs, 'readFileSync').and.callFake(filePath => { + if (filePath === 'index.component.ts') { + return ` + @Component({ + templateUrl: 'template.component.html', + styleUrls: [ + 'template.component.scss' + ] + }) + export class SampleComponent { } + `; + } + + if (filePath === 'template.component.html') { + return '

'; + } + }); + + spyOn(fs, 'writeFileSync').and.callFake((file, contents) => { + finalContents = contents; + }); + + spyOn(sass, 'renderSync').and.returnValue({ + css: 'p { color: black; }' + }); + + util(); + expect(finalContents.match('p { color: black; }')).not.toEqual(null); + }); + + it('should handle multiline styleUrls array', () => { + let finalContents; + + spyOn(glob, 'sync').and.callFake(pattern => { + if (pattern.match('.spec.')) { + return []; + } + + return ['index.component.ts']; }); spyOn(fs, 'readFileSync').and.callFake(filePath => { diff --git a/test/cli-version.spec.js b/test/cli-version.spec.js index 016fedea..b79a6765 100644 --- a/test/cli-version.spec.js +++ b/test/cli-version.spec.js @@ -18,7 +18,7 @@ describe('cli version', () => { proxyquire('../cli/version', stubs)(); expect(logger.info).toHaveBeenCalledWith( - '@blackbaud/skyux-builder: %s', + '@skyux-sdk/builder: %s', version ); }); diff --git a/test/config-webpack-build-aot.spec.js b/test/config-webpack-build-aot.spec.js index 67aa0139..dd48493a 100644 --- a/test/config-webpack-build-aot.spec.js +++ b/test/config-webpack-build-aot.spec.js @@ -1,18 +1,35 @@ /*jshint jasmine: true, node: true */ 'use strict'; -const fs = require('fs'); const mock = require('mock-require'); const skyPagesConfigUtil = require('../config/sky-pages/sky-pages.config'); const runtimeUtils = require('../utils/runtime-test-utils'); describe('config webpack build-aot', () => { - const ngtoolsWebpackPath = '@ngtools/webpack'; + let mockFsExtra; + let mockWebpackConfig; beforeEach(() => { - mock(ngtoolsWebpackPath, { - AotPlugin: function () { + mockFsExtra = { + existsSync() {}, + writeFileSync() {} + }; + mockWebpackConfig = { + module: { + rules: [] + } + }; + + mock('fs-extra', mockFsExtra); + + mock('@ngtools/webpack', { + AngularCompilerPlugin: function () {} + }); + + mock('../config/webpack/common.webpack.config', { + getWebpackConfig: () => { + return mockWebpackConfig; } }); }); @@ -22,17 +39,12 @@ describe('config webpack build-aot', () => { }); it('should expose a getWebpackConfig method', () => { - const lib = require('../config/webpack/build-aot.webpack.config'); + const lib = mock.reRequire('../config/webpack/build-aot.webpack.config'); expect(typeof lib.getWebpackConfig).toEqual('function'); }); it('should merge the common webpack config with overrides', () => { - const f = '../config/webpack/common.webpack.config'; - mock(f, { - getWebpackConfig: () => ({ module: { rules: [] } }) - }); - - const lib = require('../config/webpack/build-aot.webpack.config'); + const lib = mock.reRequire('../config/webpack/build-aot.webpack.config'); const skyPagesConfig = { runtime: runtimeUtils.getDefaultRuntime({ @@ -49,37 +61,31 @@ describe('config webpack build-aot', () => { expect(command).toBe(skyPagesConfig.runtime.command); } }); - - mock.stop(f); }); it('should use the AoT entry module', () => { - const f = '../config/webpack/common.webpack.config'; - mock(f, { - getWebpackConfig: () => ({ module: { rules: [] } }) - }); - - const lib = require('../config/webpack/build-aot.webpack.config'); + const lib = mock.reRequire('../config/webpack/build-aot.webpack.config'); const config = lib.getWebpackConfig({ runtime: runtimeUtils.getDefaultRuntime(), skyux: {} }); - expect( - config.entry.app[0] - ).toBe(skyPagesConfigUtil.spaPathTempSrc('main-internal.aot.ts')); - - mock.stop(f); + expect(config.entry.app[0]) + .toBe(skyPagesConfigUtil.spaPathTempSrc('main-internal.aot.ts')); }); it('should write metadata.json file and match entries order', () => { let json; - spyOn(fs, 'writeFileSync').and.callFake((file, content) => { + + spyOn(mockFsExtra, 'writeFileSync').and.callFake((file, content) => { json = JSON.parse(content); }); - const lib = require('../config/webpack/build-aot.webpack.config'); + // Need to refresh cache in order to spy on fs-extra. + mock.reRequire('../plugin/save-metadata'); + + const lib = mock.reRequire('../config/webpack/build-aot.webpack.config'); const config = lib.getWebpackConfig({ runtime: runtimeUtils.getDefaultRuntime(), skyux: { @@ -144,14 +150,16 @@ describe('config webpack build-aot', () => { } }); - expect(fs.writeFileSync).toHaveBeenCalled(); - expect(json[0].name).toEqual('test3.js'); + expect(mockFsExtra.writeFileSync).toHaveBeenCalled(); + + // Host Utils reverses the scripts. + expect(json[0].name).toEqual('test2.js'); expect(json[1].name).toEqual('test1.js'); - expect(json[2].name).toEqual('test2.js'); + expect(json[2].name).toEqual('test3.js'); }); it('should add the SKY_PAGES_READY_X variable to each entry, replacing periods', () => { - const lib = require('../config/webpack/build-aot.webpack.config'); + const lib = mock.reRequire('../config/webpack/build-aot.webpack.config'); const config = lib.getWebpackConfig({ runtime: runtimeUtils.getDefaultRuntime(), skyux: { @@ -194,24 +202,22 @@ describe('config webpack build-aot', () => { }); it('should remove the sky-processor loader from the rules array', () => { - const f = '../config/webpack/common.webpack.config'; const loaderName = '/sky-processor/'; - mock(f, { - getWebpackConfig: () => ({ - module: { - rules: [ - { - loader: 'test-loader' - }, - { - loader: loaderName - } - ] - } - }) - }); - const lib = require('../config/webpack/build-aot.webpack.config'); + mockWebpackConfig = { + module: { + rules: [ + { + loader: 'test-loader' + }, + { + loader: loaderName + } + ] + } + }; + + const lib = mock.reRequire('../config/webpack/build-aot.webpack.config'); const skyPagesConfig = { runtime: runtimeUtils.getDefaultRuntime(), @@ -219,40 +225,30 @@ describe('config webpack build-aot', () => { }; const config = lib.getWebpackConfig(skyPagesConfig); - - let found = false; - - config.module.rules.forEach((rule) => { - if (found) { - return; - } - - found = (rule.loader && rule.loader.indexOf(loaderName) > -1); + const found = !!config.module.rules.find((rule) => { + return (rule.loader && rule.loader.indexOf(loaderName) > -1); }); expect(found).toEqual(false); - expect(config.module.rules.length).toEqual(2); }); it('should remove the sky-processor loader from the rules array (on Windows)', () => { - const f = '../config/webpack/common.webpack.config'; const loaderName = '\\sky-processor\\'; - mock(f, { - getWebpackConfig: () => ({ - module: { - rules: [ - { - loader: 'test-loader' - }, - { - loader: loaderName - } - ] - } - }) - }); - const lib = require('../config/webpack/build-aot.webpack.config'); + mockWebpackConfig = { + module: { + rules: [ + { + loader: 'test-loader' + }, + { + loader: loaderName + } + ] + } + }; + + const lib = mock.reRequire('../config/webpack/build-aot.webpack.config'); const skyPagesConfig = { runtime: runtimeUtils.getDefaultRuntime(), @@ -260,19 +256,11 @@ describe('config webpack build-aot', () => { }; const config = lib.getWebpackConfig(skyPagesConfig); - - let found = false; - - config.module.rules.forEach((rule) => { - if (found) { - return; - } - - found = (rule.loader && rule.loader.indexOf(loaderName) > -1); + const found = !!config.module.rules.find((rule) => { + return (rule.loader && rule.loader.indexOf(loaderName) > -1); }); expect(found).toEqual(false); - expect(config.module.rules.length).toEqual(2); }); }); diff --git a/test/config-webpack-build-public-library.spec.js b/test/config-webpack-build-public-library.spec.js index 49a3901a..09be85a3 100644 --- a/test/config-webpack-build-public-library.spec.js +++ b/test/config-webpack-build-public-library.spec.js @@ -20,7 +20,7 @@ describe('config webpack build public library', () => { }; mockNgTools = { - AotPlugin: function () {} + AngularCompilerPlugin: function () {} }; skyPagesConfig = { @@ -118,15 +118,16 @@ describe('config webpack build public library', () => { }); it('should setup AOT compilation', () => { + const spy = spyOn(mockNgTools, 'AngularCompilerPlugin').and.callThrough(); const lib = mock.reRequire(configPath); - const spy = spyOn(mockNgTools, 'AotPlugin').and.callThrough(); lib.getWebpackConfig(skyPagesConfig); expect(spy).toHaveBeenCalledWith({ tsConfigPath: 'temp', entryModule: 'temp#SkyLibPlaceholderModule', - sourceMap: true + sourceMap: false, + typeChecking: false }); }); }); diff --git a/test/config-webpack-build.spec.js b/test/config-webpack-build.spec.js index bd169757..05cb7784 100644 --- a/test/config-webpack-build.spec.js +++ b/test/config-webpack-build.spec.js @@ -1,23 +1,45 @@ /*jshint jasmine: true, node: true */ 'use strict'; -const fs = require('fs'); const mock = require('mock-require'); const runtimeUtils = require('../utils/runtime-test-utils'); describe('config webpack build', () => { + let mockFsExtra; + let mockWebpackConfig; + + beforeEach(() => { + mockFsExtra = { + existsSync() {}, + writeFileSync() {} + }; + + mockWebpackConfig = { + module: { + rules: [] + } + }; + + mock('fs-extra', mockFsExtra); + + mock('../config/webpack/common.webpack.config', { + getWebpackConfig: () => { + return mockWebpackConfig; + } + }); + }); + + afterEach(() => { + mock.stopAll(); + }); + it('should expose a getWebpackConfig method', () => { - const lib = require('../config/webpack/build.webpack.config'); + const lib = mock.reRequire('../config/webpack/build.webpack.config'); expect(typeof lib.getWebpackConfig).toEqual('function'); }); it('should merge the common webpack config with overrides', () => { - const f = './common.webpack.config'; - mock(f, { - getWebpackConfig: () => ({}) - }); - - const lib = require('../config/webpack/build.webpack.config'); + const lib = mock.reRequire('../config/webpack/build.webpack.config'); const skyPagesConfig = { runtime: runtimeUtils.getDefaultRuntime(), @@ -34,17 +56,19 @@ describe('config webpack build', () => { expect(command).toBe(skyPagesConfig.skyux.command); } }); - - mock.stop(f); }); it('should write metadata.json file and match entries order', () => { let json; - spyOn(fs, 'writeFileSync').and.callFake((file, content) => { + + const writeSpy = spyOn(mockFsExtra, 'writeFileSync').and.callFake((file, content) => { json = JSON.parse(content); }); - const lib = require('../config/webpack/build.webpack.config'); + // Need to refresh cache in order to spy on fs-extra. + mock.reRequire('../plugin/save-metadata'); + + const lib = mock.reRequire('../config/webpack/build.webpack.config'); const config = lib.getWebpackConfig({ runtime: runtimeUtils.getDefaultRuntime(), skyux: {} @@ -107,15 +131,17 @@ describe('config webpack build', () => { } }); - expect(fs.writeFileSync).toHaveBeenCalled(); - expect(json[0].name).toEqual('test3.js'); + expect(writeSpy).toHaveBeenCalled(); + + // Host Utils reverses the scripts. + expect(json[0].name).toEqual('test2.js'); expect(json[1].name).toEqual('test1.js'); - expect(json[2].name).toEqual('test2.js'); + expect(json[2].name).toEqual('test3.js'); }); it('should add the SKY_PAGES_READY_X variable to each entry', () => { - const lib = require('../config/webpack/build.webpack.config'); + const lib = mock.reRequire('../config/webpack/build.webpack.config'); const config = lib.getWebpackConfig({ runtime: runtimeUtils.getDefaultRuntime(), skyux: {} diff --git a/test/config-webpack-common.spec.js b/test/config-webpack-common.spec.js index b7e4960f..ab788a42 100644 --- a/test/config-webpack-common.spec.js +++ b/test/config-webpack-common.spec.js @@ -12,8 +12,8 @@ describe('config webpack common', () => { let existsSync = fs.existsSync; - spyOn(fs, 'existsSync').and.callFake(function (path) { - if (path.indexOf('app-extras.module') >= 0) { + spyOn(fs, 'existsSync').and.callFake(function (filePath) { + if (filePath.indexOf('app-extras.module') >= 0) { return spaVersionExists; } @@ -58,40 +58,6 @@ describe('config webpack common', () => { expect(config.entry.app[0]).toContain(process.cwd()); }); - it('should look in the specified import path when resolving SKY UX', () => { - const lib = mock.reRequire('../config/webpack/common.webpack.config'); - const importPath = './some-folder'; - const cssPath = path.join(importPath, '/scss/sky.scss'); - - let config = lib.getWebpackConfig({ - runtime: runtimeUtils.getDefaultRuntime(), - skyux: { - importPath: importPath, - mode: 'advanced' - } - }); - - let alias = config.resolve.alias; - - expect( - alias['@blackbaud/skyux/dist'] - ).toBe(path.join(process.cwd(), importPath)); - - config = lib.getWebpackConfig({ - runtime: runtimeUtils.getDefaultRuntime(), - skyux: { - mode: 'advanced', - cssPath: cssPath - } - }); - - alias = config.resolve.alias; - - expect( - alias['@skyux/theme/css/sky.css'] - ).toBe(path.join(process.cwd(), cssPath)); - }); - it('should default to the local app-extras module when not present in the SPA', () => { validateAppExtras(false); }); @@ -110,7 +76,7 @@ describe('config webpack common', () => { }); const lib = mock.reRequire('../config/webpack/common.webpack.config'); - const config = lib.getWebpackConfig({ + lib.getWebpackConfig({ runtime: runtimeUtils.getDefaultRuntime(), skyux: {} }, { diff --git a/test/fixtures/index-ejs-test.js b/test/fixtures/index-ejs-test.js new file mode 100644 index 00000000..875c5ee5 --- /dev/null +++ b/test/fixtures/index-ejs-test.js @@ -0,0 +1,3 @@ +module.exports = { + foo: 'bar' +}; diff --git a/test/index-ejs.spec.js b/test/index-ejs.spec.js index 8c0284cd..3b26fcf5 100644 --- a/test/index-ejs.spec.js +++ b/test/index-ejs.spec.js @@ -4,16 +4,29 @@ const mock = require('mock-require'); const webpack = require('webpack'); const HtmlWebpackPlugin = require('html-webpack-plugin'); -const skyPagesConfigUtil = require('../config/sky-pages/sky-pages.config.js'); describe('index.ejs template', () => { + beforeEach(() => { + mock('../lib/locale-assets-processor', { + prepareLocaleFiles() {} + }); + + mock('../cli/utils/ts-linter', { + lintSync: () => 0 + }); + }); + + afterEach(() => { + mock.stopAll(); + }); it('should support external css & js in the correct locations', (done) => { + const skyPagesConfigUtil = mock.reRequire('../config/sky-pages/sky-pages.config.js'); mock('../config/webpack/build.webpack.config', { getWebpackConfig: (skyPagesConfig) => ({ entry: { - test: ['test.js'] + test: ['./test/fixtures/index-ejs-test.js'] }, plugins: [ new HtmlWebpackPlugin({ @@ -64,11 +77,8 @@ describe('index.ejs template', () => { }) }); - mock('../cli/utils/ts-linter', { - lintSync: () => 0 - }); + const config = skyPagesConfigUtil.getSkyPagesConfig('build'); - let config = skyPagesConfigUtil.getSkyPagesConfig('build'); config.skyux = { app: { externals: { @@ -106,9 +116,10 @@ describe('index.ejs template', () => { } } }; + spyOn(process, 'exit').and.callFake(() => {}); - mock.reRequire('../cli/build')({}, config, webpack); + const build = mock.reRequire('../cli/build'); + build({}, config, webpack); }); - }); diff --git a/test/index.spec.js b/test/index.spec.js index e13797d1..8ae5f6c3 100644 --- a/test/index.spec.js +++ b/test/index.spec.js @@ -3,17 +3,25 @@ const mock = require('mock-require'); const logger = require('@blackbaud/skyux-logger'); -const config = require('../config/sky-pages/sky-pages.config'); -describe('@blackbaud/skyux-builder', () => { +describe('@skyux-sdk/builder', () => { + let config; + + beforeEach(() => { + config = mock.reRequire('../config/sky-pages/sky-pages.config'); + }); + + afterEach(() => { + mock.stopAll(); + }); it('should expose a runCommand method', () => { - const lib = require('../index'); + const lib = mock.reRequire('../index'); expect(typeof lib.runCommand).toEqual('function'); }); it('should handle known commands', () => { - const lib = require('../index'); + const lib = mock.reRequire('../index'); const cmds = { 'build': { cmd: 'build', @@ -62,7 +70,7 @@ describe('@blackbaud/skyux-builder', () => { }; Object.keys(cmds).forEach((key) => { - mock('../cli/' + cmds[key].lib, () => { + mock(`../cli/${cmds[key].lib}`, () => { cmds[key].called = true; }); lib.runCommand(cmds[key].cmd, {}); @@ -75,9 +83,9 @@ describe('@blackbaud/skyux-builder', () => { spyOn(config, 'getSkyPagesConfig'); const cmd = 'junk-command-that-does-not-exist'; - const lib = require('../index'); + const lib = mock.reRequire('../index'); - expect(lib.runCommand(cmd, {})).toBe(false); + expect(lib.runCommand(cmd, {})).toEqual(false); expect(config.getSkyPagesConfig).not.toHaveBeenCalled(); }); @@ -86,7 +94,9 @@ describe('@blackbaud/skyux-builder', () => { spyOn(config, 'getSkyPagesConfig'); const cmd = 'build'; - const lib = require('../index'); + mock(`../cli/${cmd}`, () => {}); + + const lib = mock.reRequire('../index'); expect(lib.runCommand(cmd, {})).toBe(true); expect(config.getSkyPagesConfig).toHaveBeenCalled(); @@ -104,7 +114,7 @@ describe('@blackbaud/skyux-builder', () => { expect(a.force).toEqual(argv.f); done(); }); - const lib = require('../index'); + const lib = mock.reRequire('../index'); lib.runCommand('test', argv); }); diff --git a/test/sky-pages-assets-generator.spec.js b/test/sky-pages-assets-generator.spec.js index 79f57156..74607e93 100644 --- a/test/sky-pages-assets-generator.spec.js +++ b/test/sky-pages-assets-generator.spec.js @@ -3,13 +3,15 @@ const mock = require('mock-require'); const glob = require('glob'); -const skyPagesConfigUtil = require('../config/sky-pages/sky-pages.config'); const localeAssetsProcessor = require('../lib/locale-assets-processor'); describe('SKY UX Builder assets generator', () => { let mockLocaleProcessor; + let skyPagesConfigUtil; beforeEach(() => { + skyPagesConfigUtil = mock.reRequire('../config/sky-pages/sky-pages.config'); + mockLocaleProcessor = { getDefaultLocaleFiles: localeAssetsProcessor.getDefaultLocaleFiles, isLocaleFile() { @@ -43,7 +45,7 @@ describe('SKY UX Builder assets generator', () => { const source = generator.getSource(); expect(source).toBe( -`export class ${generator.getClassName()} { + `export class ${generator.getClassName()} { public getUrl(filePath: string): string { const pathMap: {[key: string]: any} = { 'a/b/c/d.jpg': '~/assets/a/b/c/d.jpg', @@ -72,7 +74,7 @@ describe('SKY UX Builder assets generator', () => { // This test ensures that the file name (and lookup key) // is governed by the locale assets processor. expect(source).toBe( -`export class SkyAppAssetsImplService { + `export class SkyAppAssetsImplService { public getUrl(filePath: string): string { const pathMap: {[key: string]: any} = { 'locales/BASENAME': '~/assets/BASENAME', @@ -102,7 +104,7 @@ describe('SKY UX Builder assets generator', () => { // This test ensures that the file name (and lookup key) // is governed by the locale assets processor. expect(source).toBe( -`export class SkyAppAssetsImplService { + `export class SkyAppAssetsImplService { public getUrl(filePath: string): string { const pathMap: {[key: string]: any} = { 'locales/BASENAME': '~/assets/BASENAME' diff --git a/test/sky-pages-module-generator.spec.js b/test/sky-pages-module-generator.spec.js index b6ed7fff..4a2e41f9 100644 --- a/test/sky-pages-module-generator.spec.js +++ b/test/sky-pages-module-generator.spec.js @@ -37,6 +37,10 @@ describe('SKY UX Builder module generator', () => { } }; + mockLogger = { + warn() {} + }; + mockRouteGenerator = { getRoutes() { return { @@ -85,20 +89,6 @@ describe('SKY UX Builder module generator', () => { expect(source).toContain(expectedImport); }); - it('should export modules from the runtimeModuleExports', () => { - const generator = mock.reRequire(GENERATOR_PATH); - const expectedExport = 'SkyAppRuntimeModule'; - - const source = generator.getSource({ - runtime: runtimeUtils.getDefaultRuntime(), - skyux: runtimeUtils.getDefaultSkyux() - }); - - const moduleExports = getModuleList('exports', source); - - expect(moduleExports).toContain(expectedExport); - }); - it('should import modules from the runtimeModuleImports', () => { const generator = mock.reRequire(GENERATOR_PATH); const expectedImport = 'CommonModule'; @@ -162,45 +152,7 @@ describe('SKY UX Builder module generator', () => { ); }); - it('should allow the SKY UX path alias to be overridden', () => { - const generator = mock.reRequire(GENERATOR_PATH); - const source = generator.getSource({ - runtime: runtimeUtils.getDefaultRuntime({ - skyuxPathAlias: 'custom' - }), - skyux: runtimeUtils.getDefaultSkyux() - }); - - expect(source).toContain( - `import { - SkyModule -} from 'custom/core';` - ); - }); - - it('should import individual SKY UX modules from config', () => { - const generator = mock.reRequire(GENERATOR_PATH); - const source = generator.getSource({ - runtime: runtimeUtils.getDefaultRuntime(), - skyux: runtimeUtils.getDefaultSkyux({ - skyuxModules: [ - 'SkyAlertModule', - 'SkyErrorModule', - 'SkyModalModule' - ] - }) - }); - - expect(source).toContain( - `import { - SkyAlertModule, - SkyErrorModule, - SkyModalModule -} from '@blackbaud/skyux/dist/core';` - ); - }); - - it('should only import the SkyAuthHttpModule if the app is configured to use auth', () => { + it('should only provide the SkyAuthHttp service if the app is configured to use auth', () => { const generator = mock.reRequire(GENERATOR_PATH); const expectedImport = `{ SkyAuthHttp }`; const expectedProvider = `{ @@ -278,13 +230,12 @@ describe('SKY UX Builder module generator', () => { expect(moduleImports).toContain(expectedImport); - let sourceWithoutRouting = generator.getSource( - { - runtime: runtimeUtils.getDefaultRuntime({ - includeRouteModule: false - }), - skyux: runtimeUtils.getDefaultSkyux() - }); + const sourceWithoutRouting = generator.getSource({ + runtime: runtimeUtils.getDefaultRuntime({ + includeRouteModule: false + }), + skyux: runtimeUtils.getDefaultSkyux() + }); moduleImports = getModuleList('imports', sourceWithoutRouting); @@ -302,7 +253,8 @@ describe('SKY UX Builder module generator', () => { expect(source).toContain( `import { enableProdMode } from '@angular/core'; -enableProdMode();`); +enableProdMode();` + ); }); it('should put auth-client in mock mode if the command is e2e', () => { @@ -316,7 +268,8 @@ enableProdMode();`); expect(source).toContain( `import { BBAuth } from '@blackbaud/auth-client'; -BBAuth.mock = true;`); +BBAuth.mock = true;` + ); }); it('should add routes to skyPagesConfig.runtime', () => { @@ -429,7 +382,6 @@ require('style-loader!src/styles/custom.css'); const generator = mock.reRequire(GENERATOR_PATH); const spy = spyOn(mockLogger, 'warn').and.callThrough(); const expectedRequire = ''; - const config = { runtime: runtimeUtils.getDefaultRuntime(), skyux: runtimeUtils.getDefaultSkyux() diff --git a/tsconfig.json b/tsconfig.json index 387d1fcf..f21d6c16 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -6,6 +6,7 @@ "emitDecoratorMetadata": true, "experimentalDecorators": true, "sourceMap": true, + "importHelpers": true, "noEmitHelpers": true, "noEmitOnError": true, "noUnusedLocals": true, @@ -22,8 +23,8 @@ ], "baseUrl": ".", "paths": { - "@blackbaud/skyux-builder/*": [ - "./node_modules/@blackbaud/skyux-builder/*", + "@skyux-sdk/builder/*": [ + "./node_modules/@skyux-sdk/builder/*", "./*" ], ".skypageslocales/*": [ diff --git a/tslint.json b/tslint.json index 691e1c03..2d87d88e 100644 --- a/tslint.json +++ b/tslint.json @@ -66,7 +66,6 @@ "no-string-literal": false, "no-switch-case-fall-through": true, "no-unused-expression": true, - "no-unused-variable": true, "no-use-before-declare": true, "no-var-keyword": true, "radix": true, @@ -146,7 +145,7 @@ "no-forward-ref": true, "use-life-cycle-interface": true, "use-pipe-transform-interface": true, - "pipe-naming": [true, "camelCase", "sky"], + "pipe-prefix": "sky", "component-class-suffix": true, "directive-class-suffix": true } diff --git a/utils/cli-test.js b/utils/cli-test.js index bbcb38ce..a0429c4c 100644 --- a/utils/cli-test.js +++ b/utils/cli-test.js @@ -3,4 +3,3 @@ // Runs the equivalent of `skyux test`, but passes in the third argument as the command. require('../cli/test')(process.argv[2]); - diff --git a/utils/host-utils.js b/utils/host-utils.js index df860909..9ebc2d52 100644 --- a/utils/host-utils.js +++ b/utils/host-utils.js @@ -33,7 +33,7 @@ function resolve(url, localUrl, chunks, skyPagesConfig) { } const delimeter = url.indexOf('?') === -1 ? '?' : '&'; - const encoded = new Buffer(JSON.stringify(config)).toString('base64'); + const encoded = Buffer.from(JSON.stringify(config)).toString('base64'); const base = skyPagesConfigUtil.getAppBase(skyPagesConfig); const resolved = `${host}${base}${url}${delimeter}local=true&_cfg=${encoded}`; @@ -52,12 +52,15 @@ function getScripts(chunks) { return chunks.metadata; } - sorter.dependency(chunks).forEach((chunk) => { + sorter.dependency(chunks, undefined, {}).forEach((chunk) => { scripts.push({ name: chunk.files[0] }); }); + // Webpack reversed the order of these scripts + scripts.reverse(); + return scripts; } diff --git a/utils/runtime-test-utils.js b/utils/runtime-test-utils.js index fd405be0..48ab4141 100644 --- a/utils/runtime-test-utils.js +++ b/utils/runtime-test-utils.js @@ -28,7 +28,6 @@ module.exports = { srcPath: 'src/app/', spaPathAlias: 'sky-pages-spa', skyPagesOutAlias: 'sky-pages-internal', - skyuxPathAlias: '@blackbaud/skyux/dist', useTemplateUrl: false }, runtime); }, @@ -42,9 +41,6 @@ module.exports = { params: [ 'envid', 'svcid' - ], - skyuxModules: [ - 'SkyModule' ] }, skyux); } diff --git a/utils/spec-bundle.js b/utils/spec-bundle.js index aa64cc70..a1cc79b5 100644 --- a/utils/spec-bundle.js +++ b/utils/spec-bundle.js @@ -3,80 +3,28 @@ /*global skyPagesConfig*/ 'use strict'; -/** - * @author: @AngularClass - */ - -/* - * When testing with webpack and ES6, we have to do some extra - * things get testing to work right. Because we are gonna write test - * in ES6 to, we have to compile those as well. That's handled in - * karma.conf.js with the karma-webpack plugin. This is the entry - * file for webpack test. Just like webpack will create a bundle.js - * file for our client, when we run test, it well compile and bundle them - * all here! Crazy huh. So we need to do some setup - */ -Error.stackTraceLimit = Infinity; - -require('core-js'); - -// Typescript emit helpers polyfill -require('ts-helpers'); - require('zone.js/dist/zone'); -require('zone.js/dist/long-stack-trace-zone'); -require('zone.js/dist/async-test'); -require('zone.js/dist/fake-async-test'); -require('zone.js/dist/sync-test'); -require('zone.js/dist/proxy'); -require('zone.js/dist/jasmine-patch'); +require('zone.js/dist/zone-testing'); require('reflect-metadata'); -// RxJS -require('rxjs/Rx'); - -var testing = require('@angular/core/testing'); -var browser = require('@angular/platform-browser-dynamic/testing'); +const testing = require('@angular/core/testing'); +const browser = require('@angular/platform-browser-dynamic/testing'); +// First, initialize the Angular testing environment. testing.getTestBed().initTestEnvironment( browser.BrowserDynamicTestingModule, browser.platformBrowserDynamicTesting() ); -Object.assign(global, testing); - -// var SkyPagesModule = require('../src/app/sky-pages.module'); - -// // console.log(SkyPagesModule); - -// testing.getTestBed().configureTestingModule({ -// imports: [ -// SkyPagesModule -// ] -// }); - -/* - * Ok, this is kinda crazy. We can use the the context method on - * require that webpack created in order to tell webpack - * what files we actually want to require or import. - * Below, context will be an function/object with file names as keys. - * using that regex we are saying look in ./src/app and ./test then find - * any file that ends with spec.js and get its path. By passing in true - * we say do this recursively - */ -var testContext = skyPagesConfig.runtime.command === 'pact' ? -require.context(ROOT_DIR, true, /\.pact-spec\.ts/) : -require.context(ROOT_DIR, true, /\.spec\.ts/); +// Then we find all the tests. +const testContext = skyPagesConfig.runtime.command === 'pact' ? + require.context(ROOT_DIR, true, /\.pact-spec\.ts/) : + require.context(ROOT_DIR, true, /\.spec\.ts/); -/* - * get all the files, for each file, call the context function - * that will require the file and load it up here. Context will - * loop and require those spec files here - */ +// And load the modules. function requireAll(requireContext) { return requireContext.keys().map(requireContext); } -// requires and returns all modules that match requireAll(testContext);