mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-20 04:14:21 +08:00
chore(gulp): updates to build process to use app-scripts for watch/build
updates to build process to use app-scripts for watch/build
This commit is contained in:
@ -28,20 +28,18 @@ Run `gulp build` or `gulp watch` to watch for changes.
|
|||||||
|
|
||||||
#### Development
|
#### Development
|
||||||
|
|
||||||
1. Run `gulp e2e` or `gulp e2e.watch` to watch for changes.
|
1. Run `gulp e2e.watch --folder nav/basic` to watch for changes, where `nav` is the component, and `basic` is the test name
|
||||||
2. Navigate to `http://localhost:8000/dist/e2e`
|
2. The browser will launch just like when using `ionic serve`. Make changes to an app in the `src` directory and the app will rebuild.
|
||||||
|
|
||||||
#### Validation
|
#### Validation
|
||||||
|
|
||||||
The following commands take longer to run because they use AoT compilation. They should really only be used to validate that our components work with AoT, and fix them if not.
|
The following commands take longer to run because they use AoT compilation. They should really only be used to validate that our components work with AoT, and fix them if not.
|
||||||
|
|
||||||
1. Run `gulp e2e.prod` to bundle all e2e tests. Folder is optional, see the flags section below.
|
1. Run `gulp e2e.prod` to bundle all e2e tests.
|
||||||
2. Run `gulp e2e.watchProd` with a folder passed to watch a test. Folder is required, see the flags section below.
|
|
||||||
3. Navigate to `http://localhost:8000/dist/e2e`
|
|
||||||
|
|
||||||
##### Flags
|
##### Flags
|
||||||
|
|
||||||
- `--f | -folder` will run the command with a test folder. For example, `gulp e2e.watchProd --f=select/single-value` will watch the test in `src/components/select/test/single-value`.
|
- `--f | -folder` will run the command with a test folder.
|
||||||
- `--debug` will run the `ionic-app-scripts` command with debug output printed.
|
- `--debug` will run the `ionic-app-scripts` command with debug output printed.
|
||||||
|
|
||||||
|
|
||||||
@ -98,8 +96,6 @@ To remove the linked version of `ionic-angular` do `npm rm ionic-angular`, and t
|
|||||||
|
|
||||||
- `gulp snapshot` will run the `gulp e2e.prod` task with AoT compilation.
|
- `gulp snapshot` will run the `gulp e2e.prod` task with AoT compilation.
|
||||||
- `gulp snapshot.skipBuild` will skip the `gulp e2e.prod` task with AoT compilation.
|
- `gulp snapshot.skipBuild` will skip the `gulp e2e.prod` task with AoT compilation.
|
||||||
- `gulp snapshot.dev` will run a development build using the `gulp e2e` task.
|
|
||||||
- `gulp snapshot.quick` will skip the build and run snapshot without uploading to the server.
|
|
||||||
|
|
||||||
#### Flags
|
#### Flags
|
||||||
|
|
||||||
|
@ -1,7 +1,25 @@
|
|||||||
// we don't want to run copy for the demos, so just override the config for now
|
// we don't want to run copy for the demos, so just override the config for now
|
||||||
|
var path = require('path');
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
copyAssets: { },
|
copyAssets: {
|
||||||
copyIndexContent: { },
|
src: [path.join(path.dirname(process.env.IONIC_APP_ENTRY_POINT), '..', 'assets', '**', '*')],
|
||||||
copyFonts: { },
|
dest: '{{WWW}}/assets'
|
||||||
copyPolyfills: { }
|
},
|
||||||
|
copyIndexContent: {
|
||||||
|
src: [path.join(process.cwd(), 'scripts', 'demos', 'index.html')],
|
||||||
|
dest: '{{WWW}}'
|
||||||
|
},
|
||||||
|
copyFonts: {
|
||||||
|
src: [`${process.cwd()}/node_modules/ionicons/dist/fonts/**/*`, `${process.cwd()}/src/fonts/**/*`],
|
||||||
|
dest: '{{WWW}}/assets/fonts'
|
||||||
|
},
|
||||||
|
copyPolyfills: {
|
||||||
|
src: [path.join(process.cwd(), 'dist', 'demos', 'polyfills', 'polyfills.js')],
|
||||||
|
dest: '{{BUILD}}'
|
||||||
|
},
|
||||||
|
sharedCss: {
|
||||||
|
src: [path.join(process.cwd(), 'scripts', 'demos', 'demos.shared.css')],
|
||||||
|
dest: `{{BUILD}}`
|
||||||
|
}
|
||||||
}
|
}
|
@ -1,57 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html dir="ltr" lang="en">
|
|
||||||
|
|
||||||
<head>
|
|
||||||
<title>Ionic E2E</title>
|
|
||||||
<meta charset="UTF-8" />
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no"
|
|
||||||
/>
|
|
||||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
|
||||||
|
|
||||||
<link id="ionicLink" href="../css/ionic.css" rel="stylesheet">
|
|
||||||
<link href="../css/demos.shared.css" rel="stylesheet">
|
|
||||||
|
|
||||||
<script src="/node_modules/systemjs/dist/system.src.js"></script>
|
|
||||||
<script>
|
|
||||||
System.config({
|
|
||||||
map: {
|
|
||||||
'@angular/core': '/node_modules/@angular/core/bundles/core.umd.js',
|
|
||||||
'@angular/compiler': '/node_modules/@angular/compiler/bundles/compiler.umd.js',
|
|
||||||
'@angular/common': '/node_modules/@angular/common/bundles/common.umd.js',
|
|
||||||
'@angular/forms': '/node_modules/@angular/forms/bundles/forms.umd.js',
|
|
||||||
'@angular/http': '/node_modules/@angular/http/bundles/http.umd.js',
|
|
||||||
'@angular/platform-browser': '/node_modules/@angular/platform-browser/bundles/platform-browser.umd.js',
|
|
||||||
'@angular/platform-browser-dynamic': '/node_modules/@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js',
|
|
||||||
'ionic-angular': location.protocol + '//' + location.host + '/dist/ionic-angular',
|
|
||||||
'rxjs': '/node_modules/rxjs'
|
|
||||||
},
|
|
||||||
packages: {
|
|
||||||
'ionic-angular': {
|
|
||||||
main: 'index',
|
|
||||||
defaultExtension: false
|
|
||||||
},
|
|
||||||
'rxjs': {
|
|
||||||
defaultExtension: 'js'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
<script src="../polyfills/polyfills.js"></script>
|
|
||||||
<script src="../../bundles/ionic.system.js"></script>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
|
|
||||||
<ion-app></ion-app>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
System.import('@angular/platform-browser-dynamic').then(function(platformBrowserDynamic) {
|
|
||||||
System.import('app.module.js').then(function(appModule) {
|
|
||||||
platformBrowserDynamic.platformBrowserDynamic().bootstrapModule(appModule.AppModule);
|
|
||||||
}, console.error.bind(console));
|
|
||||||
}, console.error.bind(console));
|
|
||||||
</script>
|
|
||||||
|
|
||||||
</body>
|
|
||||||
|
|
||||||
</html>
|
|
@ -7,13 +7,13 @@
|
|||||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||||
|
|
||||||
<link id="ionicLink" href="./build/main.css" rel="stylesheet">
|
<link id="ionicLink" href="./build/main.css" rel="stylesheet">
|
||||||
<link href="../css/demos.shared.css" rel="stylesheet">
|
<link href="./build/e2e.shared.css" rel="stylesheet">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|
||||||
<ion-app></ion-app>
|
<ion-app></ion-app>
|
||||||
|
|
||||||
<script src="../polyfills/polyfills.js"></script>
|
<script src="./build/polyfills.js"></script>
|
||||||
<script src="./build/main.js"></script>
|
<script src="./build/main.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
@ -1,5 +0,0 @@
|
|||||||
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
|
|
||||||
|
|
||||||
import { AppModule } from './app.module';
|
|
||||||
|
|
||||||
platformBrowserDynamic().bootstrapModule(AppModule);
|
|
15
scripts/demos/watch.config.js
Normal file
15
scripts/demos/watch.config.js
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
var path = require('path');
|
||||||
|
|
||||||
|
var watch = require('../../node_modules/@ionic/app-scripts/dist/watch');
|
||||||
|
|
||||||
|
var entryPointDirectory = path.dirname(process.env.IONIC_APP_ENTRY_POINT)
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
demoSrc: {
|
||||||
|
paths: [path.join(entryPointDirectory, '..', '**', '*.(ts|html|s(c|a)ss)')],
|
||||||
|
options: { ignored: [path.join(entryPointDirectory, '..', '**', '*.spec.ts'),
|
||||||
|
path.join(entryPointDirectory, '..', '**', '*.e2e.ts'),
|
||||||
|
'**/*.DS_Store'] },
|
||||||
|
callback: watch.buildUpdate
|
||||||
|
}
|
||||||
|
}
|
@ -1,7 +1,25 @@
|
|||||||
// we don't want to run copy for the demos, so just override the config for now
|
// we don't want to run copy for the demos, so just override the config for now
|
||||||
|
var path = require('path');
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
copyAssets: { },
|
copyAssets: {
|
||||||
copyIndexContent: { },
|
src: [path.join(path.dirname(process.env.IONIC_APP_ENTRY_POINT), '..', 'assets', '**', '*')],
|
||||||
copyFonts: { },
|
dest: '{{WWW}}/assets'
|
||||||
copyPolyfills: { }
|
},
|
||||||
|
copyIndexContent: {
|
||||||
|
src: [path.join(process.cwd(), 'scripts', 'e2e', 'index.html')],
|
||||||
|
dest: '{{WWW}}'
|
||||||
|
},
|
||||||
|
copyFonts: {
|
||||||
|
src: [`${process.cwd()}/node_modules/ionicons/dist/fonts/**/*`, `${process.cwd()}/src/fonts/**/*`],
|
||||||
|
dest: '{{WWW}}/assets/fonts'
|
||||||
|
},
|
||||||
|
copyPolyfills: {
|
||||||
|
src: [path.join(process.cwd(), 'dist', 'e2e', 'polyfills', 'polyfills.ng.js')],
|
||||||
|
dest: '{{BUILD}}'
|
||||||
|
},
|
||||||
|
sharedCss: {
|
||||||
|
src: [path.join(process.cwd(), 'scripts', 'e2e', 'e2e.shared.css')],
|
||||||
|
dest: `{{BUILD}}`
|
||||||
|
}
|
||||||
}
|
}
|
@ -1,83 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html dir="ltr" lang="en">
|
|
||||||
|
|
||||||
<head>
|
|
||||||
<title>Ionic E2E</title>
|
|
||||||
<meta charset="UTF-8" />
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no"
|
|
||||||
/>
|
|
||||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
|
||||||
|
|
||||||
<link id="ionicLink" href="../../css/ionic.css" rel="stylesheet">
|
|
||||||
<link href="../../css/e2e.shared.css" rel="stylesheet">
|
|
||||||
|
|
||||||
<script>
|
|
||||||
var port;
|
|
||||||
if (location.href.indexOf('snapshot=true') > -1) {
|
|
||||||
port = 8876;
|
|
||||||
document.documentElement.classList.add('snapshot');
|
|
||||||
} else {
|
|
||||||
port = 8000;
|
|
||||||
document.documentElement.classList.remove('snapshot');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (location.href.indexOf('cordova=true') > -1) {
|
|
||||||
window.cordova = {};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (location.href.indexOf('rtl=true') > -1) {
|
|
||||||
document.dir = 'rtl';
|
|
||||||
} else {
|
|
||||||
document.dir = 'ltr';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (location.href.indexOf('theme=dark') > -1) {
|
|
||||||
var link = document.getElementById('ionicLink');
|
|
||||||
link.setAttribute('href', link.getAttribute('href').replace('.css', '.dark.css'));
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<script src="/node_modules/systemjs/dist/system.src.js"></script>
|
|
||||||
<script>
|
|
||||||
System.config({
|
|
||||||
map: {
|
|
||||||
'@angular/core': '/node_modules/@angular/core/bundles/core.umd.js',
|
|
||||||
'@angular/compiler': '/node_modules/@angular/compiler/bundles/compiler.umd.js',
|
|
||||||
'@angular/common': '/node_modules/@angular/common/bundles/common.umd.js',
|
|
||||||
'@angular/forms': '/node_modules/@angular/forms/bundles/forms.umd.js',
|
|
||||||
'@angular/http': '/node_modules/@angular/http/bundles/http.umd.js',
|
|
||||||
'@angular/platform-browser': '/node_modules/@angular/platform-browser/bundles/platform-browser.umd.js',
|
|
||||||
'@angular/platform-browser-dynamic': '/node_modules/@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js',
|
|
||||||
'ionic-angular': location.protocol + '//' + location.host + '/ionic-angular',
|
|
||||||
'rxjs': '/node_modules/rxjs'
|
|
||||||
},
|
|
||||||
packages: {
|
|
||||||
'ionic-angular': {
|
|
||||||
main: 'index',
|
|
||||||
defaultExtension: false
|
|
||||||
},
|
|
||||||
'rxjs': {
|
|
||||||
defaultExtension: 'js'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
<script src="../../polyfills/polyfills.ng.js"></script>
|
|
||||||
<script src="../../../bundles/ionic.system.js"></script>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
|
|
||||||
<ion-app></ion-app>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
System.import('@angular/platform-browser-dynamic').then(function(platformBrowserDynamic) {
|
|
||||||
System.import('app.module.js').then(function(appModule) {
|
|
||||||
platformBrowserDynamic.platformBrowserDynamic().bootstrapModule(appModule.AppModule);
|
|
||||||
}, console.error.bind(console));
|
|
||||||
}, console.error.bind(console));
|
|
||||||
</script>
|
|
||||||
|
|
||||||
</body>
|
|
||||||
|
|
||||||
</html>
|
|
@ -1,4 +1,4 @@
|
|||||||
describe('<%= relativePath %>: <%= platform %>', function() {
|
describe('<%= relativePathBackwardsCompatibility %>: <%= platform %>', function() {
|
||||||
|
|
||||||
it('should init', function() {
|
it('should init', function() {
|
||||||
browser.get('http://localhost:<%= buildConfig.protractorPort %>/dist/e2e/<%= relativePath %>/index.html?ionicplatform=<%= platform %>&ionicOverlayCreatedDiff=0&ionicanimate=false&snapshot=true');
|
browser.get('http://localhost:<%= buildConfig.protractorPort %>/dist/e2e/<%= relativePath %>/index.html?ionicplatform=<%= platform %>&ionicOverlayCreatedDiff=0&ionicanimate=false&snapshot=true');
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||||
|
|
||||||
<link id="ionicLink" href="./build/main.css" rel="stylesheet">
|
<link id="ionicLink" href="./build/main.css" rel="stylesheet">
|
||||||
<link href="../../../../css/e2e.shared.css" rel="stylesheet">
|
<link href="build/e2e.shared.css" rel="stylesheet">
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
if (location.href.indexOf('snapshot=true') > -1) {
|
if (location.href.indexOf('snapshot=true') > -1) {
|
||||||
@ -43,7 +43,7 @@
|
|||||||
document.body.classList.remove('rtl');
|
document.body.classList.remove('rtl');
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<script src="../../../../polyfills/polyfills.js"></script>
|
<script src="./build/polyfills.ng.js"></script>
|
||||||
<script src="./build/main.js"></script>
|
<script src="./build/main.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
@ -1,5 +0,0 @@
|
|||||||
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
|
|
||||||
|
|
||||||
import { AppModule } from './app.module';
|
|
||||||
|
|
||||||
platformBrowserDynamic().bootstrapModule(AppModule);
|
|
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
// Font path is used to include ionicons,
|
// Font path is used to include ionicons,
|
||||||
// roboto, and noto sans fonts
|
// roboto, and noto sans fonts
|
||||||
$font-path: "../../../../../fonts";
|
$font-path: "../assets/fonts";
|
||||||
|
|
||||||
@import "ionic.globals";
|
@import "ionic.globals";
|
||||||
|
|
||||||
|
@ -31,7 +31,7 @@ export const DIST_BUILD_ROOT = join(DIST_ROOT, PACKAGE_NAME);
|
|||||||
export const DIST_BUNDLE_ROOT = join(DIST_BUILD_ROOT, BUNDLES);
|
export const DIST_BUNDLE_ROOT = join(DIST_BUILD_ROOT, BUNDLES);
|
||||||
export const DIST_BUILD_UMD_ROOT = join(DIST_BUILD_ROOT, UMD_MODULE);
|
export const DIST_BUILD_UMD_ROOT = join(DIST_BUILD_ROOT, UMD_MODULE);
|
||||||
export const DIST_BUILD_UMD_BUNDLE_ENTRYPOINT = join(DIST_BUILD_ROOT, INDEX_JS);
|
export const DIST_BUILD_UMD_BUNDLE_ENTRYPOINT = join(DIST_BUILD_ROOT, INDEX_JS);
|
||||||
export const DIST_BUILD_ES2015_ROOT = join(DIST_BUILD_ROOT, ES_2015);
|
export const DIST_BUILD_ESM_ROOT = join(DIST_BUILD_ROOT, 'esm');
|
||||||
export const DIST_VENDOR_ROOT = join(DIST_ROOT, VENDOR_NAME);
|
export const DIST_VENDOR_ROOT = join(DIST_ROOT, VENDOR_NAME);
|
||||||
export const NODE_MODULES_ROOT = join(PROJECT_ROOT, NODE_MODULES);
|
export const NODE_MODULES_ROOT = join(PROJECT_ROOT, NODE_MODULES);
|
||||||
export const SCRIPTS_ROOT = join(PROJECT_ROOT, SCRIPTS_NAME);
|
export const SCRIPTS_ROOT = join(PROJECT_ROOT, SCRIPTS_NAME);
|
||||||
|
1
scripts/gulp/declarations.d.ts
vendored
1
scripts/gulp/declarations.d.ts
vendored
@ -15,6 +15,7 @@ declare module 'gulp-tslint';
|
|||||||
declare module 'gulp-typescript';
|
declare module 'gulp-typescript';
|
||||||
declare module 'html-entities';
|
declare module 'html-entities';
|
||||||
declare module 'inquirer';
|
declare module 'inquirer';
|
||||||
|
declare module 'p-all';
|
||||||
declare module 'path';
|
declare module 'path';
|
||||||
declare module 'rollup';
|
declare module 'rollup';
|
||||||
declare module 'rollup-plugin-commonjs';
|
declare module 'rollup-plugin-commonjs';
|
||||||
|
@ -5,7 +5,6 @@ import './tasks/demos';
|
|||||||
import './tasks/demos.dev';
|
import './tasks/demos.dev';
|
||||||
import './tasks/demos.prod';
|
import './tasks/demos.prod';
|
||||||
import './tasks/docs';
|
import './tasks/docs';
|
||||||
import './tasks/e2e';
|
|
||||||
import './tasks/e2e.dev';
|
import './tasks/e2e.dev';
|
||||||
import './tasks/e2e.prod';
|
import './tasks/e2e.prod';
|
||||||
import './tasks/lint';
|
import './tasks/lint';
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { task } from 'gulp';
|
import { task } from 'gulp';
|
||||||
import { DIST_BUILD_ROOT, DIST_BUILD_ES2015_ROOT, DIST_BUILD_UMD_ROOT, ES5, ES_2015, PROJECT_ROOT, UMD_MODULE } from '../constants';
|
import { DIST_BUILD_ROOT, DIST_BUILD_ESM_ROOT, DIST_BUILD_UMD_ROOT, ES5, ES_2015, PROJECT_ROOT, UMD_MODULE } from '../constants';
|
||||||
import { copySourceToDest, createTempTsConfig, deleteFiles, runNgc } from '../util';
|
import { copySourceToDest, createTempTsConfig, deleteFiles, runNgc, runTsc } from '../util';
|
||||||
|
|
||||||
|
|
||||||
export function buildIonicAngularUmd(excludeSpec: boolean, stripDebug: boolean, done: Function) {
|
export function buildIonicAngularUmd(excludeSpec: boolean, stripDebug: boolean, done: Function) {
|
||||||
@ -23,11 +23,51 @@ export function buildIonicAngularUmd(excludeSpec: boolean, stripDebug: boolean,
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function buildIonicAngularUmdTsc(excludeSpec: boolean, stripDebug: boolean, done: Function) {
|
||||||
|
const stream = copySourceToDest(DIST_BUILD_UMD_ROOT, excludeSpec, true, stripDebug);
|
||||||
|
stream.on('end', () => {
|
||||||
|
// the source files are copied, copy over a tsconfig from
|
||||||
|
createTempTsConfig(['./**/*.ts'], ES5, UMD_MODULE, `${PROJECT_ROOT}/tsconfig.json`, `${DIST_BUILD_UMD_ROOT}/tsconfig.json`);
|
||||||
|
runTsc(`${DIST_BUILD_UMD_ROOT}/tsconfig.json`, (err) => {
|
||||||
|
if (err) {
|
||||||
|
done(err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// clean up any .ts files that remain as well as ngc metadata
|
||||||
|
deleteFiles([`${DIST_BUILD_UMD_ROOT}/**/*.ts`,
|
||||||
|
`${DIST_BUILD_UMD_ROOT}/node_modules`,
|
||||||
|
`${DIST_BUILD_UMD_ROOT}/tsconfig.json`,
|
||||||
|
`!${DIST_BUILD_UMD_ROOT}/**/*.d.ts`], done);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
export function buildIonicAngularEsm(stripDebug: boolean, done: Function) {
|
export function buildIonicAngularEsm(stripDebug: boolean, done: Function) {
|
||||||
|
const stream = copySourceToDest(DIST_BUILD_ESM_ROOT, true, true, stripDebug);
|
||||||
|
stream.on('end', () => {
|
||||||
|
// the source files are copied, copy over a tsconfig from
|
||||||
|
createTempTsConfig(['./**/*.ts'], ES_2015, ES_2015, `${PROJECT_ROOT}/tsconfig.json`, `${DIST_BUILD_ESM_ROOT}/tsconfig.json`);
|
||||||
|
runNgc(`${DIST_BUILD_ESM_ROOT}/tsconfig.json`, (err) => {
|
||||||
|
if (err) {
|
||||||
|
done(err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// clean up any .ts files that remain as well as ngc metadata
|
||||||
|
deleteFiles([`${DIST_BUILD_ESM_ROOT}/**/*.ts`,
|
||||||
|
`${DIST_BUILD_ESM_ROOT}/node_modules`,
|
||||||
|
`${DIST_BUILD_ESM_ROOT}/tsconfig.json`,
|
||||||
|
`!${DIST_BUILD_ESM_ROOT}/**/*.d.ts`], done);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function buildIonicPureEs6(stripDebug: boolean, done: Function) {
|
||||||
const stream = copySourceToDest(DIST_BUILD_ROOT, true, true, stripDebug);
|
const stream = copySourceToDest(DIST_BUILD_ROOT, true, true, stripDebug);
|
||||||
stream.on('end', () => {
|
stream.on('end', () => {
|
||||||
// the source files are copied, copy over a tsconfig from
|
// the source files are copied, copy over a tsconfig from
|
||||||
createTempTsConfig(['./**/*.ts'], ES5, ES_2015, `${PROJECT_ROOT}/tsconfig.json`, `${DIST_BUILD_ROOT}/tsconfig.json`);
|
createTempTsConfig(['./**/*.ts'], ES_2015, ES_2015, `${PROJECT_ROOT}/tsconfig.json`, `${DIST_BUILD_ROOT}/tsconfig.json`);
|
||||||
runNgc(`${DIST_BUILD_ROOT}/tsconfig.json`, (err) => {
|
runNgc(`${DIST_BUILD_ROOT}/tsconfig.json`, (err) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
done(err);
|
done(err);
|
||||||
@ -42,28 +82,9 @@ export function buildIonicAngularEsm(stripDebug: boolean, done: Function) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function buildIonicPureEs6(stripDebug: boolean, done: Function) {
|
|
||||||
const stream = copySourceToDest(DIST_BUILD_ES2015_ROOT, true, true, stripDebug);
|
|
||||||
stream.on('end', () => {
|
|
||||||
// the source files are copied, copy over a tsconfig from
|
|
||||||
createTempTsConfig(['./**/*.ts'], ES_2015, ES_2015, `${PROJECT_ROOT}/tsconfig.json`, `${DIST_BUILD_ES2015_ROOT}/tsconfig.json`);
|
|
||||||
runNgc(`${DIST_BUILD_ES2015_ROOT}/tsconfig.json`, (err) => {
|
|
||||||
if (err) {
|
|
||||||
done(err);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// clean up any .ts files that remain as well as ngc metadata
|
|
||||||
deleteFiles([`${DIST_BUILD_ES2015_ROOT}/**/*.ts`,
|
|
||||||
`${DIST_BUILD_ES2015_ROOT}/node_modules`,
|
|
||||||
`${DIST_BUILD_ES2015_ROOT}/tsconfig.json`,
|
|
||||||
`!${DIST_BUILD_ES2015_ROOT}/**/*.d.ts`], done);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/* this task builds out the necessary stuff for karma */
|
/* this task builds out the necessary stuff for karma */
|
||||||
task('compile.karma', (done: Function) => {
|
task('compile.karma', (done: Function) => {
|
||||||
buildIonicAngularUmd(false, false, done);
|
buildIonicAngularUmdTsc(false, false, done);
|
||||||
});
|
});
|
||||||
|
|
||||||
/* this task builds out the ionic-angular (commonjs and esm) directories for release */
|
/* this task builds out the ionic-angular (commonjs and esm) directories for release */
|
||||||
|
@ -1,183 +1,44 @@
|
|||||||
import { readFileSync } from 'fs';
|
import { join } from 'path';
|
||||||
import { dirname, join } from 'path';
|
|
||||||
|
|
||||||
import { dest, src, start, task } from 'gulp';
|
import { task } from 'gulp';
|
||||||
import * as babel from 'gulp-babel';
|
|
||||||
import * as cache from 'gulp-cached';
|
|
||||||
import * as concat from 'gulp-concat';
|
|
||||||
import * as connect from 'gulp-connect';
|
|
||||||
import * as gulpif from 'gulp-if';
|
|
||||||
import * as remember from 'gulp-remember';
|
|
||||||
import * as tsc from 'gulp-typescript';
|
|
||||||
import * as watch from 'gulp-watch';
|
|
||||||
import { template } from 'lodash';
|
|
||||||
import * as merge from 'merge2';
|
|
||||||
import * as runSequence from 'run-sequence';
|
|
||||||
import { obj } from 'through2';
|
|
||||||
import * as VinylFile from 'vinyl';
|
|
||||||
|
|
||||||
import { DEMOS_NAME, DIST_DEMOS_ROOT, DIST_NAME, ES5, ES_2015, SCRIPTS_ROOT } from '../constants';
|
import { DEMOS_ROOT, DIST_DEMOS_ROOT, ES_2015, PROJECT_ROOT } from '../constants';
|
||||||
|
import { createTempTsConfig, getFolderInfo, runAppScriptsServe } from '../util';
|
||||||
|
|
||||||
const buildConfig = require('../../build/config');
|
task('demos.watch', ['demos.prepare'], (done: Function) => {
|
||||||
|
const folderInfo = getFolderInfo();
|
||||||
/**
|
if (!folderInfo || !folderInfo.componentName ) {
|
||||||
* Builds Ionic demos tests to dist/demos and creates the necessary files for tests
|
done(new Error(`Usage: gulp e2e.watch --folder modal`));
|
||||||
* to run.
|
|
||||||
*/
|
|
||||||
task('demos', demosBuild);
|
|
||||||
|
|
||||||
function demosBuild(done: (err: any) => void) {
|
|
||||||
runSequence(
|
|
||||||
'demos.clean',
|
|
||||||
'demos.build',
|
|
||||||
'demos.polyfill',
|
|
||||||
'demos.copyExternalDependencies',
|
|
||||||
'demos.sass',
|
|
||||||
'demos.fonts',
|
|
||||||
'demos.bundle',
|
|
||||||
done);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Builds Ionic demos tests to dist/demos.
|
|
||||||
*/
|
|
||||||
task('demos.build', function () {
|
|
||||||
var indexTemplate = template(
|
|
||||||
readFileSync(`${SCRIPTS_ROOT}/${DEMOS_NAME}/demos.template.dev.html`).toString()
|
|
||||||
)({
|
|
||||||
buildConfig: buildConfig
|
|
||||||
});
|
|
||||||
|
|
||||||
// Get each test folder with src
|
|
||||||
var tsResult = src([
|
|
||||||
'demos/src/*/**/*.ts'
|
|
||||||
])
|
|
||||||
.pipe(cache('demos.ts'))
|
|
||||||
.pipe(tsc(getTscOptions(), undefined, tscReporter))
|
|
||||||
.on('error', function (error) {
|
|
||||||
console.log(error.message);
|
|
||||||
})
|
|
||||||
.pipe(gulpif(/app.module.js$/, createIndexHTML()));
|
|
||||||
|
|
||||||
var testFiles = src([
|
|
||||||
'demos/src/*/**/*',
|
|
||||||
'!demos/src/*/**/*.ts'
|
|
||||||
])
|
|
||||||
.pipe(cache('demos.files'));
|
|
||||||
|
|
||||||
return merge([
|
|
||||||
tsResult,
|
|
||||||
testFiles
|
|
||||||
])
|
|
||||||
.pipe(dest(DIST_DEMOS_ROOT))
|
|
||||||
.pipe(connect.reload());
|
|
||||||
|
|
||||||
function createIndexHTML() {
|
|
||||||
return obj(function (file, enc, next) {
|
|
||||||
this.push(new VinylFile({
|
|
||||||
base: file.base,
|
|
||||||
contents: new Buffer(indexTemplate),
|
|
||||||
path: join(dirname(file.path), 'index.html'),
|
|
||||||
}));
|
|
||||||
next(null, file);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
serveDemo(folderInfo.componentName).then(() => {
|
||||||
* Creates SystemJS bundle from Ionic source files.
|
done();
|
||||||
*/
|
}).catch((err: Error) => {
|
||||||
task('demos.bundle', function () {
|
done(err);
|
||||||
return tsCompile(getTscOptions('es6'), 'system')
|
|
||||||
.pipe(babel(babelOptions))
|
|
||||||
.pipe(remember('system'))
|
|
||||||
.pipe(concat('ionic.system.js'))
|
|
||||||
.pipe(dest(`${DIST_NAME}/bundles`))
|
|
||||||
.pipe(connect.reload());
|
|
||||||
});
|
|
||||||
|
|
||||||
function tsCompile(options, cacheName) {
|
|
||||||
return src([
|
|
||||||
'typings/main.d.ts',
|
|
||||||
'src/**/*.ts',
|
|
||||||
'!src/**/*.d.ts',
|
|
||||||
'!src/components/*/test/**/*',
|
|
||||||
'!src/util/test/*',
|
|
||||||
'!src/config/test/*',
|
|
||||||
'!src/platform/test/*',
|
|
||||||
'!src/**/*.spec.ts'
|
|
||||||
])
|
|
||||||
.pipe(cache(cacheName, { optimizeMemory: true }))
|
|
||||||
.pipe(tsc(options, undefined, tscReporter));
|
|
||||||
}
|
|
||||||
|
|
||||||
function getTscOptions(name?: string) {
|
|
||||||
var opts = {
|
|
||||||
emitDecoratorMetadata: true,
|
|
||||||
experimentalDecorators: true,
|
|
||||||
target: ES5,
|
|
||||||
module: 'commonjs',
|
|
||||||
isolatedModules: true,
|
|
||||||
typescript: require('typescript'),
|
|
||||||
declaration: false
|
|
||||||
};
|
|
||||||
|
|
||||||
if (name === 'typecheck') {
|
|
||||||
opts.declaration = true;
|
|
||||||
delete opts.isolatedModules;
|
|
||||||
} else if (name === 'es6') {
|
|
||||||
opts.target = 'es6';
|
|
||||||
delete opts.module;
|
|
||||||
}
|
|
||||||
return opts;
|
|
||||||
}
|
|
||||||
|
|
||||||
var tscReporter = {
|
|
||||||
error: function (error) {
|
|
||||||
console.error(error.message);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// We use Babel to easily create named System.register modules
|
|
||||||
// See: https://github.com/Microsoft/TypeScript/issues/4801
|
|
||||||
// and https://github.com/ivogabe/gulp-typescript/issues/211
|
|
||||||
const babelOptions = {
|
|
||||||
moduleIds: true,
|
|
||||||
getModuleId: function (name) {
|
|
||||||
return 'ionic-angular/' + name;
|
|
||||||
},
|
|
||||||
plugins: ['transform-es2015-modules-systemjs'],
|
|
||||||
presets: [ES_2015]
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Builds demos tests to dist/demos and watches for changes. Runs 'demos.bundle' or
|
|
||||||
* 'sass' on Ionic source changes and 'demos.build' for demos test changes.
|
|
||||||
*/
|
|
||||||
task('demos.watch', ['demos'], function () {
|
|
||||||
watchTask('demos.bundle');
|
|
||||||
|
|
||||||
watch('demos/src/**/*', function (file) {
|
|
||||||
start('demos.build');
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
function watchTask(task) {
|
function serveDemo(folderName: any) {
|
||||||
watch([
|
|
||||||
'src/**/*.ts',
|
|
||||||
'!src/components/*/test/**/*',
|
|
||||||
'!src/util/test/*'
|
|
||||||
],
|
|
||||||
function (file) {
|
|
||||||
if (file.event !== 'unlink') {
|
|
||||||
start(task);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
watch('src/**/*.scss', function () {
|
const ionicAngularDir = join(PROJECT_ROOT, 'src');
|
||||||
start('demos.sass');
|
const srcTestRoot = join(DEMOS_ROOT, 'src', folderName);
|
||||||
});
|
const distDemoRoot = join(DIST_DEMOS_ROOT, folderName);
|
||||||
|
const includeGlob = [ join(ionicAngularDir, '**', '*.ts'),
|
||||||
|
join(srcTestRoot, '**', '*.ts')];
|
||||||
|
|
||||||
start('demos.serve');
|
|
||||||
|
const pathToWriteFile = join(distDemoRoot, 'tsconfig.json');
|
||||||
|
const pathToReadFile = join(PROJECT_ROOT, 'tsconfig.json');
|
||||||
|
|
||||||
|
createTempTsConfig(includeGlob, ES_2015, ES_2015, pathToReadFile, pathToWriteFile, { removeComments: true});
|
||||||
|
|
||||||
|
const sassConfigPath = join('scripts', 'demos', 'sass.config.js');
|
||||||
|
const copyConfigPath = join('scripts', 'demos', 'copy.config.js');
|
||||||
|
const watchConfigPath = join('scripts', 'demos', 'watch.config.js');
|
||||||
|
|
||||||
|
const appEntryPoint = join(srcTestRoot, 'app', 'main.ts');
|
||||||
|
const appNgModulePath = join(srcTestRoot, 'app', 'app.module.ts');
|
||||||
|
const distDir = join(distDemoRoot, 'www');
|
||||||
|
|
||||||
|
return runAppScriptsServe(folderName, appEntryPoint, appNgModulePath, ionicAngularDir, distDir, pathToWriteFile, ionicAngularDir, sassConfigPath, copyConfigPath, watchConfigPath);
|
||||||
}
|
}
|
||||||
|
@ -1,193 +1,193 @@
|
|||||||
import { accessSync, F_OK, readFileSync, stat } from 'fs';
|
import { dirname, join, relative } from 'path';
|
||||||
import { dirname, join } from 'path';
|
import { readFileSync } from 'fs';
|
||||||
|
|
||||||
import { dest, src, start, task } from 'gulp';
|
import * as glob from 'glob';
|
||||||
import * as gulpif from 'gulp-if';
|
import { task } from 'gulp';
|
||||||
import * as watch from 'gulp-watch';
|
import * as del from 'del';
|
||||||
|
import { template } from 'lodash';
|
||||||
import * as runSequence from 'run-sequence';
|
import * as runSequence from 'run-sequence';
|
||||||
import { obj } from 'through2';
|
import { argv } from 'yargs';
|
||||||
import * as VinylFile from 'vinyl';
|
|
||||||
|
|
||||||
import { DEMOS_SRC_ROOT, DIST_DEMOS_ROOT, DIST_NAME, DEMOS_NAME, ES5, ES_2015, LOCAL_SERVER_PORT, SCRIPTS_ROOT } from '../constants';
|
|
||||||
import { createTempTsConfig, getFolderInfo, getFolders, runAppScripts } from '../util';
|
|
||||||
|
|
||||||
task('demos.prod', demosBuild);
|
import { DEMOS_SRC_ROOT, ES_2015, PROJECT_ROOT, SRC_ROOT, SRC_COMPONENTS_ROOT, SCRIPTS_ROOT } from '../constants';
|
||||||
|
import { createTempTsConfig, getFolderInfo, readFileAsync, runAppScriptsBuild, writeFileAsync, writePolyfills } from '../util';
|
||||||
|
|
||||||
function demosBuild(done: (err: any) => void) {
|
import * as pAll from 'p-all';
|
||||||
runSequence(
|
|
||||||
'demos.copyIonic',
|
task('demos.prepare', (done: Function) => {
|
||||||
'demos.clean',
|
runSequence('demos.clean', 'demos.polyfill', (err: any) => done(err));
|
||||||
'demos.polyfill',
|
});
|
||||||
'demos.copySource',
|
|
||||||
'demos.copyExternalDependencies',
|
task('demos.prod', ['demos.prepare'], (done: Function) => {
|
||||||
'demos.sass',
|
|
||||||
'demos.fonts',
|
// okay, first find out all of the demos tests to run by finding all of the 'main.ts' files
|
||||||
'demos.compileTests',
|
filterDemosEntryPoints().then((filePaths: string[]) => {
|
||||||
done);
|
console.log(`Compiling ${filePaths.length} Demos ...`);
|
||||||
|
console.log('filePaths: ', filePaths);
|
||||||
|
return buildDemos(filePaths);
|
||||||
|
}).then(() => {
|
||||||
|
done();
|
||||||
|
}).catch((err: Error) => {
|
||||||
|
done(err);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
function filterDemosEntryPoints() {
|
||||||
|
return getDemosEntryPoints().then((entryPoints: string[]) => {
|
||||||
|
const folderInfo = getFolderInfo();
|
||||||
|
if (folderInfo && folderInfo.componentName) {
|
||||||
|
const filtered = entryPoints.filter(entryPoint => {
|
||||||
|
return entryPoint.indexOf(folderInfo.componentName) >= 0;
|
||||||
|
});
|
||||||
|
return filtered;
|
||||||
|
}
|
||||||
|
return entryPoints;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
task('demos.copyIonic', (done: (err: any) => void) => {
|
function getDemosEntryPoints() {
|
||||||
runSequence(
|
return new Promise((resolve, reject) => {
|
||||||
'compile.release',
|
const mainGlob = join(DEMOS_SRC_ROOT, '**', 'main.ts');
|
||||||
'release.compileSass',
|
glob(mainGlob, (err: Error, matches: string[]) => {
|
||||||
'release.fonts',
|
if (err) {
|
||||||
'release.sass',
|
return reject(err);
|
||||||
'release.createUmdBundle',
|
|
||||||
done);
|
|
||||||
});
|
|
||||||
|
|
||||||
task('demos.copySource', (done: Function) => {
|
|
||||||
const stream = src([`${DEMOS_SRC_ROOT}/**/*`])
|
|
||||||
.pipe(gulpif(/app.module.ts$/, createIndexHTML()))
|
|
||||||
.pipe(dest(DIST_DEMOS_ROOT));
|
|
||||||
|
|
||||||
stream.on('end', done);
|
|
||||||
|
|
||||||
function createIndexHTML() {
|
|
||||||
const indexTemplate = readFileSync(`${SCRIPTS_ROOT}/${DEMOS_NAME}/demos.template.prod.html`);
|
|
||||||
const indexTs = readFileSync(`${SCRIPTS_ROOT}/${DEMOS_NAME}/main.ts`);
|
|
||||||
|
|
||||||
return obj(function (file, enc, next) {
|
|
||||||
this.push(new VinylFile({
|
|
||||||
base: file.base,
|
|
||||||
contents: new Buffer(indexTemplate),
|
|
||||||
path: join(dirname(file.path), 'index.html'),
|
|
||||||
}));
|
|
||||||
this.push(new VinylFile({
|
|
||||||
base: file.base,
|
|
||||||
contents: new Buffer(indexTs),
|
|
||||||
path: join(dirname(file.path), 'main.ts'),
|
|
||||||
}));
|
|
||||||
next(null, file);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
task('demos.compileTests', (done: Function) => {
|
|
||||||
let folderInfo = getFolderInfo();
|
|
||||||
|
|
||||||
if (folderInfo.componentName && folderInfo.componentTest) {
|
|
||||||
buildTest(folderInfo);
|
|
||||||
} else {
|
|
||||||
buildAllTests(done);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
function buildTest(folderInfo: any) {
|
|
||||||
let includeGlob = [`./dist/demos/${folderInfo.componentName}/*.ts`];
|
|
||||||
let pathToWriteFile = `${DIST_DEMOS_ROOT}/${folderInfo.componentName}/tsconfig.json`;
|
|
||||||
|
|
||||||
createTempTsConfig(includeGlob, ES5, ES_2015, `${DEMOS_SRC_ROOT}/tsconfig.json`, pathToWriteFile);
|
|
||||||
|
|
||||||
let sassConfigPath = 'scripts/demos/sass.config.js';
|
|
||||||
|
|
||||||
let appEntryPoint = `dist/demos/${folderInfo.componentName}/main.ts`;
|
|
||||||
let appNgModule = `dist/demos/${folderInfo.componentName}/app.module.ts`;
|
|
||||||
let distDir = `dist/demos/${folderInfo.componentName}/`;
|
|
||||||
|
|
||||||
return runAppScripts(folderInfo, sassConfigPath, appEntryPoint, appNgModule, distDir);
|
|
||||||
}
|
|
||||||
|
|
||||||
function buildAllTests(done: Function) {
|
|
||||||
let folders = getFolders('./dist/demos/');
|
|
||||||
let promises: Promise<any>[] = [];
|
|
||||||
|
|
||||||
folders.forEach(folder => {
|
|
||||||
stat(`./dist/demos/${folder}/app.module.ts`, function(err, stat) {
|
|
||||||
if (err == null) {
|
|
||||||
let folderInfo = {
|
|
||||||
componentName: folder,
|
|
||||||
componentTest: 'basic'
|
|
||||||
};
|
|
||||||
const promise = buildTest(folderInfo);
|
|
||||||
promises.push(promise);
|
|
||||||
}
|
}
|
||||||
|
resolve(matches);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
Promise.all(promises).then(() => {
|
|
||||||
|
function buildDemos(filePaths: string[]) {
|
||||||
|
const functions = filePaths.map(filePath => () => {
|
||||||
|
return buildDemo(filePath);
|
||||||
|
});
|
||||||
|
return pAll(functions, {concurrency: 8});
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildDemo(filePath: string) {
|
||||||
|
const start = Date.now();
|
||||||
|
const ionicAngularDir = join(process.cwd(), 'src');
|
||||||
|
|
||||||
|
const componentDir = dirname(dirname(filePath));
|
||||||
|
const relativePathFromComponents = relative(dirname(DEMOS_SRC_ROOT), componentDir);
|
||||||
|
console.log('relativePathFromComponents: ', relativePathFromComponents);
|
||||||
|
|
||||||
|
const distTestRoot = join(process.cwd(), 'dist', 'demos', relativePathFromComponents);
|
||||||
|
|
||||||
|
const includeGlob = [ join(ionicAngularDir, '**', '*.ts'), join(componentDir, '**', '*.ts')];
|
||||||
|
const pathToWriteFile = join(distTestRoot, 'tsconfig.json');
|
||||||
|
const pathToReadFile = join(PROJECT_ROOT, 'tsconfig.json');
|
||||||
|
|
||||||
|
createTempTsConfig(includeGlob, ES_2015, ES_2015, pathToReadFile, pathToWriteFile, { removeComments: true});
|
||||||
|
|
||||||
|
const sassConfigPath = join('scripts', 'demos', 'sass.config.js');
|
||||||
|
const copyConfigPath = join('scripts', 'demos', 'copy.config.js');
|
||||||
|
|
||||||
|
const appEntryPoint = filePath;
|
||||||
|
const appNgModulePath = join(dirname(filePath), 'app.module.ts');
|
||||||
|
const distDir = join(distTestRoot, 'www');
|
||||||
|
|
||||||
|
return runAppScriptsBuild(appEntryPoint, appNgModulePath, ionicAngularDir, distDir, pathToWriteFile, ionicAngularDir, sassConfigPath, copyConfigPath).then(() => {
|
||||||
|
const end = Date.now();
|
||||||
|
console.log(`${filePath} took a total of ${(end - start) / 1000} seconds to build`);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function copyProtractorTestContent(filePaths: string[]): Promise<any> {
|
||||||
|
return readDemosTestFiles(filePaths)
|
||||||
|
.then((map: Map<string, string>) => {
|
||||||
|
return applyTemplate(map);
|
||||||
|
}).then((map: Map<string, string>) => {
|
||||||
|
writeDemosJsFiles(map);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function applyTemplate(filePathContent: Map<string, string>) {
|
||||||
|
const buildConfig = require('../../build/config');
|
||||||
|
const templateFileContent = readFileSync(join(SCRIPTS_ROOT, 'demos', 'demos.template.js'));
|
||||||
|
const templater = template(templateFileContent.toString());
|
||||||
|
const modifiedMap = new Map<string, string>();
|
||||||
|
const platforms = ['android', 'ios', 'windows'];
|
||||||
|
filePathContent.forEach((fileContent: string, filePath: string) => {
|
||||||
|
const srcRelativePath = relative(SRC_ROOT, dirname(filePath));
|
||||||
|
const wwwRelativePath = join(srcRelativePath, 'www');
|
||||||
|
platforms.forEach(platform => {
|
||||||
|
const platformContents = templater({
|
||||||
|
contents: fileContent,
|
||||||
|
buildConfig: buildConfig,
|
||||||
|
relativePath: wwwRelativePath,
|
||||||
|
platform: platform,
|
||||||
|
relativePathBackwardsCompatibility: dirname(wwwRelativePath)
|
||||||
|
});
|
||||||
|
const newFilePath = join(wwwRelativePath, `${platform}.demos.js`);
|
||||||
|
modifiedMap.set(newFilePath, platformContents);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
return modifiedMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
function writeDemosJsFiles(map: Map<string, string>) {
|
||||||
|
const promises: Promise<any>[] = [];
|
||||||
|
map.forEach((fileContent: string, filePath: string) => {
|
||||||
|
const destination = join(process.cwd(), 'dist', 'demos', filePath);
|
||||||
|
promises.push(writeFileAsync(destination, fileContent));
|
||||||
|
});
|
||||||
|
return Promise.all(promises);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function readDemosTestFiles(mainFilePaths: string[]): Promise<Map<string, string>> {
|
||||||
|
const demosFiles = mainFilePaths.map(mainFilePath => {
|
||||||
|
return join(dirname(mainFilePath), 'demos.ts');
|
||||||
|
});
|
||||||
|
|
||||||
|
const promises: Promise<any>[] = [];
|
||||||
|
const map = new Map<string, string>();
|
||||||
|
for (const demosFile of demosFiles) {
|
||||||
|
const promise = readDemosFile(demosFile);
|
||||||
|
promises.push(promise);
|
||||||
|
promise.then((content: string) => {
|
||||||
|
map.set(demosFile, content);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return Promise.all(promises).then(() => {
|
||||||
|
return map;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function readDemosFile(filePath: string) {
|
||||||
|
return readFileAsync(filePath).then((content: string) => {
|
||||||
|
// purge the import statement at the top
|
||||||
|
const purgeImportRegex = /.*?import.*?'protractor';/g;
|
||||||
|
return content.replace(purgeImportRegex, '');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
task('demos.clean', (done: Function) => {
|
||||||
|
// this is a super hack, but it works for now
|
||||||
|
if (argv.skipClean) {
|
||||||
|
return done();
|
||||||
|
}
|
||||||
|
|
||||||
|
del(['dist/demos/**']).then(() => {
|
||||||
done();
|
done();
|
||||||
}).catch(err => {
|
}).catch(err => {
|
||||||
done(err);
|
done(err);
|
||||||
});
|
});
|
||||||
}
|
|
||||||
|
|
||||||
task('demos.watchProd', (done: Function) => {
|
|
||||||
const folderInfo = getFolderInfo();
|
|
||||||
let demoTestPath = DEMOS_SRC_ROOT;
|
|
||||||
|
|
||||||
if (folderInfo.componentName && folderInfo.componentTest) {
|
|
||||||
demoTestPath = join(DEMOS_SRC_ROOT, folderInfo.componentName, 'app.module.ts');
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
accessSync(demoTestPath, F_OK);
|
|
||||||
} catch (e) {
|
|
||||||
done(new Error(`Could not find demos test: ${demoTestPath}`));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (demosComponentsExists(folderInfo)) {
|
|
||||||
// already generated the demos directory
|
|
||||||
demosWatch(folderInfo.componentName, folderInfo.componentTest);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
// generate the demos directory
|
|
||||||
console.log('Generate demo builds first...');
|
|
||||||
demosBuild(() => {
|
|
||||||
demosWatch(folderInfo.componentName, folderInfo.componentTest);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
function demosWatch(componentName: string, componentTest: string) {
|
task('demos.polyfill', (done: Function) => {
|
||||||
// If any tests change within components then run demos.resources.
|
if (argv.skipPolyfill) {
|
||||||
watch([
|
return done();
|
||||||
'demos/src/**/*'
|
}
|
||||||
],
|
|
||||||
function (file) {
|
|
||||||
console.log('start demos.resources - ' + JSON.stringify(file.history, null, 2));
|
|
||||||
start('demos.copyAndCompile');
|
|
||||||
});
|
|
||||||
|
|
||||||
// If any src files change except for tests then transpile only the source ionic files
|
writePolyfills('dist/demos/polyfills').then(() => {
|
||||||
watch([
|
done();
|
||||||
'src/**/*.ts',
|
}).catch(err => {
|
||||||
'!src/components/*/test/**/*',
|
done(err);
|
||||||
'!src/util/test/*'
|
|
||||||
],
|
|
||||||
function (file) {
|
|
||||||
console.log('start demos.ngcSource - ' + JSON.stringify(file.history, null, 2));
|
|
||||||
start('demos.copyAndCompile');
|
|
||||||
});
|
|
||||||
|
|
||||||
// If any scss files change then recompile all sass
|
|
||||||
watch(['src/**/*.scss'], (file) => {
|
|
||||||
console.log('start sass - ' + JSON.stringify(file.history, null, 2));
|
|
||||||
start('demos.sass');
|
|
||||||
});
|
});
|
||||||
|
});
|
||||||
let serverUrl = `http://localhost:${LOCAL_SERVER_PORT}/${DIST_NAME}/${DEMOS_NAME}`;
|
|
||||||
if (componentName) {
|
|
||||||
serverUrl += `/${componentName}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log(serverUrl);
|
|
||||||
|
|
||||||
start('demos.serve');
|
|
||||||
}
|
|
||||||
|
|
||||||
function demosComponentsExists(folderInfo: any): boolean {
|
|
||||||
let componentPath = DIST_DEMOS_ROOT;
|
|
||||||
|
|
||||||
if (folderInfo.componentName && folderInfo.componentTest) {
|
|
||||||
componentPath += `/${folderInfo.componentName}/build`;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
accessSync(componentPath, F_OK);
|
|
||||||
} catch (e) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
@ -1,222 +1,50 @@
|
|||||||
|
import { dirname, join } from 'path';
|
||||||
import { readFileSync } from 'fs';
|
import { readFileSync } from 'fs';
|
||||||
import { dirname, join, sep } from 'path';
|
|
||||||
|
|
||||||
import { dest, src, start, task } from 'gulp';
|
import { task } from 'gulp';
|
||||||
import * as babel from 'gulp-babel';
|
|
||||||
import * as cache from 'gulp-cached';
|
|
||||||
import * as concat from 'gulp-concat';
|
|
||||||
import * as connect from 'gulp-connect';
|
|
||||||
import * as gulpif from 'gulp-if';
|
|
||||||
import * as remember from 'gulp-remember';
|
|
||||||
import * as rename from 'gulp-rename';
|
|
||||||
import * as tsc from 'gulp-typescript';
|
|
||||||
import * as watch from 'gulp-watch';
|
|
||||||
import { template } from 'lodash';
|
|
||||||
import * as merge from 'merge2';
|
|
||||||
import * as runSequence from 'run-sequence';
|
|
||||||
import { obj } from 'through2';
|
|
||||||
import * as VinylFile from 'vinyl';
|
|
||||||
|
|
||||||
import { DIST_E2E_ROOT, DIST_NAME, E2E_NAME, ES5, ES_2015, SCRIPTS_ROOT } from '../constants';
|
import { ES_2015, PROJECT_ROOT } from '../constants';
|
||||||
|
import { createTempTsConfig, getFolderInfo, runAppScriptsServe } from '../util';
|
||||||
|
|
||||||
const buildConfig = require('../../build/config');
|
task('e2e.watch', ['e2e.prepare'], (done: Function) => {
|
||||||
|
const folderInfo = getFolderInfo();
|
||||||
/**
|
if (!folderInfo || !folderInfo.componentName || !folderInfo.componentTest) {
|
||||||
* Builds Ionic e2e tests to dist/e2e and creates the necessary files for tests
|
done(new Error(`Usage: gulp e2e.watch --folder nav/basic`));
|
||||||
* to run.
|
|
||||||
*/
|
|
||||||
task('e2e', e2eBuild);
|
|
||||||
|
|
||||||
function e2eBuild(done: (err: any) => void) {
|
|
||||||
runSequence(
|
|
||||||
'e2e.clean',
|
|
||||||
'e2e.build',
|
|
||||||
'e2e.polyfill',
|
|
||||||
'e2e.copyExternalDependencies',
|
|
||||||
'e2e.sass',
|
|
||||||
'e2e.fonts',
|
|
||||||
'e2e.bundle',
|
|
||||||
done);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Builds Ionic e2e tests to dist/e2e.
|
|
||||||
*/
|
|
||||||
task('e2e.build', function () {
|
|
||||||
var indexTemplate = template(
|
|
||||||
readFileSync(`${SCRIPTS_ROOT}/${E2E_NAME}/e2e.template.dev.html`).toString()
|
|
||||||
)({
|
|
||||||
buildConfig: buildConfig
|
|
||||||
});
|
|
||||||
|
|
||||||
// Get each test folder with src
|
|
||||||
var tsResult = src([
|
|
||||||
'src/components/*/test/*/**/*.ts',
|
|
||||||
'!src/components/*/test/*/**/*.spec.ts'
|
|
||||||
])
|
|
||||||
.pipe(cache('e2e.ts'))
|
|
||||||
.pipe(tsc(getTscOptions(), undefined, tscReporter))
|
|
||||||
.on('error', function (error) {
|
|
||||||
console.log(error.message);
|
|
||||||
})
|
|
||||||
.pipe(gulpif(/app.module.js$/, createIndexHTML()))
|
|
||||||
.pipe(gulpif(/e2e.js$/, createPlatformTests()));
|
|
||||||
|
|
||||||
var testFiles = src([
|
|
||||||
'src/components/*/test/*/**/*',
|
|
||||||
'!src/components/*/test/*/**/*.ts'
|
|
||||||
])
|
|
||||||
.pipe(cache('e2e.files'));
|
|
||||||
|
|
||||||
return merge([
|
|
||||||
tsResult,
|
|
||||||
testFiles
|
|
||||||
])
|
|
||||||
.pipe(rename(function (file) {
|
|
||||||
file.dirname = file.dirname.replace(sep + 'test' + sep, sep);
|
|
||||||
}))
|
|
||||||
.pipe(dest(DIST_E2E_ROOT))
|
|
||||||
.pipe(connect.reload());
|
|
||||||
|
|
||||||
function createIndexHTML() {
|
|
||||||
return obj(function (file, enc, next) {
|
|
||||||
this.push(new VinylFile({
|
|
||||||
base: file.base,
|
|
||||||
contents: new Buffer(indexTemplate),
|
|
||||||
path: join(dirname(file.path), 'index.html'),
|
|
||||||
}));
|
|
||||||
next(null, file);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function createPlatformTests() {
|
serveTest(folderInfo).then(() => {
|
||||||
let platforms = [
|
done();
|
||||||
'android',
|
}).catch((err: Error) => {
|
||||||
'ios',
|
done(err);
|
||||||
'windows'
|
|
||||||
];
|
|
||||||
|
|
||||||
let testTemplate = template(readFileSync(`${SCRIPTS_ROOT}/${E2E_NAME}/e2e.template.js`).toString());
|
|
||||||
|
|
||||||
return obj(function (file, enc, next) {
|
|
||||||
let self = this;
|
|
||||||
|
|
||||||
let relativePath = dirname(file.path.replace(/^.*?src(\/|\\)components(\/|\\)/, ''));
|
|
||||||
relativePath = relativePath.replace('/test/', '/');
|
|
||||||
|
|
||||||
let contents = file.contents.toString();
|
|
||||||
platforms.forEach(function (platform) {
|
|
||||||
let platformContents = testTemplate({
|
|
||||||
contents: contents,
|
|
||||||
buildConfig: buildConfig,
|
|
||||||
relativePath: relativePath,
|
|
||||||
platform: platform
|
|
||||||
});
|
|
||||||
self.push(new VinylFile({
|
|
||||||
base: file.base,
|
|
||||||
contents: new Buffer(platformContents),
|
|
||||||
path: file.path.replace(/e2e.js$/, platform + '.e2e.js')
|
|
||||||
}));
|
|
||||||
});
|
|
||||||
next();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates SystemJS bundle from Ionic source files.
|
|
||||||
*/
|
|
||||||
task('e2e.bundle', function () {
|
|
||||||
return tsCompile(getTscOptions('es6'), 'system')
|
|
||||||
.pipe(babel(babelOptions))
|
|
||||||
.pipe(remember('system'))
|
|
||||||
.pipe(concat('ionic.system.js'))
|
|
||||||
.pipe(dest(`${DIST_NAME}/bundles`))
|
|
||||||
.pipe(connect.reload());
|
|
||||||
});
|
|
||||||
|
|
||||||
function tsCompile(options, cacheName) {
|
|
||||||
return src([
|
|
||||||
'typings/main.d.ts',
|
|
||||||
'src/**/*.ts',
|
|
||||||
'!src/**/*.d.ts',
|
|
||||||
'!src/components/*/test/**/*',
|
|
||||||
'!src/util/test/*',
|
|
||||||
'!src/config/test/*',
|
|
||||||
'!src/platform/test/*',
|
|
||||||
'!src/**/*.spec.ts'
|
|
||||||
])
|
|
||||||
.pipe(cache(cacheName, { optimizeMemory: true }))
|
|
||||||
.pipe(tsc(options, undefined, tscReporter));
|
|
||||||
}
|
|
||||||
|
|
||||||
function getTscOptions(name?: string) {
|
|
||||||
var opts = {
|
|
||||||
emitDecoratorMetadata: true,
|
|
||||||
experimentalDecorators: true,
|
|
||||||
target: ES5,
|
|
||||||
module: 'commonjs',
|
|
||||||
isolatedModules: true,
|
|
||||||
typescript: require('typescript'),
|
|
||||||
declaration: false
|
|
||||||
};
|
|
||||||
|
|
||||||
if (name === 'typecheck') {
|
|
||||||
opts.declaration = true;
|
|
||||||
delete opts.isolatedModules;
|
|
||||||
} else if (name === 'es6') {
|
|
||||||
opts.target = 'es6';
|
|
||||||
delete opts.module;
|
|
||||||
}
|
|
||||||
return opts;
|
|
||||||
}
|
|
||||||
|
|
||||||
var tscReporter = {
|
|
||||||
error: function (error) {
|
|
||||||
console.error(error.message);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// We use Babel to easily create named System.register modules
|
|
||||||
// See: https://github.com/Microsoft/TypeScript/issues/4801
|
|
||||||
// and https://github.com/ivogabe/gulp-typescript/issues/211
|
|
||||||
const babelOptions = {
|
|
||||||
moduleIds: true,
|
|
||||||
getModuleId: function (name) {
|
|
||||||
return 'ionic-angular/' + name;
|
|
||||||
},
|
|
||||||
plugins: ['transform-es2015-modules-systemjs'],
|
|
||||||
presets: [ES_2015]
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Builds e2e tests to dist/e2e and watches for changes. Runs 'e2e.bundle' or
|
|
||||||
* 'sass' on Ionic source changes and 'e2e.build' for e2e test changes.
|
|
||||||
*/
|
|
||||||
task('e2e.watch', ['e2e'], function () {
|
|
||||||
watchTask('e2e.bundle');
|
|
||||||
|
|
||||||
watch('src/components/*/test/**/*', function (file) {
|
|
||||||
start('e2e.build');
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
function watchTask(task) {
|
function serveTest(folderInfo: any) {
|
||||||
watch([
|
|
||||||
'src/**/*.ts',
|
|
||||||
'!src/components/*/test/**/*',
|
|
||||||
'!src/util/test/*'
|
|
||||||
],
|
|
||||||
function (file) {
|
|
||||||
if (file.event !== 'unlink') {
|
|
||||||
start(task);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
watch('src/**/*.scss', function () {
|
const ionicAngularDir = join(PROJECT_ROOT, 'src');
|
||||||
start('e2e.sass');
|
const srcTestRoot = join(PROJECT_ROOT, 'src', 'components', folderInfo.componentName, 'test', folderInfo.componentTest);
|
||||||
});
|
const distTestRoot = join(PROJECT_ROOT, 'dist', 'e2e', 'components', folderInfo.componentName, 'test', folderInfo.componentTest);
|
||||||
|
const includeGlob = [ join(ionicAngularDir, '**', '*.ts')];
|
||||||
|
const pathToWriteFile = join(distTestRoot, 'tsconfig.json');
|
||||||
|
const pathToReadFile = join(PROJECT_ROOT, 'tsconfig.json');
|
||||||
|
|
||||||
start('e2e.serve');
|
createTempTsConfig(includeGlob, ES_2015, ES_2015, pathToReadFile, pathToWriteFile, { removeComments: true});
|
||||||
|
|
||||||
|
const sassConfigPath = join('scripts', 'e2e', 'sass.config.js');
|
||||||
|
const copyConfigPath = join('scripts', 'e2e', 'copy.config.js');
|
||||||
|
|
||||||
|
let appEntryPoint = join(srcTestRoot, 'app', 'main.ts');
|
||||||
|
try {
|
||||||
|
// check if the entry point exists, otherwise fall back to the legacy entry point without 'app' folder
|
||||||
|
readFileSync(appEntryPoint);
|
||||||
|
} catch (ex) {
|
||||||
|
// the file doesn't exist, so use the legacy entry point
|
||||||
|
appEntryPoint = join(srcTestRoot, 'main.ts');
|
||||||
|
}
|
||||||
|
|
||||||
|
// this assume that app.module.ts and main.ts are peers, which they should be no matter what
|
||||||
|
const appNgModulePath = join(dirname(appEntryPoint), 'app.module.ts');
|
||||||
|
const distDir = join(distTestRoot, 'www');
|
||||||
|
|
||||||
|
return runAppScriptsServe(folderInfo.componentName + '/' + folderInfo.componentTest, appEntryPoint, appNgModulePath, ionicAngularDir, distDir, pathToWriteFile, ionicAngularDir, sassConfigPath, copyConfigPath, null);
|
||||||
}
|
}
|
||||||
|
@ -1,237 +1,220 @@
|
|||||||
import { accessSync, F_OK, readFileSync, stat } from 'fs';
|
import { dirname, join, relative } from 'path';
|
||||||
import { dirname, join } from 'path';
|
import { readFileSync, writeFileSync } from 'fs';
|
||||||
|
|
||||||
import { dest, src, start, task } from 'gulp';
|
import * as glob from 'glob';
|
||||||
import * as gulpif from 'gulp-if';
|
import { task } from 'gulp';
|
||||||
import * as watch from 'gulp-watch';
|
import * as del from 'del';
|
||||||
import { template } from 'lodash';
|
import { template } from 'lodash';
|
||||||
import * as runSequence from 'run-sequence';
|
import * as runSequence from 'run-sequence';
|
||||||
import { obj } from 'through2';
|
import { argv } from 'yargs';
|
||||||
import * as VinylFile from 'vinyl';
|
|
||||||
|
|
||||||
import { DIST_E2E_ROOT, DIST_NAME, E2E_NAME, ES5, ES_2015, LOCAL_SERVER_PORT, DEMOS_SRC_ROOT, SCRIPTS_ROOT, SRC_ROOT } from '../constants';
|
|
||||||
import { createTempTsConfig, getFolderInfo, getFolders, runAppScripts} from '../util';
|
|
||||||
|
|
||||||
task('e2e.prod', e2eBuild);
|
import { ES_2015, PROJECT_ROOT, SRC_ROOT, SRC_COMPONENTS_ROOT, SCRIPTS_ROOT } from '../constants';
|
||||||
|
import { createTempTsConfig, createTimestamp, getFolderInfo, readFileAsync, runAppScriptsBuild, writeFileAsync, writePolyfills } from '../util';
|
||||||
|
|
||||||
function e2eBuild(done: (err: any) => void) {
|
import * as pAll from 'p-all';
|
||||||
runSequence(
|
|
||||||
'e2e.copyIonic',
|
|
||||||
'e2e.clean',
|
|
||||||
'e2e.polyfill',
|
|
||||||
'e2e.copySource',
|
|
||||||
'e2e.copyExternalDependencies',
|
|
||||||
'e2e.sass',
|
|
||||||
'e2e.fonts',
|
|
||||||
'e2e.compileTests',
|
|
||||||
done);
|
|
||||||
}
|
|
||||||
|
|
||||||
task('e2e.copyIonic', (done: (err: any) => void) => {
|
task('e2e.prepare', (done: Function) => {
|
||||||
runSequence(
|
runSequence('e2e.clean', 'e2e.polyfill', 'e2e.prepareSass', (err: any) => done(err));
|
||||||
'compile.release',
|
|
||||||
'release.compileSass',
|
|
||||||
'release.fonts',
|
|
||||||
'release.sass',
|
|
||||||
'release.createUmdBundle',
|
|
||||||
done);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
task('e2e.copySource', (done: Function) => {
|
task('e2e.prepareSass', (done: Function) => {
|
||||||
|
const version = `E2E-${createTimestamp()}`;
|
||||||
|
writeFileSync(join(SRC_ROOT, 'themes/version.scss'), `$ionic-version: "${version}";`);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
|
||||||
const buildConfig = require('../../build/config');
|
task('e2e.prod', ['e2e.prepare'], (done: Function) => {
|
||||||
|
|
||||||
const stream = src([`${SRC_ROOT}/**/*`, `!${SRC_ROOT}/**/*.spec.ts`])
|
// okay, first find out all of the e2e tests to run by finding all of the 'main.ts' files
|
||||||
.pipe(gulpif(/app.module.ts$/, createIndexHTML()))
|
filterE2eTestfiles().then((filePaths: string[]) => {
|
||||||
.pipe(gulpif(/e2e.ts$/, createPlatformTests()))
|
console.log(`Compiling ${filePaths.length} E2E tests ...`);
|
||||||
.pipe(dest(DIST_E2E_ROOT));
|
return buildTests(filePaths);
|
||||||
|
}).then(() => {
|
||||||
|
done();
|
||||||
|
}).catch((err: Error) => {
|
||||||
|
done(err);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
stream.on('end', done);
|
function filterE2eTestfiles() {
|
||||||
|
return getE2eTestFiles().then((filePaths: string[]) => {
|
||||||
function createIndexHTML() {
|
const entryPoints = filePaths.map(filePath => {
|
||||||
const indexTemplate = readFileSync(`${SCRIPTS_ROOT}/${E2E_NAME}/e2e.template.prod.html`);
|
const directoryName = dirname(filePath);
|
||||||
const indexTs = readFileSync(`${SCRIPTS_ROOT}/${E2E_NAME}/main.ts`);
|
return join(directoryName, 'app', 'main.ts');
|
||||||
|
|
||||||
return obj(function (file, enc, next) {
|
|
||||||
this.push(new VinylFile({
|
|
||||||
base: file.base,
|
|
||||||
contents: new Buffer(indexTemplate),
|
|
||||||
path: join(dirname(file.path), 'index.html'),
|
|
||||||
}));
|
|
||||||
this.push(new VinylFile({
|
|
||||||
base: file.base,
|
|
||||||
contents: new Buffer(indexTs),
|
|
||||||
path: join(dirname(file.path), 'main.ts'),
|
|
||||||
}));
|
|
||||||
next(null, file);
|
|
||||||
});
|
});
|
||||||
}
|
return entryPoints;
|
||||||
|
}).then((entryPoints: string[]) => {
|
||||||
// TODO this is almost the same as dev, diff and combine
|
const folderInfo = getFolderInfo();
|
||||||
function createPlatformTests() {
|
if (folderInfo && folderInfo.componentName && folderInfo.componentTest) {
|
||||||
let platforms = [
|
const filtered = entryPoints.filter(entryPoint => {
|
||||||
'android',
|
return entryPoint.indexOf(folderInfo.componentName) >= 0 && entryPoint.indexOf(folderInfo.componentTest) >= 0;
|
||||||
'ios',
|
|
||||||
'windows'
|
|
||||||
];
|
|
||||||
|
|
||||||
let testTemplate = template(readFileSync(`${SCRIPTS_ROOT}/${E2E_NAME}/e2e.template.js`).toString());
|
|
||||||
|
|
||||||
return obj(function (file, enc, next) {
|
|
||||||
let self = this;
|
|
||||||
|
|
||||||
let relativePath = dirname(file.path.replace(/^.*?src(\/|\\)/, ''));
|
|
||||||
|
|
||||||
let contents = file.contents.toString();
|
|
||||||
platforms.forEach(function (platform) {
|
|
||||||
let platformContents = testTemplate({
|
|
||||||
contents: contents,
|
|
||||||
buildConfig: buildConfig,
|
|
||||||
relativePath: relativePath,
|
|
||||||
platform: platform
|
|
||||||
});
|
|
||||||
self.push(new VinylFile({
|
|
||||||
base: file.base,
|
|
||||||
contents: new Buffer(platformContents),
|
|
||||||
path: file.path.replace(/e2e.ts$/, platform + '.e2e.js')
|
|
||||||
}));
|
|
||||||
});
|
});
|
||||||
next();
|
return filtered;
|
||||||
});
|
}
|
||||||
}
|
return entryPoints;
|
||||||
});
|
});
|
||||||
|
|
||||||
task('e2e.compileTests', (done: Function) => {
|
|
||||||
let folderInfo = getFolderInfo();
|
|
||||||
|
|
||||||
if (folderInfo.componentName && folderInfo.componentTest) {
|
|
||||||
buildTest(folderInfo);
|
|
||||||
} else {
|
|
||||||
buildAllTests(done);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
function buildTest(folderInfo: any) {
|
|
||||||
let includeGlob = [`./dist/e2e/components/${folderInfo.componentName}/test/${folderInfo.componentTest}/*.ts`];
|
|
||||||
let pathToWriteFile = `${DIST_E2E_ROOT}/components/${folderInfo.componentName}/test/${folderInfo.componentTest}/tsconfig.json`;
|
|
||||||
|
|
||||||
createTempTsConfig(includeGlob, ES5, ES_2015, `${DEMOS_SRC_ROOT}/tsconfig.json`, pathToWriteFile);
|
|
||||||
|
|
||||||
let sassConfigPath = 'scripts/e2e/sass.config.js';
|
|
||||||
|
|
||||||
let appEntryPoint = `dist/e2e/components/${folderInfo.componentName}/test/${folderInfo.componentTest}/main.ts`;
|
|
||||||
let appNgModule = `dist/e2e/components/${folderInfo.componentName}/test/${folderInfo.componentTest}/app.module.ts`;
|
|
||||||
let distDir = `dist/e2e/components/${folderInfo.componentName}/test/${folderInfo.componentTest}/`;
|
|
||||||
|
|
||||||
return runAppScripts(folderInfo, sassConfigPath, appEntryPoint, appNgModule, distDir);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildAllTests(done: Function) {
|
function getE2eTestFiles() {
|
||||||
let folders = getFolders('./dist/e2e/components');
|
return new Promise((resolve, reject) => {
|
||||||
let promises: Promise<any>[] = [];
|
const mainGlob = join(SRC_COMPONENTS_ROOT, '*', 'test', '*', 'e2e.ts');
|
||||||
|
glob(mainGlob, (err: Error, matches: string[]) => {
|
||||||
folders.forEach(folder => {
|
if (err) {
|
||||||
console.log(folder);
|
return reject(err);
|
||||||
stat(`./dist/e2e/components/${folder}/test`, function(err, stat) {
|
|
||||||
if (err == null) {
|
|
||||||
let testFolders = getFolders(`./dist/e2e/components/${folder}/test`);
|
|
||||||
|
|
||||||
testFolders.forEach(test => {
|
|
||||||
console.log('build test for ', folder, test);
|
|
||||||
let folderInfo = {
|
|
||||||
componentName: folder,
|
|
||||||
componentTest: test
|
|
||||||
};
|
|
||||||
const promise = buildTest(folderInfo);
|
|
||||||
promises.push(promise);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
resolve(matches);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
Promise.all(promises).then(() => {
|
|
||||||
|
function buildTests(filePaths: string[]) {
|
||||||
|
const functions = filePaths.map(filePath => () => {
|
||||||
|
return buildTest(filePath);
|
||||||
|
});
|
||||||
|
return pAll(functions, {concurrency: 8}).then(() => {
|
||||||
|
// copy over all of the protractor tests to the correct location now
|
||||||
|
return copyProtractorTestContent(filePaths);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildTest(filePath: string) {
|
||||||
|
const start = Date.now();
|
||||||
|
const ionicAngularDir = join(process.cwd(), 'src');
|
||||||
|
|
||||||
|
let appEntryPoint = filePath;
|
||||||
|
let srcTestRoot = dirname(dirname(appEntryPoint));
|
||||||
|
try {
|
||||||
|
// check if the entry point exists, otherwise fall back to the legacy entry point without 'app' folder
|
||||||
|
readFileSync(appEntryPoint);
|
||||||
|
} catch (ex) {
|
||||||
|
// the file doesn't exist, so use the legacy entry point
|
||||||
|
appEntryPoint = join(dirname(dirname(appEntryPoint)), 'main.ts');
|
||||||
|
srcTestRoot = dirname(appEntryPoint);
|
||||||
|
}
|
||||||
|
|
||||||
|
const relativePathFromComponents = relative(dirname(SRC_COMPONENTS_ROOT), srcTestRoot);
|
||||||
|
const distTestRoot = join(process.cwd(), 'dist', 'e2e', relativePathFromComponents);
|
||||||
|
|
||||||
|
const includeGlob = [ join(ionicAngularDir, '**', '*.ts')];
|
||||||
|
const pathToWriteFile = join(distTestRoot, 'tsconfig.json');
|
||||||
|
const pathToReadFile = join(PROJECT_ROOT, 'tsconfig.json');
|
||||||
|
|
||||||
|
createTempTsConfig(includeGlob, ES_2015, ES_2015, pathToReadFile, pathToWriteFile, { removeComments: true});
|
||||||
|
|
||||||
|
const sassConfigPath = join('scripts', 'e2e', 'sass.config.js');
|
||||||
|
const copyConfigPath = join('scripts', 'e2e', 'copy.config.js');
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const appNgModulePath = join(dirname(appEntryPoint), 'app.module.ts');
|
||||||
|
const distDir = join(distTestRoot, 'www');
|
||||||
|
|
||||||
|
return runAppScriptsBuild(appEntryPoint, appNgModulePath, ionicAngularDir, distDir, pathToWriteFile, ionicAngularDir, sassConfigPath, copyConfigPath).then(() => {
|
||||||
|
const end = Date.now();
|
||||||
|
console.log(`${filePath} took a total of ${(end - start) / 1000} seconds to build`);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function copyProtractorTestContent(filePaths: string[]): Promise<any> {
|
||||||
|
const e2eTestPaths = filePaths.map(filePath => {
|
||||||
|
return join(dirname(dirname(filePath)), 'e2e.ts');
|
||||||
|
});
|
||||||
|
return readE2ETestFiles(e2eTestPaths)
|
||||||
|
.then((map: Map<string, string>) => {
|
||||||
|
return applyTemplate(map);
|
||||||
|
}).then((map: Map<string, string>) => {
|
||||||
|
writeE2EJsFiles(map);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function applyTemplate(filePathContent: Map<string, string>) {
|
||||||
|
const buildConfig = require('../../build/config');
|
||||||
|
const templateFileContent = readFileSync(join(SCRIPTS_ROOT, 'e2e', 'e2e.template.js'));
|
||||||
|
const templater = template(templateFileContent.toString());
|
||||||
|
const modifiedMap = new Map<string, string>();
|
||||||
|
const platforms = ['android', 'ios', 'windows'];
|
||||||
|
filePathContent.forEach((fileContent: string, filePath: string) => {
|
||||||
|
const srcRelativePath = relative(SRC_ROOT, dirname(filePath));
|
||||||
|
const wwwRelativePath = join(srcRelativePath, 'www');
|
||||||
|
platforms.forEach(platform => {
|
||||||
|
const platformContents = templater({
|
||||||
|
contents: fileContent,
|
||||||
|
buildConfig: buildConfig,
|
||||||
|
relativePath: wwwRelativePath,
|
||||||
|
platform: platform,
|
||||||
|
relativePathBackwardsCompatibility: dirname(wwwRelativePath)
|
||||||
|
});
|
||||||
|
const newFilePath = join(wwwRelativePath, `${platform}.e2e.js`);
|
||||||
|
modifiedMap.set(newFilePath, platformContents);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
return modifiedMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
function writeE2EJsFiles(map: Map<string, string>) {
|
||||||
|
const promises: Promise<any>[] = [];
|
||||||
|
map.forEach((fileContent: string, filePath: string) => {
|
||||||
|
const destination = join(process.cwd(), 'dist', 'e2e', filePath);
|
||||||
|
promises.push(writeFileAsync(destination, fileContent));
|
||||||
|
});
|
||||||
|
return Promise.all(promises);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function readE2ETestFiles(mainFilePaths: string[]): Promise<Map<string, string>> {
|
||||||
|
const e2eFiles = mainFilePaths.map(mainFilePath => {
|
||||||
|
return join(dirname(mainFilePath), 'e2e.ts');
|
||||||
|
});
|
||||||
|
|
||||||
|
const promises: Promise<any>[] = [];
|
||||||
|
const map = new Map<string, string>();
|
||||||
|
for (const e2eFile of e2eFiles) {
|
||||||
|
const promise = readE2EFile(e2eFile);
|
||||||
|
promises.push(promise);
|
||||||
|
promise.then((content: string) => {
|
||||||
|
map.set(e2eFile, content);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return Promise.all(promises).then(() => {
|
||||||
|
return map;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function readE2EFile(filePath: string) {
|
||||||
|
return readFileAsync(filePath).then((content: string) => {
|
||||||
|
// purge the import statement at the top
|
||||||
|
const purgeImportRegex = /.*?import.*?'protractor';/g;
|
||||||
|
return content.replace(purgeImportRegex, '');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
task('e2e.clean', (done: Function) => {
|
||||||
|
// this is a super hack, but it works for now
|
||||||
|
if (argv.skipClean) {
|
||||||
|
return done();
|
||||||
|
}
|
||||||
|
|
||||||
|
del(['dist/e2e/**']).then(() => {
|
||||||
done();
|
done();
|
||||||
}).catch(err => {
|
}).catch(err => {
|
||||||
done(err);
|
done(err);
|
||||||
});
|
});
|
||||||
}
|
|
||||||
|
|
||||||
task('e2e.watchProd', (done: Function) => {
|
|
||||||
const folderInfo = getFolderInfo();
|
|
||||||
let e2eTestPath = SRC_ROOT;
|
|
||||||
|
|
||||||
if (folderInfo.componentName && folderInfo.componentTest) {
|
|
||||||
e2eTestPath = join(`${SRC_ROOT}/components/${folderInfo.componentName}/test/${folderInfo.componentTest}/app.module.ts`);
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
accessSync(e2eTestPath, F_OK);
|
|
||||||
} catch (e) {
|
|
||||||
done(new Error(`Could not find e2e test: ${e2eTestPath}`));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (e2eComponentsExists(folderInfo)) {
|
|
||||||
// already generated the e2e directory
|
|
||||||
e2eWatch(folderInfo.componentName, folderInfo.componentTest);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
// generate the e2e directory
|
|
||||||
console.log('Generate e2e builds first...');
|
|
||||||
e2eBuild(() => {
|
|
||||||
e2eWatch(folderInfo.componentName, folderInfo.componentTest);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
function e2eWatch(componentName: string, componentTest: string) {
|
task('e2e.polyfill', (done: Function) => {
|
||||||
// If any tests change within components then run e2e.resources.
|
if (argv.skipPolyfill) {
|
||||||
watch([
|
return done();
|
||||||
'e2e/src/**/*'
|
}
|
||||||
],
|
|
||||||
function (file) {
|
|
||||||
console.log('start e2e.resources - ' + JSON.stringify(file.history, null, 2));
|
|
||||||
start('e2e.copyAndCompile');
|
|
||||||
});
|
|
||||||
|
|
||||||
// If any src files change except for tests then transpile only the source ionic files
|
writePolyfills('dist/e2e/polyfills').then(() => {
|
||||||
watch([
|
done();
|
||||||
'src/**/*.ts',
|
}).catch(err => {
|
||||||
'!src/components/*/test/**/*',
|
done(err);
|
||||||
'!src/util/test/*'
|
|
||||||
],
|
|
||||||
function (file) {
|
|
||||||
console.log('start e2e.ngcSource - ' + JSON.stringify(file.history, null, 2));
|
|
||||||
start('e2e.copyAndCompile');
|
|
||||||
});
|
|
||||||
|
|
||||||
// If any scss files change then recompile all sass
|
|
||||||
watch(['src/**/*.scss'], (file) => {
|
|
||||||
console.log('start sass - ' + JSON.stringify(file.history, null, 2));
|
|
||||||
start('e2e.sass');
|
|
||||||
});
|
});
|
||||||
|
});
|
||||||
let serverUrl = `http://localhost:${LOCAL_SERVER_PORT}/${DIST_NAME}/${E2E_NAME}`;
|
|
||||||
if (componentName) {
|
|
||||||
serverUrl += `/${componentName}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log(serverUrl);
|
|
||||||
|
|
||||||
start('e2e.serve');
|
|
||||||
}
|
|
||||||
|
|
||||||
function e2eComponentsExists(folderInfo: any): boolean {
|
|
||||||
let componentPath = `${DIST_E2E_ROOT}/components`;
|
|
||||||
|
|
||||||
if (folderInfo.componentName && folderInfo.componentTest) {
|
|
||||||
componentPath += `/${folderInfo.componentName}/test/${folderInfo.componentTest}/build`;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
accessSync(componentPath, F_OK);
|
|
||||||
} catch (e) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
@ -1,55 +0,0 @@
|
|||||||
import { dest, src, task } from 'gulp';
|
|
||||||
import * as connect from 'gulp-connect';
|
|
||||||
import * as del from 'del';
|
|
||||||
import * as runSequence from 'run-sequence';
|
|
||||||
|
|
||||||
import { DIST_E2E_ROOT, LOCAL_SERVER_PORT, SCRIPTS_ROOT } from '../constants';
|
|
||||||
import { compileSass, copyFonts, createTimestamp, setSassIonicVersion, writePolyfills } from '../util';
|
|
||||||
|
|
||||||
task('e2e.clean', (done: Function) => {
|
|
||||||
del(['dist/e2e/**']).then(() => {
|
|
||||||
done();
|
|
||||||
}).catch(err => {
|
|
||||||
done(err);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
task('e2e.polyfill', (done: Function) => {
|
|
||||||
writePolyfills('dist/e2e/polyfills').then(() => {
|
|
||||||
done();
|
|
||||||
}).catch(err => {
|
|
||||||
done(err);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
task('e2e.copyAndCompile', (done: (err: any) => void) => {
|
|
||||||
runSequence(
|
|
||||||
'e2e.copySource',
|
|
||||||
'e2e.compileTests',
|
|
||||||
'e2e.bundle',
|
|
||||||
done);
|
|
||||||
});
|
|
||||||
|
|
||||||
task('e2e.copyExternalDependencies', () => {
|
|
||||||
src([`${SCRIPTS_ROOT}/e2e/*.css`]).pipe(dest(`${DIST_E2E_ROOT}/css`));
|
|
||||||
});
|
|
||||||
|
|
||||||
task('e2e.sass', () => {
|
|
||||||
// ensure there is a version.scss file
|
|
||||||
setSassIonicVersion(`E2E-${createTimestamp()}`);
|
|
||||||
return compileSass(`${DIST_E2E_ROOT}/css`);
|
|
||||||
});
|
|
||||||
|
|
||||||
task('e2e.fonts', () => {
|
|
||||||
return copyFonts(`${DIST_E2E_ROOT}/fonts`);
|
|
||||||
});
|
|
||||||
|
|
||||||
task('e2e.serve', function() {
|
|
||||||
connect.server({
|
|
||||||
root: './',
|
|
||||||
port: LOCAL_SERVER_PORT,
|
|
||||||
livereload: {
|
|
||||||
port: 35700
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
@ -7,27 +7,19 @@ import { task } from 'gulp';
|
|||||||
import * as serveStatic from 'serve-static';
|
import * as serveStatic from 'serve-static';
|
||||||
import { argv } from 'yargs';
|
import { argv } from 'yargs';
|
||||||
|
|
||||||
import { DIST_E2E_ROOT, DIST_E2E_COMPONENTS_ROOT, PROJECT_ROOT, SCRIPTS_ROOT } from '../constants';
|
import { DIST_E2E_COMPONENTS_ROOT, PROJECT_ROOT, SCRIPTS_ROOT } from '../constants';
|
||||||
import { mergeObjects } from '../util';
|
import { mergeObjects } from '../util';
|
||||||
|
|
||||||
|
|
||||||
task('snapshot', ['e2e.prod'], (done: Function) => {
|
task('snapshot', ['e2e.prod'], (done: Function) => {
|
||||||
snapshot(false, false, done);
|
snapshot(false, done);
|
||||||
});
|
});
|
||||||
|
|
||||||
task('snapshot.skipBuild', ['e2e.sass'], (done: Function) => {
|
task('snapshot.skipBuild', (done: Function) => {
|
||||||
snapshot(false, false, done);
|
snapshot(false, done);
|
||||||
});
|
});
|
||||||
|
|
||||||
task('snapshot.dev', ['e2e'], (done: Function) => {
|
function snapshot(quickMode: boolean, callback: Function) {
|
||||||
snapshot(false, true, done);
|
|
||||||
});
|
|
||||||
|
|
||||||
task('snapshot.quick', ['e2e.sass'], (done: Function) => {
|
|
||||||
snapshot(true, true, done);
|
|
||||||
});
|
|
||||||
|
|
||||||
function snapshot(quickMode: boolean, devMode: boolean, callback: Function) {
|
|
||||||
const snapshotConfig = require('../../snapshot/snapshot.config').config;
|
const snapshotConfig = require('../../snapshot/snapshot.config').config;
|
||||||
const protractorConfigFile = resolve(SCRIPTS_ROOT, 'snapshot/protractor.config.js');
|
const protractorConfigFile = resolve(SCRIPTS_ROOT, 'snapshot/protractor.config.js');
|
||||||
|
|
||||||
@ -41,6 +33,7 @@ function snapshot(quickMode: boolean, devMode: boolean, callback: Function) {
|
|||||||
|
|
||||||
let component = '*';
|
let component = '*';
|
||||||
let e2eSpecs = '*';
|
let e2eSpecs = '*';
|
||||||
|
|
||||||
const folderArg: string = argv.folder || argv.f;
|
const folderArg: string = argv.folder || argv.f;
|
||||||
if (folderArg && folderArg.length) {
|
if (folderArg && folderArg.length) {
|
||||||
const folderArgPaths = folderArg.split('/');
|
const folderArgPaths = folderArg.split('/');
|
||||||
@ -49,10 +42,10 @@ function snapshot(quickMode: boolean, devMode: boolean, callback: Function) {
|
|||||||
e2eSpecs = folderArgPaths[1];
|
e2eSpecs = folderArgPaths[1];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var specs = join(DIST_E2E_COMPONENTS_ROOT, component, 'test', e2eSpecs, '*e2e.js');
|
|
||||||
if (devMode) specs = join(DIST_E2E_ROOT, component, e2eSpecs, '*e2e.js');
|
|
||||||
|
|
||||||
console.log('[snapshot] Running with', devMode ? 'Development' : 'Production', 'build');
|
const specs = join(DIST_E2E_COMPONENTS_ROOT, component, 'test', e2eSpecs, 'www', '*e2e.js');
|
||||||
|
|
||||||
|
console.log('[snapshot] Running with', 'Production', 'build');
|
||||||
console.log(`[snapshot] Specs: ${specs}`);
|
console.log(`[snapshot] Specs: ${specs}`);
|
||||||
|
|
||||||
const testId = generateTestId();
|
const testId = generateTestId();
|
||||||
@ -71,7 +64,6 @@ function snapshot(quickMode: boolean, devMode: boolean, callback: Function) {
|
|||||||
'--params.height=' + snapshotValues.params.height,
|
'--params.height=' + snapshotValues.params.height,
|
||||||
'--params.test_id=' + snapshotValues.params.test_id,
|
'--params.test_id=' + snapshotValues.params.test_id,
|
||||||
'--params.upload=' + snapshotValues.params.upload,
|
'--params.upload=' + snapshotValues.params.upload,
|
||||||
'--params.dev=' + devMode,
|
|
||||||
'--specs=' + specs
|
'--specs=' + specs
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -6,6 +6,10 @@ task('test', ['test.assembleVendorJs', 'compile.karma'], (done: Function) => {
|
|||||||
karmaTest(false, done);
|
karmaTest(false, done);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
task('test.fast', ['compile.karma'], (done: Function) => {
|
||||||
|
karmaTest(false, done);
|
||||||
|
});
|
||||||
|
|
||||||
task('test.watch', ['test.assembleVendorJs', 'compile.karma'], (done: Function) => {
|
task('test.watch', ['test.assembleVendorJs', 'compile.karma'], (done: Function) => {
|
||||||
karmaTest(true, done);
|
karmaTest(true, done);
|
||||||
});
|
});
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import { spawnSync } from 'child_process';
|
import { spawn } from 'child_process';
|
||||||
import { NODE_MODULES_ROOT, SRC_ROOT } from './constants';
|
import { NODE_MODULES_ROOT, SRC_ROOT } from './constants';
|
||||||
import { src, dest } from 'gulp';
|
import { src, dest } from 'gulp';
|
||||||
import { join } from 'path';
|
import { dirname, join } from 'path';
|
||||||
import { readdirSync, readFileSync, statSync, writeFileSync } from 'fs';
|
import { ensureDirSync, readdirSync, readFile, readFileSync, statSync, writeFile, writeFileSync } from 'fs-extra';
|
||||||
import { rollup } from 'rollup';
|
import { rollup } from 'rollup';
|
||||||
import { Replacer } from 'strip-function';
|
import { Replacer } from 'strip-function';
|
||||||
import * as commonjs from 'rollup-plugin-commonjs';
|
import * as commonjs from 'rollup-plugin-commonjs';
|
||||||
@ -12,6 +12,8 @@ import * as through from 'through2';
|
|||||||
import * as uglifyPlugin from 'rollup-plugin-uglify';
|
import * as uglifyPlugin from 'rollup-plugin-uglify';
|
||||||
import { argv } from 'yargs';
|
import { argv } from 'yargs';
|
||||||
|
|
||||||
|
import { runWorker } from './utils/app-scripts-worker-client';
|
||||||
|
|
||||||
// These packages lack of types.
|
// These packages lack of types.
|
||||||
const resolveBin = require('resolve-bin');
|
const resolveBin = require('resolve-bin');
|
||||||
|
|
||||||
@ -39,7 +41,7 @@ function getRootTsConfig(pathToReadFile): any {
|
|||||||
return tsConfig;
|
return tsConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createTempTsConfig(includeGlob: string[], target: string, moduleType: string, pathToReadFile: string, pathToWriteFile: string): any {
|
export function createTempTsConfig(includeGlob: string[], target: string, moduleType: string, pathToReadFile: string, pathToWriteFile: string, overrideCompileOptions: any = null): any {
|
||||||
let config = getRootTsConfig(pathToReadFile);
|
let config = getRootTsConfig(pathToReadFile);
|
||||||
if (!config.compilerOptions) {
|
if (!config.compilerOptions) {
|
||||||
config.compilerOptions = {};
|
config.compilerOptions = {};
|
||||||
@ -53,12 +55,20 @@ export function createTempTsConfig(includeGlob: string[], target: string, module
|
|||||||
config.compilerOptions.target = target;
|
config.compilerOptions.target = target;
|
||||||
}
|
}
|
||||||
config.include = includeGlob;
|
config.include = includeGlob;
|
||||||
|
|
||||||
|
if (overrideCompileOptions) {
|
||||||
|
config.compilerOptions = Object.assign(config.compilerOptions, overrideCompileOptions);
|
||||||
|
}
|
||||||
|
|
||||||
let json = JSON.stringify(config, null, 2);
|
let json = JSON.stringify(config, null, 2);
|
||||||
|
|
||||||
|
const dirToCreate = dirname(pathToWriteFile);
|
||||||
|
ensureDirSync(dirToCreate);
|
||||||
writeFileSync(pathToWriteFile, json);
|
writeFileSync(pathToWriteFile, json);
|
||||||
}
|
}
|
||||||
|
|
||||||
function removeDebugStatements() {
|
function removeDebugStatements() {
|
||||||
let replacer = new Replacer(['console.debug', 'assert', 'runInDev']);
|
let replacer = new Replacer(['console.debug', 'console.time', 'console.timeEnd', 'assert', 'runInDev']);
|
||||||
return through.obj(function (file, encoding, callback) {
|
return through.obj(function (file, encoding, callback) {
|
||||||
const content = file.contents.toString();
|
const content = file.contents.toString();
|
||||||
const cleanedJs = replacer.replace(content);
|
const cleanedJs = replacer.replace(content);
|
||||||
@ -75,7 +85,7 @@ export function copySourceToDest(destinationPath: string, excludeSpecs: boolean,
|
|||||||
glob.push(`${SRC_ROOT}/**/*.spec.ts`);
|
glob.push(`${SRC_ROOT}/**/*.spec.ts`);
|
||||||
}
|
}
|
||||||
if (excludeE2e) {
|
if (excludeE2e) {
|
||||||
glob.push(`!${SRC_ROOT}/components/*/test/*/*.ts`);
|
glob.push(`!${SRC_ROOT}/components/*/test/**/*.ts`);
|
||||||
}
|
}
|
||||||
let stream = src(glob);
|
let stream = src(glob);
|
||||||
if (stripDebug) {
|
if (stripDebug) {
|
||||||
@ -178,41 +188,58 @@ export function runWebpack(pathToWebpackConfig: string, done: Function) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function runAppScripts(folderInfo: any, sassConfigPath: string, appEntryPoint: string, appNgModulePath: string, distDir: string) {
|
export function runAppScriptsServe(testOrDemoName: string, appEntryPoint: string, appNgModulePath: string, srcDir: string, distDir: string, tsConfig: string, ionicAngularDir: string, sassConfigPath: string, copyConfigPath: string, watchConfigPath: string) {
|
||||||
console.log('Running ionic-app-scripts build with', folderInfo.componentName, '/', folderInfo.componentTest);
|
console.log('Running ionic-app-scripts serve with', testOrDemoName);
|
||||||
let tsConfig = distDir + 'tsconfig.json';
|
|
||||||
let scriptArgs = [
|
let scriptArgs = [
|
||||||
'build',
|
'serve',
|
||||||
'--sass', sassConfigPath,
|
|
||||||
'--appEntryPoint', appEntryPoint,
|
'--appEntryPoint', appEntryPoint,
|
||||||
'--appNgModulePath', appNgModulePath,
|
'--appNgModulePath', appNgModulePath,
|
||||||
'--srcDir', distDir,
|
'--srcDir', srcDir,
|
||||||
'--wwwDir', distDir,
|
'--wwwDir', distDir,
|
||||||
'--tsconfig', tsConfig
|
'--tsconfig', tsConfig,
|
||||||
];
|
'--readConfigJson', 'false',
|
||||||
|
'--experimentalParseDeepLinks', 'true',
|
||||||
|
'--ionicAngularDir', ionicAngularDir,
|
||||||
|
'--sass', sassConfigPath,
|
||||||
|
'--copy', copyConfigPath
|
||||||
|
];
|
||||||
|
|
||||||
|
if (watchConfigPath) {
|
||||||
|
scriptArgs.push('--watch');
|
||||||
|
scriptArgs.push(watchConfigPath);
|
||||||
|
}
|
||||||
|
|
||||||
const debug: boolean = argv.debug;
|
const debug: boolean = argv.debug;
|
||||||
if (debug) {
|
if (debug) {
|
||||||
scriptArgs.push('--debug');
|
scriptArgs.push('--debug');
|
||||||
scriptArgs.push('--aot');
|
|
||||||
} else {
|
|
||||||
scriptArgs.push('--prod');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
return new Promise((resolve, reject) => {
|
||||||
console.log('$ node ./node_modules/.bin/ionic-app-scripts', scriptArgs.join(' '));
|
const args = ['./node_modules/.bin/ionic-app-scripts'].concat(scriptArgs);
|
||||||
const scriptsCmd = spawnSync('node', ['./node_modules/.bin/ionic-app-scripts'].concat(scriptArgs));
|
console.log(`node ${args.join(' ')}`);
|
||||||
|
const spawnedCommand = spawn('node', args);
|
||||||
|
|
||||||
if (scriptsCmd.status !== 0) {
|
spawnedCommand.stdout.on('data', (buffer: Buffer) => {
|
||||||
console.log(scriptsCmd.stderr.toString());
|
console.log(buffer.toString());
|
||||||
return Promise.reject(scriptsCmd.stderr.toString());
|
});
|
||||||
}
|
|
||||||
|
|
||||||
console.log(scriptsCmd.output.toString());
|
spawnedCommand.stderr.on('data', (buffer: Buffer) => {
|
||||||
return Promise.resolve();
|
console.error(buffer.toString());
|
||||||
} catch (ex) {
|
});
|
||||||
return Promise.reject(ex);
|
|
||||||
}
|
spawnedCommand.on('close', (code: number) => {
|
||||||
|
if (code === 0) {
|
||||||
|
return resolve();
|
||||||
|
}
|
||||||
|
reject(new Error('App-scripts failed with non-zero status code'));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function runAppScriptsBuild(appEntryPoint: string, appNgModulePath: string, srcDir: string, distDir: string, tsConfig: string, ionicAngularDir: string, sassConfigPath: string, copyConfigPath: string) {
|
||||||
|
const pathToAppScripts = join(NODE_MODULES_ROOT, '.bin', 'ionic-app-scripts');
|
||||||
|
const debug: boolean = argv.debug;
|
||||||
|
return runWorker(pathToAppScripts, debug, appEntryPoint, appNgModulePath, srcDir, distDir, tsConfig, ionicAngularDir, sassConfigPath, copyConfigPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Resolves the path for a node package executable. */
|
/** Resolves the path for a node package executable. */
|
||||||
@ -302,7 +329,10 @@ function bundlePolyfill(pathsToIncludeInPolyfill: string[], outputPath: string)
|
|||||||
}),
|
}),
|
||||||
commonjs(),
|
commonjs(),
|
||||||
uglifyPlugin()
|
uglifyPlugin()
|
||||||
]
|
],
|
||||||
|
onwarn: () => {
|
||||||
|
return () => {};
|
||||||
|
}
|
||||||
}).then((bundle) => {
|
}).then((bundle) => {
|
||||||
return bundle.write({
|
return bundle.write({
|
||||||
format: 'iife',
|
format: 'iife',
|
||||||
@ -333,3 +363,25 @@ export function getFolders(dir) {
|
|||||||
return statSync(join(dir, file)).isDirectory();
|
return statSync(join(dir, file)).isDirectory();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function readFileAsync(filePath: string) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
readFile(filePath, (err: Error, buffer: Buffer) => {
|
||||||
|
if (err) {
|
||||||
|
return reject(err);
|
||||||
|
}
|
||||||
|
return resolve(buffer.toString());
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function writeFileAsync(filePath: string, fileContent: string) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
writeFile(filePath, fileContent, (err: Error) => {
|
||||||
|
if (err) {
|
||||||
|
return reject(err);
|
||||||
|
}
|
||||||
|
return resolve();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
102
scripts/gulp/utils/app-scripts-worker-client.ts
Normal file
102
scripts/gulp/utils/app-scripts-worker-client.ts
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
import { fork, ChildProcess } from 'child_process';
|
||||||
|
import { join } from 'path';
|
||||||
|
|
||||||
|
import { MessageToWorker, WorkerProcess } from './interfaces';
|
||||||
|
|
||||||
|
export function runWorker(pathToAppScripts: string, debug: boolean, appEntryPoint: string, appNgModulePath: string, srcDir: string, distDir: string, tsConfig: string, ionicAngularDir: string, sassConfigPath: string, copyConfigPath: string) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
|
||||||
|
const msgToWorker: MessageToWorker = {
|
||||||
|
pathToAppScripts: pathToAppScripts,
|
||||||
|
appEntryPoint: appEntryPoint,
|
||||||
|
appNgModulePath: appNgModulePath,
|
||||||
|
debug: debug,
|
||||||
|
srcDir: srcDir,
|
||||||
|
distDir: distDir,
|
||||||
|
tsConfig: tsConfig,
|
||||||
|
ionicAngularDir: ionicAngularDir,
|
||||||
|
sassConfigPath: sassConfigPath,
|
||||||
|
copyConfigPath: copyConfigPath
|
||||||
|
};
|
||||||
|
|
||||||
|
const worker = <ChildProcess>createWorker(msgToWorker);
|
||||||
|
console.log(`Starting to build test ${appEntryPoint}`);
|
||||||
|
|
||||||
|
worker.on('error', (err: any) => {
|
||||||
|
console.error(`worker error, entrypoint: ${appEntryPoint}, pid: ${worker.pid}, error: ${err}`);
|
||||||
|
reject(err);
|
||||||
|
});
|
||||||
|
|
||||||
|
worker.on('exit', (code: number) => {
|
||||||
|
console.log(`Finished building test ${appEntryPoint}`);
|
||||||
|
if (code === 0) {
|
||||||
|
resolve(code);
|
||||||
|
} else {
|
||||||
|
reject(new Error(`${appEntryPoint} exited with non-zero status code`));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export function createWorker(msg: MessageToWorker): any {
|
||||||
|
for (var i = workers.length - 1; i >= 0; i--) {
|
||||||
|
if (workers[i].appEntryPoint === msg.appEntryPoint) {
|
||||||
|
try {
|
||||||
|
workers[i].worker.kill('SIGKILL');
|
||||||
|
} catch (e) {
|
||||||
|
console.log(`createWorker, kill('SIGKILL'): ${e}`);
|
||||||
|
} finally {
|
||||||
|
delete workers[i].worker;
|
||||||
|
workers.splice(i, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
let scriptArgs = [
|
||||||
|
'build',
|
||||||
|
'--aot',
|
||||||
|
'--optimizejs',
|
||||||
|
'--appEntryPoint', msg.appEntryPoint,
|
||||||
|
'--appNgModulePath', msg.appNgModulePath,
|
||||||
|
'--srcDir', msg.srcDir,
|
||||||
|
'--wwwDir', msg.distDir,
|
||||||
|
'--tsconfig', msg.tsConfig,
|
||||||
|
'--readConfigJson', 'false',
|
||||||
|
'--experimentalParseDeepLinks', 'true',
|
||||||
|
'--experimentalManualTreeshaking', 'false',
|
||||||
|
'--experimentalPurgeDecorators', 'false',
|
||||||
|
'--ionicAngularDir', msg.ionicAngularDir,
|
||||||
|
'--sass', msg.sassConfigPath,
|
||||||
|
'--copy', msg.copyConfigPath,
|
||||||
|
'--enableLint', 'false',
|
||||||
|
// '--disableLogging', 'true'
|
||||||
|
];
|
||||||
|
|
||||||
|
if (msg.debug) {
|
||||||
|
scriptArgs.push('--debug');
|
||||||
|
}
|
||||||
|
|
||||||
|
const workerModule = join(process.cwd(), 'node_modules', '@ionic', 'app-scripts', 'bin', 'ionic-app-scripts.js');
|
||||||
|
const worker = fork(workerModule, scriptArgs, {
|
||||||
|
env: {
|
||||||
|
FORCE_COLOR: true,
|
||||||
|
npm_config_argv: process.env.npm_config_argv
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
workers.push({
|
||||||
|
appEntryPoint: msg.appEntryPoint,
|
||||||
|
worker: worker
|
||||||
|
});
|
||||||
|
|
||||||
|
return worker;
|
||||||
|
|
||||||
|
} catch (e) {
|
||||||
|
throw new Error(`unable to create worker-process: ${e.msg}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export const workers: WorkerProcess[] = [];
|
18
scripts/gulp/utils/interfaces.ts
Normal file
18
scripts/gulp/utils/interfaces.ts
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
|
||||||
|
export interface WorkerProcess {
|
||||||
|
appEntryPoint: string;
|
||||||
|
worker: any;
|
||||||
|
};
|
||||||
|
|
||||||
|
export interface MessageToWorker {
|
||||||
|
pathToAppScripts: string;
|
||||||
|
debug: boolean;
|
||||||
|
appEntryPoint: string;
|
||||||
|
appNgModulePath: string;
|
||||||
|
srcDir: string;
|
||||||
|
distDir: string;
|
||||||
|
tsConfig: string;
|
||||||
|
ionicAngularDir: string;
|
||||||
|
sassConfigPath: string;
|
||||||
|
copyConfigPath: string;
|
||||||
|
};
|
@ -8,7 +8,7 @@
|
|||||||
"url": "https://github.com/driftyco/ionic.git"
|
"url": "https://github.com/driftyco/ionic.git"
|
||||||
},
|
},
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"main": "umd/index.js",
|
"main": "esm/index.js",
|
||||||
"module": "index.js",
|
"module": "index.js",
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@angular/common": "",
|
"@angular/common": "",
|
||||||
|
@ -115,10 +115,13 @@ var IonicSnapshot = function(options) {
|
|||||||
var specIdString = '[' + (spec.id+1) + '/' + self.testData.total_specs + ']';
|
var specIdString = '[' + (spec.id+1) + '/' + self.testData.total_specs + ']';
|
||||||
|
|
||||||
self.testData.spec_index = spec.id;
|
self.testData.spec_index = spec.id;
|
||||||
|
// console.log('spec.id: ', spec.id);
|
||||||
self.testData.highest_mismatch = self.highestMismatch;
|
self.testData.highest_mismatch = self.highestMismatch;
|
||||||
self.testData.png_base64 = pngBase64;
|
self.testData.png_base64 = pngBase64;
|
||||||
self.testData.description = spec.getFullName().replace('components/', '').replace('test/', '');
|
self.testData.description = spec.getFullName().replace('components/', '').replace('test/', '').replace('www', '');
|
||||||
self.testData.url = currentUrl.replace('dist', '').replace('components/', '').replace('test/', '').replace('&ionicanimate=false', '');
|
self.testData.url = currentUrl.replace('dist', '').replace('components/', '').replace('test/', '').replace('&ionicanimate=false', '').replace('www/', '');
|
||||||
|
//console.log('self.testData.description: ', self.testData.description);
|
||||||
|
//console.log('self.testData.url: ', self.testData.url);
|
||||||
pngBase64 = null;
|
pngBase64 = null;
|
||||||
|
|
||||||
var requestDeferred = q.defer();
|
var requestDeferred = q.defer();
|
||||||
|
17
scripts/templates/component/module.ts.tmpl
Normal file
17
scripts/templates/component/module.ts.tmpl
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
import { $CLASSNAMEComponent } from './$FILENAME';
|
||||||
|
import { IonicModule } from 'ionic-angular';
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
declarations: [
|
||||||
|
$CLASSNAMEComponent,
|
||||||
|
],
|
||||||
|
imports: [
|
||||||
|
IonicModule.forChild($CLASSNAMEComponent)
|
||||||
|
],
|
||||||
|
entryComponents: [
|
||||||
|
$CLASSNAMEComponent
|
||||||
|
],
|
||||||
|
providers: []
|
||||||
|
})
|
||||||
|
export class $CLASSNAMEComponentModule {}
|
17
scripts/templates/page/module.ts.tmpl
Normal file
17
scripts/templates/page/module.ts.tmpl
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
import { $CLASSNAMEPage } from './$FILENAME';
|
||||||
|
import { IonicModule } from 'ionic-angular';
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
declarations: [
|
||||||
|
$CLASSNAMEPage,
|
||||||
|
],
|
||||||
|
imports: [
|
||||||
|
IonicModule.forChild($CLASSNAMEPage)
|
||||||
|
],
|
||||||
|
entryComponents: [
|
||||||
|
$CLASSNAMEPage
|
||||||
|
],
|
||||||
|
providers: []
|
||||||
|
})
|
||||||
|
export class $CLASSNAMEPageModule {}
|
Reference in New Issue
Block a user