chore(): e2e tests from demos, reorganize gulpfile

Conflicts:
	config/protractor.conf.js
	gulpfile.js
This commit is contained in:
Andrew Joslin
2014-05-28 11:42:55 -06:00
parent 7e5b8183b5
commit 1254fcde01
32 changed files with 494 additions and 559 deletions

View File

@@ -5,6 +5,8 @@ module.exports = {
dist: 'dist',
releasePostUrl: fs.readFileSync('config/RELEASE_POST_URL'),
protractorPort: 8765,
banner:
'/*!\n' +
' * Copyright 2014 Drifty Co.\n' +

View File

@@ -7,6 +7,7 @@ var projectBase = path.resolve(__dirname, '../..');
module.exports = function(config) {
config = staticSite(config);
config.set('buildConfig', require('../build.config'));
config.merge('rendering.nunjucks.config.tags', {
variableStart: '{$',

View File

@@ -14,10 +14,22 @@ module.exports = {
process: function(docs, config) {
var contentsFolder = config.rendering.contentsFolder;
var assetOutputPath = path.join(contentsFolder, '${component}/${name}/${fileName}');
var assetOutputPath = '${component}/${name}/${fileName}';
var pages = [];
var templates = {
'.scenario.js': 'scenario.template.js'
};
var transform = {
'.scenario.js': function(doc) {
doc.url = 'http://localhost:' + config.get('buildConfig.protractorPort') +
'/' + config.versionData.current.folder +
'/' + _.template(assetOutputPath, _.assign({},doc,{fileName:''}));
return doc;
}
};
var demos = _(docs)
.filter('yaml')
.groupBy(function(doc) {
@@ -41,8 +53,10 @@ module.exports = {
doc.contents = fragment.contents;
doc.extension = doc.fileType.replace(/^\./,'');
doc.template = 'asset.contents.template',
doc.outputPath = _.template(assetOutputPath, doc);
doc.template = templates[doc.fileType] || 'asset.contents.template',
doc.outputPath = path.join(contentsFolder, _.template(assetOutputPath, doc));
doc = (transform[doc.fileType] || _.identity)(doc);
demoData.files.push(doc);
pages.push(doc);
@@ -50,19 +64,29 @@ module.exports = {
var firstDoc = demoData.files[0];
var indexOutputPath = _.template(assetOutputPath, _.assign({}, firstDoc, {
fileName: 'index.html'
}));
var appOutputPath = _.template(assetOutputPath, _.assign({}, firstDoc, {
fileName: 'index-ionic-demo-app.js'
}, demoData));
var indexOutputPath = path.join(
contentsFolder,
_.template(assetOutputPath, _.assign({}, firstDoc, {
fileName: 'index.html'
}))
);
var appOutputPath = path.join(
contentsFolder,
_.template(assetOutputPath, _.assign({}, firstDoc, {
fileName: 'index-ionic-demo-app.js'
}, demoData))
);
demoData.files = _.groupBy(demoData.files, 'extension');
demoData.id = firstDoc.id;
demoData.name = firstDoc.name;
demoData.component = firstDoc.component;
demoData.href = '/' + _.template(assetOutputPath, _.assign({}, firstDoc, { fileName: '' }));
demoData.href = path.join(
'/',
contentsFolder,
_.template(assetOutputPath, _.assign({}, firstDoc, { fileName: '' }))
);
pages.push({
template: 'index.template.html',

View File

@@ -1,9 +1,11 @@
var jsYaml = require('js-yaml');
var path = require('canonical-path');
var YAML_LINE_REGEX = /---+/;
var FILE_PATTERN_REGEX = /\.(scenario.js|js|html|css)$/;
module.exports = {
pattern: /\.*$/,
pattern: FILE_PATTERN_REGEX,
processFile: function(filePath, contents, basePath) {
contents = contents.trim();
@@ -26,7 +28,7 @@ module.exports = {
var yamlJson = jsYaml.safeLoad(yamlContents);
return [{
fileType: path.extname(filePath),
fileType: filePath.match(FILE_PATTERN_REGEX)[0].toString(),
file: filePath,
basePath: basePath,
contents: contents,

View File

@@ -0,0 +1,9 @@
describe('{$ doc.id $}', function() {
it('should init', function() {
browser.get('{$ doc.url $}');
});
{$ doc.contents $}
});

87
config/gulp-tasks/test.js Normal file
View File

@@ -0,0 +1,87 @@
var cp = require('child_process');
var connect = require('connect');
var http = require('http');
var buildConfig = require('../build.config');
var karma = require('karma').server;
var karmaConf = require('../karma.conf.js');
var karmaSauceConf = require('../karma-sauce.conf.js');
module.exports = function(gulp, argv) {
/*
* Connect to Saucelabs
*/
var sauceInstance;
gulp.task('sauce-connect', function(done) {
require('sauce-connect-launcher')({
username: process.env.SAUCE_USER,
accessKey: process.env.SAUCE_KEY,
verbose: true,
tunnelIdentifier: process.env.TRAVIS_BUILD_NUMBER
}, function(err, instance) {
if (err) return done('Failed to launch sauce connect!');
sauceInstance = instance;
done();
});
});
gulp.task('sauce-disconnect', function(done) {
sauceInstance && sauceInstance.close(done) || done();
});
/*
* Karma
*/
gulp.task('karma', function(done) {
karmaConf.singleRun = true;
argv.browsers && (karmaConf.browsers = argv.browsers.trim().split(','));
argv.reporters && (karmaConf.reporters = argv.reporters.trim().split(','));
karma.start(karmaConf, done);
});
gulp.task('karma-watch', function(done) {
karmaConf.singleRun = false;
karma.start(karmaConf, done);
});
gulp.task('karma-sauce', ['sauce-connect'], function(done) {
return karma.start(karmaSauceConf, function() {
sauceDisconnect(done);
});
});
/*
* Protractor Snapshot Tests
*/
var connectServer;
gulp.task('snapshot-server', function() {
var app = connect().use(connect.static(__dirname + '/../../dist/ionic-demo'));
connectServer = http.createServer(app).listen(buildConfig.protractorPort);
});
gulp.task('snapshot', ['snapshot-server'], function(done) {
var uuid = require('node-uuid');
return protractor(done, [
'config/protractor.conf.js',
'--test_id=' + uuid.v4()
]);
});
gulp.task('snapshot-sauce', ['sauce-connect', 'snapshot-server'], function(done) {
return protractor(done, ['config/protractor-sauce.conf.js']);
});
function protractor(done, args) {
cp.spawn('protractor', args, { stdio: 'inherit' })
.on('exit', function(code) {
connectServer && connectServer.close();
if (code) return done('Protector test(s) failed. Exit code: ' + code);
done();
});
}
};

View File

@@ -1,7 +1,7 @@
var _ = require('lodash');
var shared = require('./karma.conf.js');
module.exports = _.assign(shared, {
module.exports = _.assign({}, shared, {
reporters: ['dots'],
sauceLabs: {
testName: 'Ionic unit tests',

View File

@@ -1,9 +1,10 @@
var buildConfig = require('./build.config');
// An example configuration file.
exports.config = {
// Spec patterns are relative to the location of the spec file. They may
// include glob patterns.
specs: ['../test/e2e/**/*.js'],
specs: ['../dist/ionic-demo/nightly/**/*.scenario.js'],
// Options to be passed to Jasmine-node.
jasmineNodeOpts: {
@@ -11,7 +12,7 @@ exports.config = {
defaultTimeoutInterval: 120000
},
baseUrl: 'http://localhost:8765',
baseUrl: 'http://localhost:' + buildConfig.protractorPort,
//local build: chrome
chromeOnly: true,

View File

@@ -0,0 +1,16 @@
---
name: simple
component: ionCheckbox
---
it('should uncheck 1st and check 2nd checkbox by clicking its label', function(){
var ele = element.all(by.css('label.item-checkbox'));
ele.get(0).click();
ele.get(1).click();
});
it('should check 1st and uncheck 2nd checkbox by clicking its label', function(){
var ele = element.all(by.css('label.item-checkbox'));
ele.get(0).click();
ele.get(1).click();
});

View File

@@ -0,0 +1,23 @@
---
name: contacts
component: collectionRepeat
---
it('should scroll to the bottom', function(){
var ele = element(by.css('.bar-header .button'));
ele.click();
});
it('should scroll to the top', function(){
var ele = element(by.css('.bar-header'));
ele.click();
});
it('should filter by juan', function(){
var ele = element(by.model('search'));
ele.sendKeys('juan');
});
it('should clear search', function(){
var ele = element(by.css('.bar-header .input-button'));
ele.click();
});

View File

@@ -0,0 +1,24 @@
---
name: simple
component: ionFooterBar
---
it('should show subfooter', function(){
var ele = element.all(by.css('.toggle'));
ele.get(0).click();
});
it('should hide subfooter', function(){
var ele = element.all(by.css('.toggle'));
ele.get(0).click();
});
it('should hide footer', function(){
var ele = element.all(by.css('.toggle'));
ele.get(1).click();
});
it('should show footer', function(){
var ele = element.all(by.css('.toggle'));
ele.get(1).click();
});

View File

@@ -0,0 +1,24 @@
---
name: simple
component: ionHeaderBar
---
it('should show subheader', function(){
var ele = element.all(by.css('.toggle'));
ele.get(0).click();
});
it('should hide subheader', function(){
var ele = element.all(by.css('.toggle'));
ele.get(0).click();
});
it('should hide header', function(){
var ele = element.all(by.css('.toggle'));
ele.get(1).click();
});
it('should show header', function(){
var ele = element.all(by.css('.toggle'));
ele.get(1).click();
});

View File

@@ -0,0 +1,4 @@
---
name: forever
component: ionInfiniteScroll
---

View File

@@ -0,0 +1,14 @@
---
name: animated
component: ionList
---
it('should add item below Item 0', function(){
var ele = element.all(by.css('.list .button'));
ele.get(0).click();
});
it('should remove Item 0', function(){
var ele = element.all(by.css('.list .button'));
ele.get(1).click();
});

View File

@@ -0,0 +1,24 @@
---
name: reorderDelete
component: ionList
---
it('should show reorder icons', function(){
var ele = element.all(by.css('.bar-header .button'));
ele.get(1).click();
});
it('should hide reorder icons', function(){
var ele = element.all(by.css('.bar-header .button'));
ele.get(1).click();
});
it('should show delete icons', function(){
var ele = element.all(by.css('.bar-header .button'));
ele.get(0).click();
});
it('should hide delete icons', function(){
var ele = element.all(by.css('.bar-header .button'));
ele.get(0).click();
});

View File

@@ -0,0 +1,4 @@
---
name: chooseOne
component: ionRadio
---

View File

@@ -0,0 +1,4 @@
---
name: refreshList
component: ionRefresher
---

View File

@@ -0,0 +1,24 @@
---
name: navWithMenu
component: ionSideMenus
---
it('should nav to Search from left menu', function(){
var ele = element.all(by.css('button[menu-toggle="left"]'));
ele.get(0).click();
browser.sleep(500).then(function(){
var itemEle = element.all(by.css('ion-side-menu[side="left"] a'));
itemEle.get(0).click();
});
});
it('should nav to Browse from left menu', function(){
var ele = element.all(by.css('button[menu-toggle="left"]'));
ele.get(0).click();
browser.sleep(500).then(function(){
var itemEle = element.all(by.css('ion-side-menu[side="left"] a'));
itemEle.get(1).click();
});
});

View File

@@ -0,0 +1,23 @@
---
name: simple
component: ionSideMenus
---
it('should show left menu', function(){
var ele = element.all(by.css('.bar-header .button'));
ele.get(0).click();
});
it('should hide left menu by clicking header button', function(){
var ele = element.all(by.css('.bar-header .button'));
ele.get(0).click();
});
it('should show left menu', function(){
var ele = element.all(by.css('.bar-header .button'));
ele.get(0).click();
});
it('should hide left menu by close menu item', function(){
var ele = element.all(by.css('ion-side-menu[side="left"] a'));
ele.get(0).click();
});

View File

@@ -0,0 +1,33 @@
---
name: appIntro
component: ionSlideBox
---
it('should go to slide 2', function(){
var ele = element(by.css('.right-buttons .button'));
ele.click();
});
it('should go to slide 1', function(){
var ele = element(by.css('.left-buttons .button'));
ele.click();
});
it('should go to slide 2', function(){
var ele = element(by.css('.right-buttons .button'));
ele.click();
});
it('should go to slide 3', function(){
var ele = element(by.css('.right-buttons .button'));
ele.click();
});
it('should go to main app', function(){
var ele = element(by.css('.right-buttons .button'));
ele.click();
});
it('should start over', function(){
var ele = element(by.css('ion-nav-view .button'));
ele.click();
});

View File

@@ -0,0 +1,63 @@
---
name: tabsAndNav
component: ionTabs
---
it('should go to page 2 in Home tab', function(){
var ele = element.all(by.css('ion-nav-view[name="home-tab"] .button'));
ele.get(0).click();
});
it('should go to page 3 in Home tab', function(){
var ele = element.all(by.css('ion-nav-view[name="home-tab"] .button'));
ele.get(1).click();
});
it('should go to About tab', function(){
var ele = element.all(by.css('.tabs a'));
ele.get(1).click();
});
it('should go to page 2 in About tab', function(){
var ele = element.all(by.css('ion-nav-view[name="about-tab"] .button'));
ele.get(0).click();
});
it('should go to Contact tab', function(){
var ele = element.all(by.css('.tabs a'));
ele.get(2).click();
});
it('should go to About tab and still be at page 2', function(){
var ele = element.all(by.css('.tabs a'));
ele.get(1).click();
});
it('should go to Home tab and still be at page 3', function(){
var ele = element.all(by.css('.tabs a'));
ele.get(0).click();
});
it('should go back to page 2 in Home tab', function(){
var ele = element(by.css('ion-nav-back-button'));
ele.click();
});
it('should go back to page 1 in Home tab', function(){
var ele = element(by.css('ion-nav-back-button'));
ele.click();
});
it('should go to About tab and still be at page 2', function(){
var ele = element.all(by.css('.tabs a'));
ele.get(1).click();
});
it('should go back to page 1 in About tab', function(){
var ele = element(by.css('ion-nav-back-button'));
ele.click();
});
it('should go to Home tab and still be at page 1', function(){
var ele = element.all(by.css('.tabs a'));
ele.get(0).click();
});

View File

@@ -0,0 +1,24 @@
---
name: takeAction
component: $ionicActionSheet
---
it('should open up actionsheet', function(){
var ele = element(by.css('.button'));
ele.click();
});
it('should close when clicking backdrop', function(){
var ele = element(by.css('.action-sheet-backdrop'));
ele.click();
});
it('should open up actionsheet again', function(){
var ele = element(by.css('.button'));
ele.click();
});
it('should click the share button', function(){
var ele = element.all(by.css('.action-sheet-group .button'));
ele.get(0).click();
});

View File

@@ -0,0 +1,4 @@
---
name: complete
component: $ionicLoading
---

View File

@@ -0,0 +1,36 @@
---
name: popping
component: $ionicPopup
---
it('should open confirm popup', function(){
var ele = element.all(by.css('[ng-click="showConfirm()"]'));
ele.get(0).click();
});
it('should cancel confirm popup', function(){
var ele = element.all(by.css('.popup-buttons .button'));
ele.get(0).click();
});
it('should open prompt popup and enter input', function(){
var ele = element.all(by.css('[ng-click="showPrompt()"]'));
ele.get(0).click();
ele = element(by.model('data.response'));
ele.sendKeys('Waffles');
});
it('should close prompt popup by clicking OK', function(){
var ele = element.all(by.css('.popup-buttons .button'));
ele.get(1).click();
});
it('should open alert popup', function(){
var ele = element.all(by.css('[ng-click="showAlert()"]'));
ele.get(0).click();
});
it('should close alert popup', function(){
var ele = element.all(by.css('.popup-buttons .button'));
ele.get(0).click();
});

View File

@@ -1,5 +1,4 @@
var gulp = require('gulp');
var karma = require('karma').server;
var path = require('canonical-path');
var pkg = require('./package.json');
var semver = require('semver');
@@ -10,7 +9,6 @@ var argv = require('minimist')(process.argv.slice(2));
var _ = require('lodash');
var buildConfig = require('./config/build.config.js');
var changelog = require('conventional-changelog');
var connect = require('connect');
var dgeni = require('dgeni');
var es = require('event-stream');
var htmlparser = require('htmlparser2');
@@ -21,7 +19,6 @@ var mkdirp = require('mkdirp');
var twitter = require('node-twitter-api');
var yaml = require('js-yaml');
var http = require('http');
var cp = require('child_process');
var fs = require('fs');
@@ -48,6 +45,11 @@ if (IS_RELEASE_BUILD) {
);
}
/**
* Load Test Tasks
*/
require('./config/gulp-tasks/test')(gulp, argv);
if (argv.dist) {
buildConfig.dist = argv.dist;
}
@@ -406,79 +408,6 @@ gulp.task('docs-index', function() {
});
});
gulp.task('sauce-connect', sauceConnect);
gulp.task('cloudtest', ['protractor-sauce'], function(cb) {
sauceDisconnect(cb);
});
gulp.task('karma', function(cb) {
var config = require('./config/karma.conf.js');
config.singleRun = true;
if (argv.browsers) {
config.browsers = argv.browsers.trim().split(',');
}
if (argv.reporters) {
config.reporters = argv.reporters.trim().split(',');
}
return karma.start(config, cb);
});
gulp.task('karma-watch', function(cb) {
return karma.start(_.assign(require('./config/karma.conf.js'), {singleRun: false}), cb);
});
gulp.task('karma-sauce', ['sauce-connect'], function(cb) {
return karma.start(require('./config/karma-sauce.conf.js'), function() {
sauceDisconnect(cb);
});
});
var connectServer;
gulp.task('connect-server', function() {
var app = connect().use(connect.static(__dirname));
connectServer = http.createServer(app).listen(8765);
});
gulp.task('protractor', ['connect-server'], function(cb) {
return protractor(cb, ['config/protractor.conf.js']);
});
gulp.task('protractor-sauce', ['sauce-connect', 'connect-server'], function(cb) {
return protractor(cb, ['config/protractor-sauce.conf.js']);
});
function pad(n) {
if (n<10) { return '0' + n; }
return n;
}
function protractor(cb, args) {
cp.spawn('protractor', args, { stdio: 'inherit' })
.on('exit', function(code) {
connectServer && connectServer.close();
if (code) return cb('Protector test(s) failed. Exit code: ' + code);
cb();
});
}
var sauceInstance;
function sauceConnect(cb) {
require('sauce-connect-launcher')({
username: process.env.SAUCE_USER,
accessKey: process.env.SAUCE_KEY,
verbose: true,
tunnelIdentifier: process.env.TRAVIS_BUILD_NUMBER
}, function(err, instance) {
if (err) return cb('Failed to launch sauce connect!');
sauceInstance = instance;
cb();
});
}
function sauceDisconnect(cb) {
if (sauceInstance) {
return sauceInstance.close(cb);
}
cb();
}
function notContains(disallowed) {
disallowed = disallowed || [];
@@ -507,3 +436,7 @@ function notContains(disallowed) {
return match !== null ? match.index + match[1].length : -1;
}
}
function pad(n) {
if (n<10) { return '0' + n; }
return n;
}

View File

@@ -45,9 +45,7 @@
"node-twitter-api": "^1.2.2",
"chalk": "^0.4.0",
"jshint-summary": "^0.3.0",
"js-yaml": "^3.0.2",
"jasmine-node": "^1.14.3",
"q": "^1.0.1",
"cpr": "^0.2.0",
"dgeni": "^0.3.0",
"dgeni-packages": "^0.9.3",

View File

@@ -1,366 +0,0 @@
<html ng-app="navState">
<head>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no">
<title>navViews and ion-tabs w/ nested navViews</title>
<link rel="stylesheet" href="../../../dist/css/ionic.css">
<script src="../../../dist/js/angular/angular.js"></script>
<script src="../../../dist/js/angular/angular-animate.js"></script>
<script src="../../../dist/js/angular/angular-sanitize.js"></script>
<script src="../../../dist/js/angular-ui/angular-ui-router.js"></script>
<script src="../../../dist/js/ionic.js"></script>
<script src="../../../dist/js/ionic-angular.js"></script>
</head>
<body>
<div ng-controller="AppCtrl">
<ion-nav-bar animation="nav-title-slide-ios7"
type="bar-positive">
<ion-nav-back-button class="button-icon">
<i class="icon ion-arrow-left-c"></i> Back
</ion-nav-back-button>
</ion-nav-bar>
<ion-nav-view animation="slide-left-right"></ion-nav-view>
</div>
<script id="sign-in.html" type="text/ng-template">
<ion-view title="Sign-In">
<ion-nav-buttons side="left">
<button class="button button-icon icon ion-home">
Home
</button>
</ion-nav-buttons>
<ion-nav-buttons side="right">
<button class="button button-icon icon ion-navicon">
</button>
</ion-nav-buttons>
<ion-content has-header="true">
<div class="list">
<label class="item item-input">
<span class="input-label">Username</span>
<input type="text" ng-model="user.username">
</label>
<label class="item item-input">
<span class="input-label">Password</span>
<input type="password" ng-model="user.password">
</label>
</div>
<div class="padding">
<button id="sign-in-button" class="button button-block button-positive" ng-click="signIn(user)">
Sign-In
</button>
<p class="text-center">
<a href="#/sign-in">Sign-In</a> -
<a href="#/forgot-password">Forgot password</a> -
<a ui-sref="contact">Contact</a>
</p>
<p>
Current View: {{ $viewHistory.currentView }}<br>
Back View: {{ $viewHistory.backView }}<br>
Forward View: {{ $viewHistory.forwardView }}
</p>
</div>
</ion-content>
</ion-view>
</script>
<script id="forgot-password.html" type="text/ng-template">
<ion-view title="Forgot Password" hide-nav-bar="true">
<ion-content has-header="true" padding="true">
<p>This ion-view hides the nav bar using the hideNavBar attribute.</p>
<p>
<button ng-click="hideNavBar()">Hide Nav Bar</button>
<button ng-click="showNavBar()">Show Nav Bar</button>
</p>
<p>
<button ng-click="clearViewHistory()">Clear View History</button>
</p>
<p class="text-center">
<a href="#/sign-in">Sign-In</a> -
<a href="#/forgot-password">Forgot password</a> -
<a href="#/contact">Contact</a>
</p>
<p>
Current View: {{ $viewHistory.currentView }}<br>
Back View: {{ $viewHistory.backView }}<br>
Forward View: {{ $viewHistory.forwardView }}
</p>
</ion-content>
</ion-view>
</script>
<script id="contact.html" type="text/ng-template">
<ion-view hide-back-button="true">
<ion-content has-header="true" padding="true">
<p>The views title is blank on purpose.</p>
<p>The hideBackButton attribute is "true" for this view.</p>
<p>@drifty</p>
<p class="text-center">
<a href="#/sign-in">Sign-In</a> -
<a href="#/forgot-password">Forgot password</a> -
<a href="#/contact">Contact</a>
</p>
<p>
Current View: {{ $viewHistory.currentView }}<br>
Back View: {{ $viewHistory.backView }}<br>
Forward View: {{ $viewHistory.forwardView }}
</p>
</ion-content>
</ion-view>
</script>
<script id="tabs.html" type="text/ng-template">
<ion-tabs tabs-style="tabs-icon-top" tabs-type="tabs-positive">
<ion-tab title="Automobiles" icon="ion-model-s" href="#/tabs/autos">
<ion-nav-view name="auto-nav-view"></ion-nav-view>
</ion-tab>
<ion-tab title="Add" icon="ion-plus-circled" href="#/tabs/add-auto">
<ion-nav-view name="add-autos-nav-view"></ion-nav-view>
</ion-tab>
<ion-tab title="About" icon="ion-ios7-world" ui-sref="tabs.about">
<ion-nav-view name="about-nav-view"></ion-nav-view>
</ion-tab>
<ion-tab title="Sign-Out" icon="ion-log-out" href="#/sign-in">
</ion-tab>
</ion-tabs>
</script>
<script id="auto-list.html" type="text/ng-template">
<ion-view title="Auto List">
<ion-content has-header="true" has-tabs="true">
<ion-list>
<ion-item ng-repeat="auto in autos" ng-href="#/tabs/autos/{{ $index }}">
{{ auto.year }} {{ auto.make }} {{ auto.model }}
</ion-item>
</ion-list>
<p>
<button ng-click="testStateGo()">Test State Go</button>
</p>
<p>
Current View: {{ $viewHistory.currentView }}<br>
Back View: {{ $viewHistory.backView }}<br>
Forward View: {{ $viewHistory.forwardView }}
</p>
</ion-content>
</ion-view>
</script>
<script id="auto-detail.html" type="text/ng-template">
<ion-view title="Auto Details">
<ion-content has-header="true" has-tabs="true" padding="true">
<h2>{{ auto.year }} {{ auto.make }} {{ auto.model }}</h2>
<p ng-bind="auto.desc"></p>
<p><a class="button" ng-href="{{ auto.url }}">Read More</a></p>
<ul>
<li>
<a ng-href="#/tabs/autos/0" class="ng-binding" href="#/tabs/autos/0">1936 Cord 810</a>
</li><li>
<a ng-href="#/tabs/autos/1" class="ng-binding" href="#/tabs/autos/1">1981 DeLorean DMC-12</a>
</li><li>
<a ng-href="#/tabs/autos/2" class="ng-binding" href="#/tabs/autos/2">1933 Duesenberg Model SJ</a>
</li><li>
<a ng-href="#/tabs/autos/3" class="ng-binding" href="#/tabs/autos/3">1951 Hudson Hornet</a>
</li><li>
<a ng-href="#/tabs/autos/4" class="ng-binding" href="#/tabs/autos/4">1965 Shelby Cobra</a>
</li><li>
<a ng-href="#/tabs/autos/5" class="ng-binding" href="#/tabs/autos/5">2008 Tesla Roadster</a>
</li><li>
<a ng-href="#/tabs/autos/6" class="ng-binding" href="#/tabs/autos/6">1948 Tucker 48</a>
</li>
</ul>
<p>
<button ng-click="hideBackButton()">Hide Back Button</button>
<button ng-click="showBackButton()">Show Back Button</button>
</p>
<p><a class="button" href="#/tabs/autos">Auto List</a></p>
<p>
Current View: {{ $viewHistory.currentView }}<br>
Back View: {{ $viewHistory.backView }}<br>
Forward View: {{ $viewHistory.forwardView }}
</p>
</ion-content>
</ion-view>
</script>
<script id="add-auto.html" type="text/ng-template">
<ion-view title="Add Auto">
<ion-content has-header="true" has-tabs="true">
<div class="list">
<label class="item item-input">
<input type="text" placeholder="Make">
</label>
<label class="item item-input">
<input type="text" placeholder="Model">
</label>
<label class="item item-input">
<input type="text" placeholder="Year">
</label>
<label class="item item-input">
<textarea placeholder="Description"></textarea>
</label>
</div>
<div class="padding">
<p>
Current View: {{ $viewHistory.currentView }}<br>
Back View: {{ $viewHistory.backView }}<br>
Forward View: {{ $viewHistory.forwardView }}
</p>
</div>
</ion-content>
</ion-view>
</script>
<script id="about.html" type="text/ng-template">
<ion-view title="About">
<ion-content has-header="true" has-tabs="true" padding="true">
<h3>About this app!</h3>
<p>
Current View: {{ $viewHistory.currentView }}<br>
Back View: {{ $viewHistory.backView }}<br>
Forward View: {{ $viewHistory.forwardView }}
</p>
</ion-content>
</ion-view>
</script>
<script>
angular.module('navState', ['ionic'])
.config(function($stateProvider, $urlRouterProvider) {
$stateProvider
.state('signin', {
url: "/sign-in",
templateUrl: "sign-in.html",
controller: 'SignInCtrl'
})
.state('forgotpassword', {
url: "/forgot-password",
templateUrl: "forgot-password.html",
controller: 'ForgotPasswordCtrl'
})
.state('contact', {
url: "/contact",
templateUrl: "contact.html"
})
.state('tabs', {
url: "/tabs",
abstract: true,
templateUrl: "tabs.html"
})
.state('tabs.autolist', {
url: "/autos",
views: {
'auto-nav-view': {
templateUrl: "auto-list.html",
controller: 'AutoListCtrl'
}
}
})
.state('tabs.addauto', {
url: "/add-auto",
views: {
'add-autos-nav-view': {
templateUrl: "add-auto.html",
controller: 'AutoAddCtrl'
}
}
})
.state('tabs.autodetail', {
url: "/autos/:id",
views: {
'auto-nav-view': {
templateUrl: "auto-detail.html",
controller: 'AutoDetailCtrl'
}
}
})
.state('tabs.about', {
url: "/about",
views: {
'about-nav-view': {
templateUrl: "about.html"
}
}
});
$urlRouterProvider.otherwise("/sign-in");
})
.controller('SignInCtrl', function($scope, $state) {
$scope.signIn = function(user) {
$state.go('tabs.autolist');
};
})
.controller('ForgotPasswordCtrl', function($ionicViewService, $rootScope, $scope, $state) {
$scope.clearViewHistory = function() {
$ionicViewService.clearHistory();
};
$scope.hideNavBar = function() {
$rootScope.$broadcast('viewState.showNavBar', false);
};
$scope.showNavBar = function() {
$rootScope.$broadcast('viewState.showNavBar', true);
};
})
.controller('AutoListCtrl', function($scope, $state) {
$scope.autoListData = "AutoListCtrl Data";
$scope.testStateGo = function() {
var toParams = { id: 4 };
$state.go('tabs.autodetail', toParams);
};
})
.controller('AutoDetailCtrl', function($scope, $state, $stateParams) {
$scope.autoDetailData = "AutoDetailCtrl Data";
$scope.hideBackButton = function() {
$scope.$emit('viewState.showBackButton', false);
};
$scope.showBackButton = function() {
$scope.$emit('viewState.showBackButton', true);
};
$scope.auto = $scope.autos[$stateParams.id];
})
.controller('AutoAddCtrl', function($scope) {
$scope.newAutoData = "AutoAddCtrl Data";
})
.controller('AppCtrl', function($scope, $state) {
$scope.autos = [
{ make: 'Cord', model: '810', year: '1936', desc: 'Styled by Gordon M. Buehrig, it featured front-wheel drive and independent front suspension;[ the front drive enabled the 810 to be so low, runningboards were unnecessary. Powered by a 4,739 cc (289 cu in) Lycoming V8 of the same 125 hp (93 kW) as the L-29, The 810 had a four-speed electrically-selected semi-automatic transmission, among other innovative features.', url: 'http://en.wikipedia.org/wiki/Cord_810/812' },
{ make: 'DeLorean', model: 'DMC-12', year: '1981', desc: 'The DeLorean DMC-12 is a sports car manufactured by John DeLorean\'s DeLorean Motor Company for the American market in 198182. Featuring gull-wing doors with a fiberglass "underbody", to which non-structural brushed stainless steel panels are affixed, the car became iconic for its appearance as a modified time machine in the Back to the Future film trilogy.', url: 'http://en.wikipedia.org/wiki/DeLorean_DMC-12' },
{ make: 'Duesenberg', model: 'Model SJ', year: '1933', desc: 'The rare supercharged Model J version, with 320 hp (239 kW) was also created by Fred Duesenberg and introduced in May 1932, only 36 units were built. Special-bodied models, such as the later "Mormon Meteor" chassis, achieved an average speed of over 135 mph (217 km/h)[17] and a one-hour average of over 152 mph (245 km/h) at Bonneville Salt Flats, Utah.', url: 'http://en.wikipedia.org/wiki/Duesenberg_Model_J' },
{ make: 'Hudson', model: 'Hornet', year: '1951', desc: 'The Hornet, introduced for the 1951 model year, was based on Hudson\'s "step-down" design that was first seen in the 1948 model year on the Commodore. The design merged body and chassis frame into a single structure, with the floor pan recessed between the car\'s chassis rails instead of sitting on top of them. Thus one "stepped down" into a Hudson. The step-down chassis\'s "lower center of gravity...was both functional and stylish. The car not only handled well, but treated its six passengers to a sumptuous ride. The low-slung look also had a sleekness about it that was accentuated by the nearly enclosed rear wheels.', url: 'http://en.wikipedia.org/wiki/Hudson_Hornet' },
{ make: 'Shelby', model: 'Cobra', year: '1965', desc: 'Shelby wanted the AC Cobras to be "Corvette-Beaters" and at nearly 500 lb (227 kg) less than the Chevrolet Corvette, the lightweight roadster accomplished that goal at Riverside International Raceway on 2 February 1963. Driver Dave MacDonald piloted CSX2026 past a field of Corvettes, Jaguars, Porsches, and Maseratis and recorded the Cobra\'s historic first-ever victory.', url: 'http://en.wikipedia.org/wiki/Shelby_Cobra' },
{ make: 'Tesla', model: 'Roadster', year: '2008', desc: 'Tesla Motors\' first production vehicle, the Tesla Roadster, was an all-electric sports car. The Roadster was the first highway-capable all-electric vehicle in serial production for sale in the United States in the modern era. The Roadster was also the first production automobile to use lithium-ion battery cells and the first production BEV (all-electric) to travel more than 200 miles (320 km) per charge.', url: 'http://en.wikipedia.org/wiki/Tesla_Roadster' },
{ make: 'Tucker', model: '48', year: '1948', desc: 'The Tucker 48 (named after its model year) was an advanced automobile conceived by Preston Tucker and briefly produced in Chicago in 1948. Only 51 cars were made before the company folded on March 3, 1949, due to negative publicity initiated by the news media, a Securities and Exchange Commission investigation and a heavily publicized stock fraud trial (in which allegations were proven baseless in court with a full acquittal). Speculation exists that the Big Three automakers and Michigan senator Homer S. Ferguson also had a role in the Tucker Corporation\'s demise.', url: 'http://en.wikipedia.org/wiki/Tucker_Torpedo' },
];
});
</script>
</body>
</html>

View File

@@ -1,100 +0,0 @@
describe('viewState', function() {
beforeEach(function() {
browser.get('http://localhost:8765/test/e2e/viewState/test.html');
});
function navTitle() {
return element(by.css('h1.title'));
}
function navButtons(dir) {
return dir == 'back' ?
element(by.css('.bar-header .back-button')) :
element(by.css('.bar-header .'+dir+'-buttons .button'));
}
it('navbar with multiple histories', function() {
expect(navTitle().getText()).toBe('Sign-In');
expect(navButtons('back').getAttribute('class')).toContain('hide');
expect(navButtons('left').getText()).toEqual('Home');
expect(navButtons('left').getAttribute('class')).toContain('ion-home');
expect(navButtons('right').getText()).toEqual('');
expect(navButtons('right').getAttribute('class')).toContain('ion-navicon');
browser.takeScreenshot().then(function(png) {
console.log(png);
});
element(by.id('sign-in-button')).click();
expect(navTitle().getText()).toBe('Auto List');
expect(navButtons('back').getAttribute('class')).toContain('hide');
expect(navButtons('left').isPresent()).toBe(false);
expect(navButtons('right').isPresent()).toBe(false);
element(by.css('[href="#/tabs/autos/3"]')).click();
expect(navTitle().getText()).toBe('Auto Details');
expect(navButtons('back').getAttribute('class')).not.toContain('hide');
expect(navButtons('back').getText()).toEqual('Back');
expect(element(by.css('.back-button i')).getAttribute('class')).toContain('ion-arrow-left-c');
expect(navButtons('left').isPresent()).toBe(false);
expect(navButtons('right').isPresent()).toBe(false);
element(by.css('.tabs .tab-item:nth-of-type(2)')).click();
expect(navTitle().getText()).toBe('Add Auto');
expect(navButtons('back').getAttribute('class')).toContain('hide');
expect(navButtons('left').isPresent()).toBe(false);
expect(navButtons('right').isPresent()).toBe(false);
element(by.css('.tabs .tab-item:nth-of-type(1)')).click();
expect(navTitle().getText()).toBe('Auto Details');
expect(navButtons('back').getAttribute('class')).not.toContain('hide');
expect(navButtons('left').isPresent()).toBe(false);
expect(navButtons('right').isPresent()).toBe(false);
navButtons('back').click();
expect(navTitle().getText()).toBe('Auto List');
expect(navButtons('back').getAttribute('class')).toContain('hide');
expect(navButtons('left').isPresent()).toBe(false);
expect(navButtons('right').isPresent()).toBe(false);
element(by.css('[href="#/tabs/autos/3"]')).click();
expect(navTitle().getText()).toBe('Auto Details');
expect(navButtons('back').getAttribute('class')).not.toContain('hide');
expect(navButtons('left').isPresent()).toBe(false);
expect(navButtons('right').isPresent()).toBe(false);
element(by.css('.tabs a:nth-of-type(1)')).click();
expect(navTitle().getText()).toBe('Auto List');
expect(navButtons('back').getAttribute('class')).toContain('hide');
expect(navButtons('left').isPresent()).toBe(false);
expect(navButtons('right').isPresent()).toBe(false);
element(by.css('[href="#/tabs/autos/3"]')).click();
expect(navTitle().getText()).toBe('Auto Details');
expect(navButtons('back').getAttribute('class')).not.toContain('hide');
expect(navButtons('left').isPresent()).toBe(false);
expect(navButtons('right').isPresent()).toBe(false);
element(by.css('.tabs a:nth-of-type(4)')).click();
expect(navTitle().getText()).toBe('Sign-In');
expect(navButtons('back').getAttribute('class')).toContain('hide');
expect(navButtons('left').getText()).toEqual('Home');
expect(navButtons('left').getAttribute('class')).toContain('ion-home');
expect(navButtons('right').getText()).toEqual('');
expect(navButtons('right').getAttribute('class')).toContain('ion-navicon');
element(by.id('sign-in-button')).click();
expect(navTitle().getText()).toBe('Auto List');
expect(navButtons('back').getAttribute('class')).toContain('hide');
});
});