Commit f7c1860b5bb9ed4bde0cd7198931fa2f48adb05d

Authored by tmcdeveloper
1 parent b2b910457f
Exists in master

add basic acceptance tests for signup and login with Chimp

1 # Meteor packages used by this project, one per line. 1 # Meteor packages used by this project, one per line.
2 # Check this file (and the other files in this directory) into your repository. 2 # Check this file (and the other files in this directory) into your repository.
3 # 3 #
4 # 'meteor add' and 'meteor remove' will edit this file for you, 4 # 'meteor add' and 'meteor remove' will edit this file for you,
5 # but you can also edit it by hand. 5 # but you can also edit it by hand.
6 6
7 meteor-base # Packages every Meteor app needs to have 7 meteor-base # Packages every Meteor app needs to have
8 mobile-experience # Packages for a great mobile UX 8 mobile-experience # Packages for a great mobile UX
9 mongo # The database Meteor supports right now 9 mongo # The database Meteor supports right now
10 reactive-var # Reactive variable for tracker 10 reactive-var # Reactive variable for tracker
11 session 11 session
12 jquery # Helpful client-side library 12 jquery # Helpful client-side library
13 tracker # Meteor's client-side reactive programming library 13 tracker # Meteor's client-side reactive programming library
14 14
15 standard-minifier-css # CSS minifier run for production mode 15 standard-minifier-css # CSS minifier run for production mode
16 standard-minifier-js # JS minifier run for production mode 16 standard-minifier-js # JS minifier run for production mode
17 es5-shim # ECMAScript 5 compatibility for older browsers. 17 es5-shim # ECMAScript 5 compatibility for older browsers.
18 ecmascript # Enable ECMAScript2015+ syntax in app code 18 ecmascript # Enable ECMAScript2015+ syntax in app code
19 19
20 accounts-password 20 accounts-password
21 accounts-base 21 accounts-base
22 check 22 check
23 audit-argument-checks 23 audit-argument-checks
24 browser-policy 24 browser-policy
25 25
26 fourseven:scss 26 fourseven:scss
27 aldeed:collection2 27 aldeed:collection2
28 # momentjs:moment NPM this 28 # momentjs:moment NPM this
29 alanning:roles 29 alanning:roles
30 react-meteor-data 30 react-meteor-data
31 themeteorchef:jquery-validation 31 themeteorchef:jquery-validation
32 themeteorchef:bert 32 themeteorchef:bert
33 static-html
34 xolvio:cleaner
35 practicalmeteor:mocha
36 xolvio:backdoor
33 37
1 accounts-base@1.2.4 1 accounts-base@1.2.4
2 accounts-password@1.1.6 2 accounts-password@1.1.6
3 alanning:roles@1.2.15 3 alanning:roles@1.2.15
4 aldeed:collection2@2.9.1 4 aldeed:collection2@2.9.1
5 aldeed:collection2-core@1.1.1 5 aldeed:collection2-core@1.1.1
6 aldeed:schema-deny@1.0.1 6 aldeed:schema-deny@1.0.1
7 aldeed:schema-index@1.0.1 7 aldeed:schema-index@1.0.1
8 aldeed:simple-schema@1.5.3 8 aldeed:simple-schema@1.5.3
9 allow-deny@1.0.2 9 allow-deny@1.0.2
10 audit-argument-checks@1.0.5 10 audit-argument-checks@1.0.5
11 autoupdate@1.2.6 11 autoupdate@1.2.6
12 babel-compiler@6.5.2 12 babel-compiler@6.5.2
13 babel-runtime@0.1.6 13 babel-runtime@0.1.6
14 base64@1.0.6 14 base64@1.0.6
15 binary-heap@1.0.6 15 binary-heap@1.0.6
16 blaze@2.1.5 16 blaze@2.1.5
17 blaze-tools@1.0.6 17 blaze-tools@1.0.6
18 boilerplate-generator@1.0.6 18 boilerplate-generator@1.0.6
19 browser-policy@1.0.7 19 browser-policy@1.0.7
20 browser-policy-common@1.0.7 20 browser-policy-common@1.0.7
21 browser-policy-content@1.0.8 21 browser-policy-content@1.0.8
22 browser-policy-framing@1.0.8 22 browser-policy-framing@1.0.8
23 caching-compiler@1.0.2 23 caching-compiler@1.0.2
24 caching-html-compiler@1.0.4 24 caching-html-compiler@1.0.4
25 callback-hook@1.0.6 25 callback-hook@1.0.6
26 check@1.1.2 26 check@1.1.2
27 coffeescript@1.0.15
27 ddp@1.2.3 28 ddp@1.2.3
28 ddp-client@1.2.3 29 ddp-client@1.2.3
29 ddp-common@1.2.3 30 ddp-common@1.2.3
30 ddp-rate-limiter@1.0.2 31 ddp-rate-limiter@1.0.2
31 ddp-server@1.2.4 32 ddp-server@1.2.4
32 deps@1.0.10 33 deps@1.0.10
33 diff-sequence@1.0.3 34 diff-sequence@1.0.3
34 ecmascript@0.4.1 35 ecmascript@0.4.1
35 ecmascript-runtime@0.2.8 36 ecmascript-runtime@0.2.8
36 ejson@1.0.9 37 ejson@1.0.9
37 email@1.0.10 38 email@1.0.10
38 es5-shim@4.5.8 39 es5-shim@4.5.8
39 fastclick@1.0.9 40 fastclick@1.0.9
40 fortawesome:fontawesome@4.4.0_1 41 fortawesome:fontawesome@4.4.0_1
41 fourseven:scss@3.4.1 42 fourseven:scss@3.4.1
42 geojson-utils@1.0.6 43 geojson-utils@1.0.6
43 hot-code-push@1.0.2 44 hot-code-push@1.0.2
44 html-tools@1.0.7 45 html-tools@1.0.7
45 htmljs@1.0.7 46 htmljs@1.0.7
46 http@1.1.3 47 http@1.1.3
47 id-map@1.0.5 48 id-map@1.0.5
48 jquery@1.11.6 49 jquery@1.11.6
49 launch-screen@1.0.8 50 launch-screen@1.0.8
50 livedata@1.0.16 51 livedata@1.0.16
51 localstorage@1.0.7 52 localstorage@1.0.7
52 logging@1.0.10 53 logging@1.0.10
53 mdg:validation-error@0.2.0 54 mdg:validation-error@0.2.0
54 meteor@1.1.12 55 meteor@1.1.12
55 meteor-base@1.0.2 56 meteor-base@1.0.2
56 minifier-css@1.1.9 57 minifier-css@1.1.9
57 minifier-js@1.1.9 58 minifier-js@1.1.9
58 minimongo@1.0.12 59 minimongo@1.0.12
59 mobile-experience@1.0.2 60 mobile-experience@1.0.2
60 mobile-status-bar@1.0.10 61 mobile-status-bar@1.0.10
61 modules@0.5.1 62 modules@0.5.1
62 modules-runtime@0.6.1 63 modules-runtime@0.6.1
63 mongo@1.1.5 64 mongo@1.1.5
64 mongo-id@1.0.2 65 mongo-id@1.0.2
65 npm-bcrypt@0.7.8_2 66 npm-bcrypt@0.7.8_2
66 npm-mongo@1.4.41 67 npm-mongo@1.4.41
67 observe-sequence@1.0.9 68 observe-sequence@1.0.9
68 ordered-dict@1.0.5 69 ordered-dict@1.0.5
70 practicalmeteor:chai@2.1.0_1
71 practicalmeteor:loglevel@1.2.0_2
72 practicalmeteor:mocha@2.1.0_8
73 practicalmeteor:mocha-core@0.1.4
74 practicalmeteor:sinon@1.14.1_2
69 promise@0.6.5 75 promise@0.6.5
70 raix:eventemitter@0.1.3 76 raix:eventemitter@0.1.3
71 random@1.0.7 77 random@1.0.7
72 rate-limit@1.0.2 78 rate-limit@1.0.2
73 react-meteor-data@0.2.7 79 react-meteor-data@0.2.7
74 reactive-dict@1.1.5 80 reactive-dict@1.1.5
75 reactive-var@1.0.7 81 reactive-var@1.0.7
76 reload@1.1.6 82 reload@1.1.6
77 retry@1.0.5 83 retry@1.0.5
78 routepolicy@1.0.8 84 routepolicy@1.0.8
79 service-configuration@1.0.7 85 service-configuration@1.0.7
80 session@1.1.3 86 session@1.1.3
81 sha@1.0.5 87 sha@1.0.5
82 spacebars@1.0.9 88 spacebars@1.0.9
83 spacebars-compiler@1.0.9 89 spacebars-compiler@1.0.9
84 srp@1.0.6 90 srp@1.0.6
85 standard-minifier-css@1.0.4 91 standard-minifier-css@1.0.4
86 standard-minifier-js@1.0.4 92 standard-minifier-js@1.0.4
93 static-html@1.0.5
87 templating@1.1.7 94 templating@1.1.7
88 templating-tools@1.0.2 95 templating-tools@1.0.2
89 themeteorchef:bert@2.1.0 96 themeteorchef:bert@2.1.0
90 themeteorchef:jquery-validation@1.14.0 97 themeteorchef:jquery-validation@1.14.0
91 tmeasday:check-npm-versions@0.2.0 98 tmeasday:check-npm-versions@0.2.0
99 tmeasday:test-reporter-helpers@0.2.1
92 tracker@1.0.11 100 tracker@1.0.11
93 ui@1.0.9 101 ui@1.0.9
94 underscore@1.0.6 102 underscore@1.0.6
95 url@1.0.7 103 url@1.0.7
96 webapp@1.2.6 104 webapp@1.2.6
97 webapp-hashing@1.0.7 105 webapp-hashing@1.0.7
106 xolvio:backdoor@0.1.2
107 xolvio:cleaner@0.2.0
98 108
File was created 1 <head>
2 <meta charset="utf-8">
3 <title>Application Name</title>
4 <meta name="description" content="A description for the application.">
5 <meta name="viewport" content="initial-scale=1, minimal-ui, maximum-scale=1, minimum-scale=1" />
6 <link rel="shortcut icon" type="image/png" href="favicon.png?v1" sizes="16x16 32x32 64x64">
7 <link rel="apple-touch-icon" sizes="120x120" href="apple-touch-icon-precomposed.png">
8 </head>
9
10 <body>
11 <div id="react-root"></div>
12 </body>
13
client/stylesheets/application.scss
1 @import "extends"; 1 @import "extends";
2 2
3 @import "base/animations"; 3 @import "base/animations";
4 @import "base/forms"; 4 @import "base/forms";
5 5
6 @import "module/loading"; 6 @import "module/loading";
7 @import "module/login"; 7 @import "module/login";
8 @import "module/signup"; 8 @import "module/signup";
9
10 @import "state/navbar";
9 11
client/stylesheets/state/_navbar.scss
File was created 1 .navbar-default .navbar-nav > li > a.active,
2 .navbar-default .navbar-nav > li > a.active:focus,
3 .navbar-default .navbar-nav > li > a.active:hover {
4 color: #555;
5 background-color: #e7e7e7;
6 }
7
imports/startup/client/routes.jsx
1 import React from 'react'; 1 import React from 'react';
2 import { render } from 'react-dom'; 2 import { render } from 'react-dom';
3 import { Router, Route, Redirect, IndexRoute, browserHistory } from 'react-router'; 3 import { Router, Route, Redirect, IndexRoute, browserHistory } from 'react-router';
4 4
5 import { App } from '../../ui/layouts/app'; 5 import { App } from '../../ui/layouts/app';
6 import { Dashboard } from '../../ui/pages/dashboard'; 6 import { Dashboard } from '../../ui/pages/dashboard';
7 import { Index } from '../../ui/pages/index'; 7 import { Index } from '../../ui/pages/index';
8 import { Login } from '../../ui/pages/login'; 8 import { Login } from '../../ui/pages/login';
9 import { RecoverPassword } from '../../ui/pages/recover-password'; 9 import { RecoverPassword } from '../../ui/pages/recover-password';
10 import { ResetPassword } from '../../ui/pages/reset-password'; 10 import { ResetPassword } from '../../ui/pages/reset-password';
11 import { Signup } from '../../ui/pages/signup'; 11 import { Signup } from '../../ui/pages/signup';
12 12
13 const requireAuth = ( nextState, replace ) => { 13 const requireAuth = ( nextState, replace ) => {
14 if ( !Meteor.loggingIn() && !Meteor.user() ) { 14 if ( !Meteor.loggingIn() && !Meteor.user() ) {
15 replace({ 15 replace({
16 pathname: '/login', 16 pathname: '/login',
17 state: { nextPathName: nextState.location.pathname } 17 state: { nextPathName: nextState.location.pathname }
18 }); 18 });
19 } 19 }
20 }; 20 };
21 21
22 const renderReactRoot = () => {
23 let container = document.createElement( 'div' );
24 container.id = 'react-root';
25 document.body.appendChild( container );
26 };
27
28 Meteor.startup( () => { 22 Meteor.startup( () => {
29 renderReactRoot();
30
31 render( 23 render(
32 <Router history={ browserHistory }> 24 <Router history={ browserHistory }>
33 <Route path="/" component={ App }> 25 <Route path="/" component={ App }>
34 <IndexRoute name="index" component={ Index } onEnter={ requireAuth } /> 26 <IndexRoute name="index" component={ Index } onEnter={ requireAuth } />
35 <Route name="dashboard" path="/dashboard" component={ Dashboard } onEnter={ requireAuth } /> 27 <Route name="dashboard" path="/dashboard" component={ Dashboard } onEnter={ requireAuth } />
36 <Route name="login" path="/login" component={ Login } /> 28 <Route name="login" path="/login" component={ Login } />
37 <Route name="recover-password" path="/recover-password" component={ RecoverPassword } /> 29 <Route name="recover-password" path="/recover-password" component={ RecoverPassword } />
38 <Route name="reset-password" path="/reset-password/:token" component={ ResetPassword } /> 30 <Route name="reset-password" path="/reset-password/:token" component={ ResetPassword } />
39 <Route name="signup" path="/signup" component={ Signup } /> 31 <Route name="signup" path="/signup" component={ Signup } />
40 </Route> 32 </Route>
41 </Router>, 33 </Router>,
42 document.getElementById( 'react-root' ) 34 document.getElementById( 'react-root' )
43 ); 35 );
44 }); 36 });
45 37
imports/ui/components/app-navigation.js
1 import React from 'react'; 1 import React from 'react';
2 import { Navbar, Nav, NavItem, NavDropdown, MenuItem } from 'react-bootstrap'; 2 import { Navbar, Nav, NavItem, NavDropdown, MenuItem } from 'react-bootstrap';
3 import { Link } from 'react-router';
3 import { PublicNavigation } from './public-navigation'; 4 import { PublicNavigation } from './public-navigation';
4 import { AuthenticatedNavigation } from './authenticated-navigation'; 5 import { AuthenticatedNavigation } from './authenticated-navigation';
5 6
6 export class AppNavigation extends React.Component { 7 export class AppNavigation extends React.Component {
7 renderNavigation( hasUser, activeRoute ) { 8 renderNavigation( hasUser, activeRoute ) {
8 return hasUser ? <AuthenticatedNavigation activeRoute={ activeRoute } /> : <PublicNavigation activeRoute={ activeRoute } />; 9 return hasUser ? <AuthenticatedNavigation activeRoute={ activeRoute } /> : <PublicNavigation activeRoute={ activeRoute } />;
9 } 10 }
10 11
11 render() { 12 render() {
12 return <Navbar> 13 return <Navbar>
13 <Navbar.Header> 14 <Navbar.Header>
14 <Navbar.Brand> 15 <Navbar.Brand>
15 <a href="/">Application Name</a> 16 <Link to="/">Application Name</Link>
16 </Navbar.Brand> 17 </Navbar.Brand>
18 <Navbar.Toggle />
17 </Navbar.Header> 19 </Navbar.Header>
18 { this.renderNavigation( this.props.hasUser, this.props.activeRoute ) } 20 <Navbar.Collapse>
21 { this.renderNavigation( this.props.hasUser, this.props.activeRoute ) }
22 </Navbar.Collapse>
19 </Navbar>; 23 </Navbar>;
20 } 24 }
21 } 25 }
22 26
imports/ui/components/authenticated-navigation.js
1 import React from 'react'; 1 import React from 'react';
2 import { browserHistory } from 'react-router'; 2 import { browserHistory, IndexLink, Link } from 'react-router';
3 import { Nav, NavItem, NavDropdown, MenuItem } from 'react-bootstrap'; 3 import { Nav, NavItem, NavDropdown, MenuItem } from 'react-bootstrap';
4 import { IndexLinkContainer, LinkContainer } from 'react-router-bootstrap';
5 4
6 const handleLogout = () => { 5 const handleLogout = () => {
7 return Meteor.logout( () => browserHistory.push( '/login' ) ); 6 return Meteor.logout( () => browserHistory.push( '/login' ) );
8 }; 7 };
9 8
10 const userName = () => { 9 const userName = () => {
11 const user = Meteor.user(); 10 const user = Meteor.user();
12 if ( user ) { 11 if ( user ) {
13 const name = user && user.profile ? user.profile.name : ''; 12 const name = user && user.profile ? user.profile.name : '';
14 return `${ name.first } ${ name.last }`; 13 return `${ name.first } ${ name.last }`;
15 } 14 }
16 }; 15 };
17 16
18 export const AuthenticatedNavigation = React.createClass({ 17 export const AuthenticatedNavigation = () => (
19 isActive( route, indexOnly ) { 18 <div>
20 return this.props.activeRoute( route, indexOnly ); 19 <Nav>
21 }, 20 <li><IndexLink to="/" activeClassName="active">Index</IndexLink></li>
22 handleRouteChange() { 21 <li><Link to="/dashboard" activeClassName="active">Dashboard</Link></li>
23 this.forceUpdate(); 22 </Nav>
24 }, 23 <Nav pullRight>
25 render() { 24 <NavDropdown eventKey={ 3 } title={ userName() } id="basic-nav-dropdown">
26 return <div> 25 <MenuItem eventKey={ 3.1 } onClick={ handleLogout }>Logout</MenuItem>
27 <Nav> 26 </NavDropdown>
28 <li className={ this.isActive( '/', true ) } onClick={ this.handleRouteChange }> 27 </Nav>
29 <Link to="/">Index</Link> 28 </div>
30 </li> 29 )
31 <li className={ this.isActive( '/dashboard' ) } onClick={ this.handleRouteChange }>
32 <Link to="/dashboard">Dashboard</Link>
33 </li>
34 </Nav>
35 <Nav pullRight>
36 <NavDropdown eventKey={ 3 } title={ userName() } id="basic-nav-dropdown">
37 <MenuItem eventKey={ 3.3 } onClick={ handleLogout }>Logout</MenuItem>
38 </NavDropdown>
39 </Nav>
40 </div>;
41 }
42 });
43 30
imports/ui/components/public-navigation.js
1 import React from 'react'; 1 import React from 'react';
2 import { Link } from 'react-router'; 2 import { Link } from 'react-router';
3 import { Nav, NavItem } from 'react-bootstrap'; 3 import { Nav, NavItem } from 'react-bootstrap';
4 4
5 export const PublicNavigation = React.createClass({ 5 export const PublicNavigation = () => (
6 isActive( route, indexOnly ) { 6 <Nav pullRight>
7 return this.props.activeRoute( route, indexOnly ) ? 'active' : ''; 7 <li role="presentation"><Link to="/signup">Sign Up</Link></li>
8 }, 8 <li role="presentation"><Link to="/login">Log In</Link></li>
9 handleRouteChange() { 9 </Nav>
10 this.forceUpdate(); 10 )
11 },
12 render() {
13 return <Nav pullRight>
14 <li className={ this.isActive( '/signup' ) } onClick={ this.handleRouteChange }>
15 <Link to="/signup">Sign Up</Link>
16 </li>
17 <li className={ this.isActive( '/login' ) } onClick={ this.handleRouteChange }>
18 <Link to="/login">Log In</Link>
19 </li>
20 </Nav>;
21 }
22 });
23 11
1 { 1 {
2 "name": "application-name", 2 "name": "application-name",
3 "version": "1.0.0", 3 "version": "1.0.0",
4 "description": "Application description.", 4 "description": "Application description.",
5 "scripts": { 5 "scripts": {
6 "start": "meteor --settings settings-development.json", 6 "start": "meteor --settings settings-development.json",
7 "chimp-watch": "chimp --ddp=http://localhost:3000 --watch --mocha --path=tests",
8 "chimp-test": "chimp --ddp=http://localhost:3000 --mocha --path=tests",
7 "staging": "meteor deploy staging.meteor.com --settings settings-development.json", 9 "staging": "meteor deploy staging.meteor.com --settings settings-development.json",
8 "production": "meteor deploy production.meteor.com --settings settings-production.json" 10 "production": "meteor deploy production.meteor.com --settings settings-production.json"
9 }, 11 },
10 "devDependencies": {}, 12 "devDependencies": {},
11 "dependencies": { 13 "dependencies": {
14 "chimp": "^0.33.0",
12 "react": "^0.14.8", 15 "react": "^0.14.8",
13 "react-addons-pure-render-mixin": "^0.14.8", 16 "react-addons-pure-render-mixin": "^0.14.8",
14 "react-bootstrap": "^0.28.4", 17 "react-bootstrap": "^0.28.4",
15 "react-dom": "^0.14.7", 18 "react-dom": "^0.14.7",
16 "react-mounter": "^1.1.0", 19 "react-mounter": "^1.1.0",
17 "react-router": "^2.0.1", 20 "react-router": "^2.0.1",
18 "react-router-bootstrap": "^0.20.1" 21 "react-router-bootstrap": "^0.20.1"
19 } 22 }
20 } 23 }
21 24
File was created 1 describe( 'Log In', function() {
2 beforeEach( function() {
3 server.execute( function() {
4 var user = Meteor.users.findOne( { 'emails.address': 'carl.winslow@abc.com' } );
5 if ( user ) {
6 Meteor.users.remove( user._id );
7 }
8 });
9 });
10
11 it( 'should allow us to login @watch', function() {
12 server.execute( function() {
13 Accounts.createUser({
14 email: 'carl.winslow@abc.com',
15 password: 'bigguy1989',
16 profile: {
17 name: { first: 'Carl', last: 'Winslow' }
18 }
19 });
20 });
21
22 browser.url( 'http://localhost:3000/login' )
23 .setValue( '[name="emailAddress"]', 'carl.winslow@abc.com' )
24 .setValue( '[name="password"]', 'bigguy1989' )
25 .submitForm( 'form' );
26
27 browser.waitForExist( '.jumbotron' );
28 expect( browser.getUrl() ).to.equal( 'http://localhost:3000/' );
29 });
30 });
31
File was created 1 describe( 'Sign Up', function() {
2 beforeEach( function() {
3 server.execute( function() {
4 var user = Meteor.users.findOne( { 'emails.address': 'carl.winslow@abc.com' } );
5 if ( user ) {
6 Meteor.users.remove( user._id );
7 }
8 });
9 });
10
11 it( 'should create a new user and login with redirect to index @watch', function() {
12 browser.url( 'http://localhost:3000/signup' )
13 .setValue( '[name="firstName"]', 'Carl' )
14 .setValue( '[name="lastName"]', 'Winslow' )
15 .setValue( '[name="emailAddress"]', 'carl.winslow@abc.com' )
16 .setValue( '[name="password"]', 'bigguy1989' )
17 .submitForm( 'form' );
18
19 browser.waitForExist( '.jumbotron' );
20 expect( browser.getUrl() ).to.equal( 'http://localhost:3000/' );
21 });
22 });
23