diff --git a/scripts/build/config.js b/scripts/build/config.js index 31d1a3bb42..098077c9f6 100644 --- a/scripts/build/config.js +++ b/scripts/build/config.js @@ -26,9 +26,9 @@ module.exports = { autoprefixer: { browsers: [ 'last 2 versions', - 'iOS >= 7', - 'Android >= 4', - 'Explorer >= 10', + 'iOS >= 8', + 'Android >= 4.4', + 'Explorer >= 11', 'ExplorerMobile >= 11' ], cascade: false diff --git a/scripts/e2e/e2e-publish.js b/scripts/e2e/e2e-publish.js index b2148d8a5f..60c895f5e5 100644 --- a/scripts/e2e/e2e-publish.js +++ b/scripts/e2e/e2e-publish.js @@ -4,7 +4,7 @@ module.exports = function(options) { var fs = require('fs'); var path = require('path'); var request = require('request'); - var inputDir = path.join(__dirname, '../../dist'); + var inputDir = path.join(__dirname, '../../dist/e2e/tests'); var uploadQueue = []; var ignoreFiles = /(\/test\/|\/ts\/|\/q\/|\/ionic-site\/|\/docs\/|\/examples\/|\/inquirer\/|\/lodash\/|\/tooling\/|\/colors\/|\/bin\/|\.ts$|\.bin|\.map$|\.md$|\.git|\.scss$|\.yml$|\.yaml$|\.dart$|\.txt|\.npm|bower|DS_Store|LICENSE)/i; @@ -13,17 +13,16 @@ module.exports = function(options) { fs.readdir(dir, function(err, list) { list.forEach(function(file) { - var url = urlPath + '/' + file + var url = urlPath + '/' + file; - if (ignoreFiles.test(url)) { - return; - } fs.stat(dir + '/' + file, function(err, stat) { if (stat && stat.isDirectory()) { uploadFiles(dir + '/' + file, urlPath + '/' + file); } else { - uploadFile(url, dir + '/' + file); + if ( shouldProcessPath (url) ){ + uploadFile(url, dir + '/' + file); + } } }); @@ -124,6 +123,17 @@ module.exports = function(options) { ); } + function shouldProcessPath(urlPath) { + if ( urlPath && urlPath.length > 0 ) { + var cleanedUpString = urlPath.substring(1); + var tokens = cleanedUpString.split('/'); + // {component}/test/{testName}/{file} + var extension = path.extname(cleanedUpString); + return tokens && tokens.length > 3 && tokens[1] === 'test' && ( extension === '.html' || extension === '.js' ); + } + return false; + } + console.log('Uploading e2e tests:', options.testId); uploadFiles(inputDir, ''); }; diff --git a/scripts/e2e/e2e.shared.css b/scripts/e2e/e2e.shared.css new file mode 100644 index 0000000000..58d6f248e8 --- /dev/null +++ b/scripts/e2e/e2e.shared.css @@ -0,0 +1,266 @@ +.snapshot body { + /* crop an exact size */ + max-height: 700px !important; +} +.snapshot .scroll-content { + /* disable scrollbars */ + overflow: hidden !important; +} +.snapshot ::-webkit-scrollbar { + display: none; +} +.snapshot *, +.snapshot *:before, +.snapshot *:after { + /* do not allow css animations during snapshot */ + -webkit-transition-duration: 0ms !important; + transition-duration: 0ms !important; +} +.snapshot .button-effect { + display: none !important; +} + +/* hack to create tall scrollable areas for testing using
*/ +div[f] { + display: block; + margin: 15px auto; + max-width: 150px; + height: 150px; + background: blue; +} +div[f]:last-of-type { + background: red; +} +ion-tab:nth-of-type(2) div[f], +.green div[f] { + background: green; + max-width: 250px; + height: 100px; +} +ion-tab:nth-of-type(3) div[f], +.yellow div[f] { + background: yellow; + width: 100px; + height: 50px; +} + + +/******************** + e2e-stacked-tabbars +*********************/ +.e2e-stacked-tabbars ion-tabs { + margin-bottom: 20px; +} + +.e2e-stacked-tabbars ion-tabs, +.e2e-stacked-tabbars ion-tabs .tabbar { + position: relative; + top: auto; + height: auto; + visibility: visible; + opacity: 1; +} + + +/******************** + e2e-loading +*********************/ +.e2e-loading { + position: absolute; + width: 100%; + height: 100%; +} + +.e2e-loading .fixed-spinner svg { + animation: none; +} + +.e2e-loading .custom-spinner-container { + position: relative; + display: inline-block; + box-sizing: border-box; +} + +.e2e-loading .custom-spinner-box { + position: relative; + box-sizing: border-box; + border: 4px solid #000; + width: 60px; + height: 60px; + animation: spin 3s infinite linear; +} + +.e2e-loading .custom-spinner-box:before { + content: ''; + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + box-sizing: border-box; + border: 4px solid #000; + width: 40px; + height: 40px; + animation: pulse 1.5s infinite ease; +} + +.e2e-loading .wp .custom-spinner-box, +.e2e-loading .wp .custom-spinner-box:before { + border-color: #fff; +} + +@-webkit-keyframes pulse { + 50% { + border-width: 20px; + } +} +@keyframes pulse { + 50% { + border-width: 20px; + } +} + +@-webkit-keyframes spin { + 100% { + -webkit-transform: rotate(360deg); + transform: rotate(360deg); + } +} +@keyframes spin { + 100% { + -webkit-transform: rotate(360deg); + transform: rotate(360deg); + } +} + + +/******************** + e2e-loading +*********************/ +.e2e-popover-basic { + position: absolute; + width: 100%; + height: 100%; +} + +.e2e-popover-basic .text-to-change div { + margin: 10px auto; +} + +.e2e-popover-basic ion-row, +.e2e-popover-basic ion-col { + padding: 0; +} + +.e2e-popover-basic .text-button { + padding-left: 0; + text-align: center; + min-height: 20px; + line-height: 18px; +} + +.e2e-popover-basic .text-button .item-inner { + padding-right: 0; +} + +.e2e-popover-basic .text-smaller { + font-size: 12px; +} + +.e2e-popover-basic .ios .text-smaller { + border-right: 1px solid #c8c7cc; +} + +.md.e2e-popover-basic .text-smaller { + border-right: 1px solid #dedede; +} + +.e2e-popover-basic .text-larger { + font-size: 16px; +} + +.e2e-popover-basic .row-dots { + text-align: center; +} + +.ios .e2e-popover-basic .row-dots { + border-bottom: 1px solid #c8c7cc; +} + +.md .e2e-popover-basic .row-dots { + border-bottom: 1px solid #dedede; +} + +.ios .e2e-popover-basic .dot { + border: 1px solid #c8c7cc; +} + +.md .e2e-popover-basic .dot { + border: 1px solid #dedede; +} + +.wp .e2e-popover-basic .dot { + border: 2px solid #ccc; +} + +.hairlines .e2e-popover-basic .text-smaller, +.hairlines .e2e-popover-basic .row-dots, +.hairlines .e2e-popover-basic .dot { + border-width: 0.55px; +} + +.e2e-popover-basic .row-dots .dot { + height: 30px; + width: 30px; + border-radius: 50%; + margin: 10px auto; + position: relative; +} + +.e2e-popover-basic .dot-white { + background-color: rgb(255,255,255); +} + +.e2e-popover-basic .dot-tan { + background-color: rgb(249,241,228); +} + +.e2e-popover-basic .dot-grey { + background-color: rgb(76,75,80); +} + +.e2e-popover-basic .dot-black { + background-color: rgb(0,0,0); +} + +.e2e-popover-basic .dot.selected { + border-width: 2px; + border-color: #327eff; +} + +.e2e-popover-basic .text-athelas { + font-family: "Athelas"; +} + +.e2e-popover-basic .text-charter { + font-family: "Charter"; +} + +.e2e-popover-basic .text-iowan { + font-family: "Iowan"; +} + +.e2e-popover-basic .text-palatino { + font-family: "Palatino"; +} + +.e2e-popover-basic .text-san-francisco { + font-family: "San Francisco"; +} + +.e2e-popover-basic .text-seravek { + font-family: "Seravek"; +} + +.e2e-popover-basic .text-times-new-roman { + font-family: "Times New Roman"; +} diff --git a/scripts/e2e/e2e.template.html b/scripts/e2e/e2e.template.html deleted file mode 100644 index 9725492ad9..0000000000 --- a/scripts/e2e/e2e.template.html +++ /dev/null @@ -1,133 +0,0 @@ - - - - Ionic E2E - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/scripts/e2e/e2e.template.js b/scripts/e2e/e2e.template.js index 34aeb4a0ba..dcf196f45c 100644 --- a/scripts/e2e/e2e.template.js +++ b/scripts/e2e/e2e.template.js @@ -1,7 +1,7 @@ describe('<%= relativePath %>: <%= platform %>', 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/components/<%= relativePath %>/index.html?ionicplatform=<%= platform %>&ionicOverlayCreatedDiff=0&ionicanimate=false&snapshot=true'); }); <%= contents %> diff --git a/scripts/e2e/entry.ts b/scripts/e2e/entry.ts new file mode 100644 index 0000000000..264bdbd47b --- /dev/null +++ b/scripts/e2e/entry.ts @@ -0,0 +1,6 @@ +import { platformBrowser } from '@angular/platform-browser'; +import { enableProdMode } from '@angular/core'; +import { AppModuleNgFactory } from './app-module.ngfactory'; + +enableProdMode(); +platformBrowser().bootstrapModuleFactory(AppModuleNgFactory); diff --git a/scripts/e2e/index.html b/scripts/e2e/index.html new file mode 100644 index 0000000000..ce0e764a29 --- /dev/null +++ b/scripts/e2e/index.html @@ -0,0 +1,51 @@ + + + + Ionic E2E + + + + + + + + + + + + + + + + + + + + diff --git a/scripts/e2e/ionic.ios.dark.scss b/scripts/e2e/ionic.ios.dark.scss deleted file mode 100644 index 88e6bae204..0000000000 --- a/scripts/e2e/ionic.ios.dark.scss +++ /dev/null @@ -1,6 +0,0 @@ - -// For E2E dark theme tests - -@import "../../src/themes/dark.ios.scss"; - -@import "../../src/ionic.ios.scss"; diff --git a/scripts/e2e/ionic.md.dark.scss b/scripts/e2e/ionic.md.dark.scss deleted file mode 100644 index b2cacfb920..0000000000 --- a/scripts/e2e/ionic.md.dark.scss +++ /dev/null @@ -1,6 +0,0 @@ - -// For E2E dark theme tests - -@import "../../src/themes/dark.md.scss"; - -@import "../../src/ionic.md.scss"; diff --git a/scripts/e2e/ionic.wp.dark.scss b/scripts/e2e/ionic.wp.dark.scss deleted file mode 100644 index e76b7786c1..0000000000 --- a/scripts/e2e/ionic.wp.dark.scss +++ /dev/null @@ -1,6 +0,0 @@ - -// For E2E dark theme tests - -@import "../../src/themes/dark.wp.scss"; - -@import "../../src/ionic.wp.scss"; diff --git a/scripts/e2e/ngcConfig.json b/scripts/e2e/ngcConfig.json new file mode 100644 index 0000000000..7d7153d815 --- /dev/null +++ b/scripts/e2e/ngcConfig.json @@ -0,0 +1,18 @@ +{ + "compilerOptions": { + "target": "es5", + "module": "es2015", + "lib": [ + "dom", + "es2015" + ], + "moduleResolution": "node", + "declaration": true, + "noImplicitAny": false, + "emitDecoratorMetadata": true, + "experimentalDecorators": true + }, + "angularCompilerOptions": { + "skipMetadataEmit": true + } +} \ No newline at end of file diff --git a/scripts/e2e/polyfills.js b/scripts/e2e/polyfills.js new file mode 100644 index 0000000000..4109cee608 --- /dev/null +++ b/scripts/e2e/polyfills.js @@ -0,0 +1,5 @@ +import 'core-js/es6'; +import 'core-js/es7/reflect'; +import 'zone.js/dist/zone'; +import 'zone.js/dist/proxy'; +import 'zone.js/dist/long-stack-trace-zone'; diff --git a/scripts/e2e/vendor.js b/scripts/e2e/vendor.js new file mode 100644 index 0000000000..f5e56e98d7 --- /dev/null +++ b/scripts/e2e/vendor.js @@ -0,0 +1,10 @@ +// Angular 2 +import '@angular/platform-browser'; +import '@angular/platform-browser-dynamic'; +import '@angular/common'; +import '@angular/core'; +import '@angular/http'; + +// RxJS +import 'rxjs/add/operator/map'; +import 'rxjs/add/operator/mergeMap'; diff --git a/scripts/e2e/webpack.config.js b/scripts/e2e/webpack.config.js index 540648a2e4..b35348b5eb 100644 --- a/scripts/e2e/webpack.config.js +++ b/scripts/e2e/webpack.config.js @@ -1,30 +1,34 @@ +var entryData = require('./webpackEntryPoints.json'); +var path = require('path') + +entryData["dist/e2e/vendor"] = "./scripts/e2e/vendor"; +entryData["dist/e2e/polyfills"] = "./scripts/e2e/polyfills"; + module.exports = { - externals: [ - { - 'src/ionic': { - commonjs2: 'src/ionic' - }, - '@angular/core': { - commonjs2: ['angular2', 'core'] - }, - '@angular/common': { - commonjs2: ['angular2', 'common'] - }, - '@angular/forms' : { - commonjs2: ['angular2', 'forms'] - }, - '@angular/http': { - commonjs2: ['angular2', 'http'] - }, - '@angular/platform-browser-dynamic': { - commonjs2: ['angular2', 'platform', 'browser'] - }, - } - ], - module: { - loaders: [{ test: /\.ts$/, loader: "awesome-typescript-loader" }] + devtool: "source-map", + + entry: entryData, + + output: { + "path": path.join(__dirname, '../../'), + "filename": "[name].js" }, + resolve: { - extensions: ["", ".js", ".ts"] - } + extensions: ["", ".js", ".json"], + mainFields: ["module", "browser"] + }, + + module: { + loaders: [ + { + test : /\.css$/, + loader : 'file-loader?config=cssLoader' + } + ] + }, + + cssLoader: { + name: 'test/css/[name]-[hash].[ext]' + }, };