Commit f0c912bf1f2a4157f8583e1922edfd5247346701
1 parent
d1f05315dd
Exists in
master
add method tests and airbnb linting via eslint
Showing
38 changed files
with
436 additions
and
345 deletions
Show diff stats
.meteor/packages
.meteor/versions
... | ... | @@ -25,6 +25,7 @@ caching-html-compiler@1.0.5 |
25 | 25 | callback-hook@1.0.7 |
26 | 26 | check@1.1.3 |
27 | 27 | coffeescript@1.0.16 |
28 | +dburles:factory@0.4.2 | |
28 | 29 | ddp@1.2.4 |
29 | 30 | ddp-client@1.2.4 |
30 | 31 | ddp-common@1.2.4 |
... | ... | @@ -38,8 +39,8 @@ ejson@1.0.10 |
38 | 39 | email@1.0.11 |
39 | 40 | es5-shim@4.5.9 |
40 | 41 | fastclick@1.0.10 |
41 | -fortawesome:fontawesome@4.4.0_1 | |
42 | -fourseven:scss@3.4.1 | |
42 | +fortawesome:fontawesome@4.5.0 | |
43 | +fourseven:scss@3.4.3 | |
43 | 44 | geojson-utils@1.0.7 |
44 | 45 | hot-code-push@1.0.3 |
45 | 46 | html-tools@1.0.8 |
... | ... | @@ -51,7 +52,7 @@ launch-screen@1.0.10 |
51 | 52 | livedata@1.0.17 |
52 | 53 | localstorage@1.0.8 |
53 | 54 | logging@1.0.11 |
54 | -mdg:validated-method@1.0.2 | |
55 | +mdg:validated-method@1.1.0 | |
55 | 56 | mdg:validation-error@0.5.1 |
56 | 57 | meteor@1.1.13 |
57 | 58 | meteor-base@1.0.3 |
... | ... | @@ -70,14 +71,14 @@ observe-sequence@1.0.10 |
70 | 71 | ordered-dict@1.0.6 |
71 | 72 | practicalmeteor:chai@2.1.0_1 |
72 | 73 | practicalmeteor:loglevel@1.2.0_2 |
73 | -practicalmeteor:mocha@2.1.0_8 | |
74 | +practicalmeteor:mocha@2.4.5_1 | |
74 | 75 | practicalmeteor:mocha-core@0.1.4 |
75 | 76 | practicalmeteor:sinon@1.14.1_2 |
76 | 77 | promise@0.6.6 |
77 | 78 | raix:eventemitter@0.1.3 |
78 | 79 | random@1.0.8 |
79 | 80 | rate-limit@1.0.3 |
80 | -react-meteor-data@0.2.7 | |
81 | +react-meteor-data@0.2.9 | |
81 | 82 | reactive-dict@1.1.6 |
82 | 83 | reactive-var@1.0.8 |
83 | 84 | reload@1.1.7 |
... | ... | @@ -104,6 +105,6 @@ underscore@1.0.7 |
104 | 105 | url@1.0.8 |
105 | 106 | webapp@1.2.7 |
106 | 107 | webapp-hashing@1.0.8 |
107 | -xolvio:backdoor@0.1.2 | |
108 | -xolvio:cleaner@0.2.0 | |
108 | +xolvio:backdoor@0.2.0 | |
109 | +xolvio:cleaner@0.3.0 | |
109 | 110 | xolvio:email-stub@0.2.0 | ... | ... |
imports/api/documents/documents.js
1 | 1 | import { Mongo } from 'meteor/mongo'; |
2 | +import faker from 'faker'; | |
2 | 3 | |
3 | -export const Documents = new Mongo.Collection( 'Documents' ); | |
4 | +export const Documents = new Mongo.Collection('Documents'); | |
5 | + | |
6 | +Documents.schema = new SimpleSchema({ | |
7 | + title: { | |
8 | + type: String, | |
9 | + label: 'The title of the document.', | |
10 | + }, | |
11 | +}); | |
12 | + | |
13 | +Documents.attachSchema(Documents.schema); | |
14 | + | |
15 | +Factory.define('document', Documents, { | |
16 | + title: () => faker.hacker.phrase(), | |
17 | +}); | ... | ... |
imports/api/documents/documents.tests.js
... | ... | @@ -0,0 +1,13 @@ |
1 | +/* eslint-env mocha */ | |
2 | +/* eslint-disable func-names, prefer-arrow-callback */ | |
3 | + | |
4 | +import { chai } from 'meteor/practicalmeteor:chai'; | |
5 | +import { Documents } from './documents.js'; | |
6 | + | |
7 | +const { assert } = chai; | |
8 | + | |
9 | +describe('Documents collection', function () { | |
10 | + it('registers the collection with Mongo properly', function () { | |
11 | + assert.equal(typeof Documents, 'object'); | |
12 | + }); | |
13 | +}); | ... | ... |
imports/api/documents/methods.js
... | ... | @@ -3,30 +3,30 @@ import { Documents } from './documents'; |
3 | 3 | export const insertDocument = new ValidatedMethod({ |
4 | 4 | name: 'documents.insert', |
5 | 5 | validate: new SimpleSchema({ |
6 | - title: { type: String } | |
6 | + title: { type: String }, | |
7 | 7 | }).validator(), |
8 | - run( document ) { | |
9 | - Documents.insert( document ); | |
10 | - } | |
8 | + run(document) { | |
9 | + Documents.insert(document); | |
10 | + }, | |
11 | 11 | }); |
12 | 12 | |
13 | 13 | export const updateDocument = new ValidatedMethod({ |
14 | 14 | name: 'documents.update', |
15 | 15 | validate: new SimpleSchema({ |
16 | 16 | _id: { type: String }, |
17 | - 'update.title': { type: String, optional: true } | |
17 | + 'update.title': { type: String, optional: true }, | |
18 | 18 | }).validator(), |
19 | - run( { _id, update } ) { | |
20 | - Documents.update( _id, { $set: update } ); | |
21 | - } | |
19 | + run({ _id, update }) { | |
20 | + Documents.update(_id, { $set: update }); | |
21 | + }, | |
22 | 22 | }); |
23 | 23 | |
24 | 24 | export const removeDocument = new ValidatedMethod({ |
25 | 25 | name: 'documents.remove', |
26 | 26 | validate: new SimpleSchema({ |
27 | - _id: { type: String } | |
27 | + _id: { type: String }, | |
28 | 28 | }).validator(), |
29 | - run( { _id } ) { | |
30 | - Documents.remove( _id ); | |
31 | - } | |
29 | + run({ _id }) { | |
30 | + Documents.remove(_id); | |
31 | + }, | |
32 | 32 | }); | ... | ... |
imports/api/documents/methods.tests.js
... | ... | @@ -0,0 +1,42 @@ |
1 | +/* eslint-env mocha */ | |
2 | +/* eslint-disable func-names, prefer-arrow-callback */ | |
3 | + | |
4 | +import { assert } from 'meteor/practicalmeteor:chai'; | |
5 | +import { resetDatabase } from 'meteor/xolvio:cleaner'; | |
6 | +import { Documents } from './documents.js'; | |
7 | +import { insertDocument, updateDocument, removeDocument } from './methods.js'; | |
8 | + | |
9 | +describe('Documents methods', function () { | |
10 | + beforeEach(function () { | |
11 | + if (Meteor.isServer) { | |
12 | + resetDatabase(); | |
13 | + } | |
14 | + }); | |
15 | + | |
16 | + it('inserts a document into the Documents collection', function () { | |
17 | + insertDocument.call({ title: 'You can\'t arrest me, I\'m the Cake Boss!' }); | |
18 | + const getDocument = Documents.findOne({ title: 'You can\'t arrest me, I\'m the Cake Boss!' }); | |
19 | + assert.equal(getDocument.title, 'You can\'t arrest me, I\'m the Cake Boss!'); | |
20 | + }); | |
21 | + | |
22 | + it('updates a document in the Documents collection', function () { | |
23 | + const { _id } = Factory.create('document'); | |
24 | + | |
25 | + updateDocument.call({ | |
26 | + _id, | |
27 | + update: { | |
28 | + title: 'You can\'t arrest me, I\'m the Cake Boss!', | |
29 | + }, | |
30 | + }); | |
31 | + | |
32 | + const getDocument = Documents.findOne(_id); | |
33 | + assert.equal(getDocument.title, 'You can\'t arrest me, I\'m the Cake Boss!'); | |
34 | + }); | |
35 | + | |
36 | + it('removes a document from the Documents collection', function () { | |
37 | + const { _id } = Factory.create('document'); | |
38 | + removeDocument.call({ _id }); | |
39 | + const getDocument = Documents.findOne(_id); | |
40 | + assert.equal(getDocument, undefined); | |
41 | + }); | |
42 | +}); | ... | ... |
imports/api/documents/server/publications.js
imports/modules/get-input-value.js
imports/modules/login.js
... | ... | @@ -4,44 +4,44 @@ let component; |
4 | 4 | |
5 | 5 | const _handleLogin = () => { |
6 | 6 | // <Input /> component value is accessed via nested refs. |
7 | - const email = component.refs.emailAddress.refs.input.value, | |
8 | - password = component.refs.password.value; | |
7 | + const email = component.refs.emailAddress.refs.input.value; | |
8 | + const password = component.refs.password.value; | |
9 | 9 | |
10 | - Meteor.loginWithPassword( email, password, ( error ) => { | |
11 | - if ( error ) { | |
12 | - Bert.alert( error.reason, 'warning' ); | |
10 | + Meteor.loginWithPassword(email, password, (error) => { | |
11 | + if (error) { | |
12 | + Bert.alert(error.reason, 'warning'); | |
13 | 13 | } else { |
14 | - browserHistory.push( '/' ); | |
15 | - Bert.alert( 'Logged in!', 'success' ); | |
14 | + browserHistory.push('/'); | |
15 | + Bert.alert('Logged in!', 'success'); | |
16 | 16 | } |
17 | 17 | }); |
18 | 18 | }; |
19 | 19 | |
20 | 20 | const _validate = () => { |
21 | - $( component.refs.login ).validate({ | |
21 | + $(component.refs.login).validate({ | |
22 | 22 | rules: { |
23 | 23 | emailAddress: { |
24 | 24 | required: true, |
25 | - email: true | |
25 | + email: true, | |
26 | 26 | }, |
27 | 27 | password: { |
28 | - required: true | |
29 | - } | |
28 | + required: true, | |
29 | + }, | |
30 | 30 | }, |
31 | 31 | messages: { |
32 | 32 | emailAddress: { |
33 | 33 | required: 'Need an email address here.', |
34 | - email: 'Is this email address legit?' | |
34 | + email: 'Is this email address legit?', | |
35 | 35 | }, |
36 | 36 | password: { |
37 | - required: 'Need a password here.' | |
38 | - } | |
37 | + required: 'Need a password here.', | |
38 | + }, | |
39 | 39 | }, |
40 | - submitHandler() { _handleLogin(); } | |
40 | + submitHandler() { _handleLogin(); }, | |
41 | 41 | }); |
42 | 42 | }; |
43 | 43 | |
44 | -export const handleLogin = ( options ) => { | |
44 | +export const handleLogin = (options) => { | |
45 | 45 | component = options.component; |
46 | 46 | _validate(); |
47 | 47 | }; | ... | ... |
imports/modules/recover-password.js
... | ... | @@ -4,35 +4,35 @@ let component; |
4 | 4 | |
5 | 5 | const _handleRecovery = () => { |
6 | 6 | Accounts.forgotPassword({ |
7 | - email: getInputValue( component, 'emailAddress', true ) | |
8 | - }, ( error ) => { | |
9 | - if ( error ) { | |
10 | - Bert.alert( error.reason, 'warning' ); | |
7 | + email: getInputValue(component, 'emailAddress', true), | |
8 | + }, (error) => { | |
9 | + if (error) { | |
10 | + Bert.alert(error.reason, 'warning'); | |
11 | 11 | } else { |
12 | - Bert.alert( 'Check your inbox for a reset link!', 'success' ); | |
12 | + Bert.alert('Check your inbox for a reset link!', 'success'); | |
13 | 13 | } |
14 | 14 | }); |
15 | 15 | }; |
16 | 16 | |
17 | 17 | const _validate = () => { |
18 | - $( component.refs.recoverPassword ).validate({ | |
18 | + $(component.refs.recoverPassword).validate({ | |
19 | 19 | rules: { |
20 | 20 | emailAddress: { |
21 | 21 | required: true, |
22 | - email: true | |
23 | - } | |
22 | + email: true, | |
23 | + }, | |
24 | 24 | }, |
25 | 25 | messages: { |
26 | 26 | emailAddress: { |
27 | 27 | required: 'Need an email address here.', |
28 | - email: 'Is this email address legit?' | |
29 | - } | |
28 | + email: 'Is this email address legit?', | |
29 | + }, | |
30 | 30 | }, |
31 | - submitHandler() { _handleRecovery(); } | |
31 | + submitHandler() { _handleRecovery(); }, | |
32 | 32 | }); |
33 | 33 | }; |
34 | 34 | |
35 | -export const handleRecoverPassword = ( options ) => { | |
35 | +export const handleRecoverPassword = (options) => { | |
36 | 36 | component = options.component; |
37 | 37 | _validate(); |
38 | 38 | }; | ... | ... |
imports/modules/reset-password.js
1 | 1 | import { getInputValue } from './get-input-value'; |
2 | 2 | import { browserHistory } from 'react-router'; |
3 | 3 | |
4 | -let component, | |
5 | - token; | |
4 | +let component; | |
5 | +let token; | |
6 | 6 | |
7 | 7 | const _handleReset = () => { |
8 | - const password = getInputValue( component, 'newPassword', true ); | |
9 | - Accounts.resetPassword( token, password, ( error ) => { | |
10 | - if ( error ) { | |
11 | - Bert.alert( error.reason, 'danger' ); | |
8 | + const password = getInputValue(component, 'newPassword', true); | |
9 | + Accounts.resetPassword(token, password, (error) => { | |
10 | + if (error) { | |
11 | + Bert.alert(error.reason, 'danger'); | |
12 | 12 | } else { |
13 | - browserHistory.push( '/' ); | |
14 | - Bert.alert( 'Password reset!', 'success' ); | |
13 | + browserHistory.push('/'); | |
14 | + Bert.alert('Password reset!', 'success'); | |
15 | 15 | } |
16 | 16 | }); |
17 | 17 | }; |
18 | 18 | |
19 | 19 | const _validate = () => { |
20 | - $( component.refs.resetPassword ).validate({ | |
20 | + $(component.refs.resetPassword).validate({ | |
21 | 21 | rules: { |
22 | 22 | newPassword: { |
23 | 23 | required: true, |
24 | - minlength: 6 | |
24 | + minlength: 6, | |
25 | 25 | }, |
26 | 26 | repeatNewPassword: { |
27 | 27 | required: true, |
28 | 28 | minlength: 6, |
29 | - equalTo: '[name="newPassword"]' | |
30 | - } | |
29 | + equalTo: '[name="newPassword"]', | |
30 | + }, | |
31 | 31 | }, |
32 | 32 | messages: { |
33 | 33 | newPassword: { |
34 | - required: "Enter a new password, please.", | |
35 | - minlength: "Use at least six characters, please." | |
34 | + required: 'Enter a new password, please.', | |
35 | + minlength: 'Use at least six characters, please.', | |
36 | 36 | }, |
37 | 37 | repeatNewPassword: { |
38 | - required: "Repeat your new password, please.", | |
39 | - equalTo: "Hmm, your passwords don't match. Try again?" | |
40 | - } | |
38 | + required: 'Repeat your new password, please.', | |
39 | + equalTo: 'Hmm, your passwords don\'t match. Try again?', | |
40 | + }, | |
41 | 41 | }, |
42 | - submitHandler() { _handleReset(); } | |
42 | + submitHandler() { _handleReset(); }, | |
43 | 43 | }); |
44 | 44 | }; |
45 | 45 | |
46 | -export const handleResetPassword = ( options ) => { | |
46 | +export const handleResetPassword = (options) => { | |
47 | 47 | component = options.component; |
48 | - token = options.token; | |
48 | + token = options.token; | |
49 | 49 | _validate(); |
50 | 50 | }; | ... | ... |
imports/modules/signup.js
... | ... | @@ -3,71 +3,69 @@ import { getInputValue } from './get-input-value'; |
3 | 3 | |
4 | 4 | let component; |
5 | 5 | |
6 | -const _getUserData = () => { | |
7 | - return { | |
8 | - email: getInputValue( component, 'emailAddress', true ), | |
9 | - password: getInputValue( component, 'password', true ), | |
10 | - profile: { | |
11 | - name: { | |
12 | - first: getInputValue( component, 'firstName', true ), | |
13 | - last: getInputValue( component, 'lastName', true ) | |
14 | - } | |
15 | - } | |
16 | - }; | |
17 | -}; | |
6 | +const _getUserData = () => ({ | |
7 | + email: getInputValue(component, 'emailAddress', true), | |
8 | + password: getInputValue(component, 'password', true), | |
9 | + profile: { | |
10 | + name: { | |
11 | + first: getInputValue(component, 'firstName', true), | |
12 | + last: getInputValue(component, 'lastName', true), | |
13 | + }, | |
14 | + }, | |
15 | +}); | |
18 | 16 | |
19 | 17 | const _handleSignup = () => { |
20 | 18 | const user = _getUserData(); |
21 | 19 | |
22 | - Accounts.createUser( user, ( error ) => { | |
23 | - if ( error ) { | |
24 | - Bert.alert( error.reason, 'danger' ); | |
20 | + Accounts.createUser(user, (error) => { | |
21 | + if (error) { | |
22 | + Bert.alert(error.reason, 'danger'); | |
25 | 23 | } else { |
26 | - browserHistory.push( '/' ); | |
27 | - Bert.alert( 'Welcome!', 'success' ); | |
24 | + browserHistory.push('/'); | |
25 | + Bert.alert('Welcome!', 'success'); | |
28 | 26 | } |
29 | 27 | }); |
30 | 28 | }; |
31 | 29 | |
32 | 30 | const _validate = () => { |
33 | - $( component.refs.signup ).validate({ | |
31 | + $(component.refs.signup).validate({ | |
34 | 32 | rules: { |
35 | 33 | firstName: { |
36 | - required: true | |
34 | + required: true, | |
37 | 35 | }, |
38 | 36 | lastName: { |
39 | - required: true | |
37 | + required: true, | |
40 | 38 | }, |
41 | 39 | emailAddress: { |
42 | 40 | required: true, |
43 | - email: true | |
41 | + email: true, | |
44 | 42 | }, |
45 | 43 | password: { |
46 | 44 | required: true, |
47 | - minlength: 6 | |
48 | - } | |
45 | + minlength: 6, | |
46 | + }, | |
49 | 47 | }, |
50 | 48 | messages: { |
51 | 49 | firstName: { |
52 | - required: 'First name?' | |
50 | + required: 'First name?', | |
53 | 51 | }, |
54 | 52 | lastName: { |
55 | - required: 'Last name?' | |
53 | + required: 'Last name?', | |
56 | 54 | }, |
57 | 55 | emailAddress: { |
58 | 56 | required: 'Need an email address here.', |
59 | - email: 'Is this email address legit?' | |
57 | + email: 'Is this email address legit?', | |
60 | 58 | }, |
61 | 59 | password: { |
62 | 60 | required: 'Need a password here.', |
63 | - minlength: 'Use at least six characters, please.' | |
64 | - } | |
61 | + minlength: 'Use at least six characters, please.', | |
62 | + }, | |
65 | 63 | }, |
66 | - submitHandler() { _handleSignup(); } | |
64 | + submitHandler() { _handleSignup(); }, | |
67 | 65 | }); |
68 | 66 | }; |
69 | 67 | |
70 | -export const handleSignup = ( options ) => { | |
68 | +export const handleSignup = (options) => { | |
71 | 69 | component = options.component; |
72 | 70 | _validate(); |
73 | 71 | }; | ... | ... |
imports/startup/client/index.js
imports/startup/client/routes.js
... | ... | @@ -0,0 +1,38 @@ |
1 | +import React from 'react'; | |
2 | +import { render } from 'react-dom'; | |
3 | +import { Router, Route, Redirect, IndexRoute, browserHistory } from 'react-router'; | |
4 | + | |
5 | +import { App } from '../../ui/layouts/app'; | |
6 | +import { Documents } from '../../ui/pages/documents'; | |
7 | +import { Index } from '../../ui/pages/index'; | |
8 | +import { Login } from '../../ui/pages/login'; | |
9 | +import { NotFound } from '../../ui/pages/not-found'; | |
10 | +import { RecoverPassword } from '../../ui/pages/recover-password'; | |
11 | +import { ResetPassword } from '../../ui/pages/reset-password'; | |
12 | +import { Signup } from '../../ui/pages/signup'; | |
13 | + | |
14 | +const requireAuth = (nextState, replace) => { | |
15 | + if (!Meteor.loggingIn() && !Meteor.user()) { | |
16 | + replace({ | |
17 | + pathname: '/login', | |
18 | + state: { nextPathName: nextState.location.pathname }, | |
19 | + }); | |
20 | + } | |
21 | +}; | |
22 | + | |
23 | +Meteor.startup(() => { | |
24 | + render( | |
25 | + <Router history={ browserHistory }> | |
26 | + <Route path="/" component={ App }> | |
27 | + <IndexRoute name="index" component={ Index } onEnter={ requireAuth } /> | |
28 | + <Route name="documents" path="/documents" component={ Documents } onEnter={ requireAuth } /> | |
29 | + <Route name="login" path="/login" component={ Login } /> | |
30 | + <Route name="recover-password" path="/recover-password" component={ RecoverPassword } /> | |
31 | + <Route name="reset-password" path="/reset-password/:token" component={ ResetPassword } /> | |
32 | + <Route name="signup" path="/signup" component={ Signup } /> | |
33 | + <Route path="*" component={ NotFound } /> | |
34 | + </Route> | |
35 | + </Router>, | |
36 | + document.getElementById('react-root') | |
37 | + ); | |
38 | +}); | ... | ... |
imports/startup/client/routes.jsx
... | ... | @@ -1,38 +0,0 @@ |
1 | -import React from 'react'; | |
2 | -import { render } from 'react-dom'; | |
3 | -import { Router, Route, Redirect, IndexRoute, browserHistory } from 'react-router'; | |
4 | - | |
5 | -import { App } from '../../ui/layouts/app'; | |
6 | -import { Documents } from '../../ui/pages/documents'; | |
7 | -import { Index } from '../../ui/pages/index'; | |
8 | -import { Login } from '../../ui/pages/login'; | |
9 | -import { NotFound } from '../../ui/pages/not-found'; | |
10 | -import { RecoverPassword } from '../../ui/pages/recover-password'; | |
11 | -import { ResetPassword } from '../../ui/pages/reset-password'; | |
12 | -import { Signup } from '../../ui/pages/signup'; | |
13 | - | |
14 | -const requireAuth = ( nextState, replace ) => { | |
15 | - if ( !Meteor.loggingIn() && !Meteor.user() ) { | |
16 | - replace({ | |
17 | - pathname: '/login', | |
18 | - state: { nextPathName: nextState.location.pathname } | |
19 | - }); | |
20 | - } | |
21 | -}; | |
22 | - | |
23 | -Meteor.startup( () => { | |
24 | - render( | |
25 | - <Router history={ browserHistory }> | |
26 | - <Route path="/" component={ App }> | |
27 | - <IndexRoute name="index" component={ Index } onEnter={ requireAuth } /> | |
28 | - <Route name="documents" path="/documents" component={ Documents } onEnter={ requireAuth } /> | |
29 | - <Route name="login" path="/login" component={ Login } /> | |
30 | - <Route name="recover-password" path="/recover-password" component={ RecoverPassword } /> | |
31 | - <Route name="reset-password" path="/reset-password/:token" component={ ResetPassword } /> | |
32 | - <Route name="signup" path="/signup" component={ Signup } /> | |
33 | - <Route path="*" component={ NotFound } /> | |
34 | - </Route> | |
35 | - </Router>, | |
36 | - document.getElementById( 'react-root' ) | |
37 | - ); | |
38 | -}); |
imports/startup/server/accounts/email-templates.js
1 | -const name = 'Application Name', | |
2 | - email = '<support@application.com>', | |
3 | - from = `${ name } ${ email }`, | |
4 | - emailTemplates = Accounts.emailTemplates; | |
1 | +const name = 'Application Name'; | |
2 | +const email = '<support@application.com>'; | |
3 | +const from = `${name} ${email}`; | |
4 | +const emailTemplates = Accounts.emailTemplates; | |
5 | 5 | |
6 | 6 | emailTemplates.siteName = name; |
7 | -emailTemplates.from = from; | |
7 | +emailTemplates.from = from; | |
8 | 8 | |
9 | 9 | emailTemplates.resetPassword = { |
10 | 10 | subject() { |
11 | - return `[${ name }] Reset Your Password`; | |
11 | + return `[${name}] Reset Your Password`; | |
12 | 12 | }, |
13 | - text( user, url ) { | |
14 | - let userEmail = user.emails[ 0 ].address, | |
15 | - urlWithoutHash = url.replace( '#/', '' ); | |
13 | + text(user, url) { | |
14 | + const userEmail = user.emails[0].address; | |
15 | + const urlWithoutHash = url.replace('#/', ''); | |
16 | 16 | |
17 | - return `A password reset has been requested for the account related to this address (${ userEmail }). To reset the password, visit the following link:\n\n${ urlWithoutHash }\n\n If you did not request this reset, please ignore this email. If you feel something is wrong, please contact our support team: ${ email }.`; | |
18 | - } | |
17 | + return `A password reset has been requested for the account related to this | |
18 | + address (${userEmail}). To reset the password, visit the following link: | |
19 | + \n\n${urlWithoutHash}\n\n If you did not request this reset, please ignore | |
20 | + this email. If you feel something is wrong, please contact our support team: | |
21 | + ${email}.`; | |
22 | + }, | |
19 | 23 | }; | ... | ... |
imports/startup/server/fixtures.js
... | ... | @@ -2,18 +2,14 @@ const users = [{ |
2 | 2 | email: 'admin@admin.com', |
3 | 3 | password: 'password', |
4 | 4 | profile: { |
5 | - name: { first: 'Carl', last: 'Winslow' } | |
6 | - } | |
5 | + name: { first: 'Carl', last: 'Winslow' }, | |
6 | + }, | |
7 | 7 | }]; |
8 | 8 | |
9 | -users.forEach( ( { email, password, profile } ) => { | |
10 | - const userExists = Meteor.users.findOne( { 'emails.address': email } ); | |
9 | +users.forEach(({ email, password, profile }) => { | |
10 | + const userExists = Meteor.users.findOne({ 'emails.address': email }); | |
11 | 11 | |
12 | - if ( !userExists ) { | |
13 | - Accounts.createUser({ | |
14 | - email: email, | |
15 | - password: password, | |
16 | - profile: profile | |
17 | - }); | |
12 | + if (!userExists) { | |
13 | + Accounts.createUser({ email, password, profile }); | |
18 | 14 | } |
19 | 15 | }); | ... | ... |
imports/ui/components/add-document.js
... | ... | @@ -2,19 +2,19 @@ import React from 'react'; |
2 | 2 | import { Row, Col, ListGroup, ListGroupItem, Input, Alert } from 'react-bootstrap'; |
3 | 3 | import { insertDocument } from '../../api/documents/methods.js'; |
4 | 4 | |
5 | -const handleInsertDocument = ( event ) => { | |
6 | - const target = event.target, | |
7 | - title = target.value.trim(); | |
5 | +const handleInsertDocument = (event) => { | |
6 | + const target = event.target; | |
7 | + const title = target.value.trim(); | |
8 | 8 | |
9 | - if ( title !== '' && event.keyCode === 13 ) { | |
9 | + if (title !== '' && event.keyCode === 13) { | |
10 | 10 | insertDocument.call({ |
11 | - title: title | |
12 | - }, ( error, response ) => { | |
13 | - if ( error ) { | |
14 | - Bert.alert( error.reason, 'danger' ); | |
11 | + title, | |
12 | + }, (error) => { | |
13 | + if (error) { | |
14 | + Bert.alert(error.reason, 'danger'); | |
15 | 15 | } else { |
16 | 16 | target.value = ''; |
17 | - Bert.alert( 'Document added!', 'success' ); | |
17 | + Bert.alert('Document added!', 'success'); | |
18 | 18 | } |
19 | 19 | }); |
20 | 20 | } |
... | ... | @@ -26,4 +26,4 @@ export const AddDocument = () => ( |
26 | 26 | onKeyUp={ handleInsertDocument } |
27 | 27 | placeholder="Type a document title and press enter..." |
28 | 28 | /> |
29 | -) | |
29 | +); | ... | ... |
imports/ui/components/app-navigation.js
... | ... | @@ -5,7 +5,7 @@ import { PublicNavigation } from './public-navigation'; |
5 | 5 | import { AuthenticatedNavigation } from './authenticated-navigation'; |
6 | 6 | |
7 | 7 | export class AppNavigation extends React.Component { |
8 | - renderNavigation( hasUser ) { | |
8 | + renderNavigation(hasUser) { | |
9 | 9 | return hasUser ? <AuthenticatedNavigation /> : <PublicNavigation />; |
10 | 10 | } |
11 | 11 | |
... | ... | @@ -18,7 +18,7 @@ export class AppNavigation extends React.Component { |
18 | 18 | <Navbar.Toggle /> |
19 | 19 | </Navbar.Header> |
20 | 20 | <Navbar.Collapse> |
21 | - { this.renderNavigation( this.props.hasUser ) } | |
21 | + { this.renderNavigation(this.props.hasUser) } | |
22 | 22 | </Navbar.Collapse> |
23 | 23 | </Navbar>; |
24 | 24 | } | ... | ... |
imports/ui/components/authenticated-navigation.js
... | ... | @@ -3,16 +3,12 @@ import { browserHistory } from 'react-router'; |
3 | 3 | import { IndexLinkContainer, LinkContainer } from 'react-router-bootstrap'; |
4 | 4 | import { Nav, NavItem, NavDropdown, MenuItem } from 'react-bootstrap'; |
5 | 5 | |
6 | -const handleLogout = () => { | |
7 | - return Meteor.logout( () => browserHistory.push( '/login' ) ); | |
8 | -}; | |
6 | +const handleLogout = () => Meteor.logout(() => browserHistory.push('/login')); | |
9 | 7 | |
10 | 8 | const userName = () => { |
11 | 9 | const user = Meteor.user(); |
12 | - if ( user ) { | |
13 | - const name = user && user.profile ? user.profile.name : ''; | |
14 | - return `${ name.first } ${ name.last }`; | |
15 | - } | |
10 | + const name = user && user.profile ? user.profile.name : ''; | |
11 | + return user ? `${name.first} ${name.last}` : ''; | |
16 | 12 | }; |
17 | 13 | |
18 | 14 | export const AuthenticatedNavigation = () => ( |
... | ... | @@ -31,4 +27,4 @@ export const AuthenticatedNavigation = () => ( |
31 | 27 | </NavDropdown> |
32 | 28 | </Nav> |
33 | 29 | </div> |
34 | -) | |
30 | +); | ... | ... |
imports/ui/components/document.js
... | ... | @@ -0,0 +1,57 @@ |
1 | +import React from 'react'; | |
2 | +import { Row, Col, ListGroupItem, Input, Button } from 'react-bootstrap'; | |
3 | +import { updateDocument, removeDocument } from '../../api/documents/methods.js'; | |
4 | + | |
5 | +const handleUpdateDocument = (documentId, event) => { | |
6 | + const title = event.target.value.trim(); | |
7 | + if (title !== '' && event.keyCode === 13) { | |
8 | + updateDocument.call({ | |
9 | + _id: documentId, | |
10 | + update: { title }, | |
11 | + }, (error) => { | |
12 | + if (error) { | |
13 | + Bert.alert(error.reason, 'danger'); | |
14 | + } else { | |
15 | + Bert.alert('Document updated!', 'success'); | |
16 | + } | |
17 | + }); | |
18 | + } | |
19 | +}; | |
20 | + | |
21 | +const handleRemoveDocument = (documentId, event) => { | |
22 | + event.preventDefault(); | |
23 | + if (confirm('Are you sure? This is permanent.')) { | |
24 | + removeDocument.call({ | |
25 | + _id: documentId, | |
26 | + }, (error) => { | |
27 | + if (error) { | |
28 | + Bert.alert(error.reason, 'danger'); | |
29 | + } else { | |
30 | + Bert.alert('Document removed!', 'success'); | |
31 | + } | |
32 | + }); | |
33 | + } | |
34 | +}; | |
35 | + | |
36 | +export const Document = ({ document }) => ( | |
37 | + <ListGroupItem key={ document._id }> | |
38 | + <Row> | |
39 | + <Col xs={ 8 } sm={ 10 }> | |
40 | + <Input | |
41 | + type="text" | |
42 | + standalone | |
43 | + defaultValue={ document.title } | |
44 | + onKeyUp={ handleUpdateDocument.bind(this, document._id) } | |
45 | + /> | |
46 | + </Col> | |
47 | + <Col xs={ 4 } sm={ 2 }> | |
48 | + <Button | |
49 | + bsStyle="danger" | |
50 | + className="btn-block" | |
51 | + onClick={ handleRemoveDocument.bind(this, document._id) }> | |
52 | + Remove | |
53 | + </Button> | |
54 | + </Col> | |
55 | + </Row> | |
56 | + </ListGroupItem> | |
57 | +); | ... | ... |
imports/ui/components/documents-list.js
1 | 1 | import React from 'react'; |
2 | -import { Row, Col, ListGroup, ListGroupItem, Input, Button, Alert } from 'react-bootstrap'; | |
3 | -import { updateDocument, removeDocument } from '../../api/documents/methods.js'; | |
2 | +import { Row, Col, ListGroup, Alert } from 'react-bootstrap'; | |
3 | +import { Document } from './document.js'; | |
4 | 4 | |
5 | -const handleUpdateDocument = ( documentId, event ) => { | |
6 | - const title = event.target.value.trim(); | |
7 | - if ( title !== '' && event.keyCode === 13 ) { | |
8 | - updateDocument.call({ | |
9 | - _id: documentId, | |
10 | - update: { title: title } | |
11 | - }, ( error, response ) => { | |
12 | - if ( error ) { | |
13 | - Bert.alert( error.reason, 'danger' ); | |
14 | - } | |
15 | - }); | |
16 | - } | |
17 | -}; | |
18 | - | |
19 | -const handleRemoveDocument = ( documentId, event ) => { | |
20 | - event.preventDefault(); | |
21 | - if ( confirm( 'Are you sure? This is permanent.' ) ) { | |
22 | - removeDocument.call({ | |
23 | - _id: documentId | |
24 | - }, ( error, response ) => { | |
25 | - if ( error ) { | |
26 | - Bert.alert( error.reason, 'danger' ); | |
27 | - } else { | |
28 | - Bert.alert( 'Document removed!', 'success' ); | |
29 | - } | |
30 | - }); | |
31 | - } | |
32 | -}; | |
33 | - | |
34 | -export const DocumentsList = ( { documents } ) => { | |
35 | - if ( documents.length > 0 ) { | |
36 | - return <ListGroup className="documents-list"> | |
37 | - {documents.map( ( { _id, title } ) => { | |
38 | - return <ListGroupItem key={ _id }> | |
39 | - <Row> | |
40 | - <Col xs={ 8 } sm={ 10 }> | |
41 | - <Input | |
42 | - type="text" | |
43 | - standalone | |
44 | - defaultValue={ title } | |
45 | - onKeyUp={ handleUpdateDocument.bind( this, _id ) } | |
46 | - /> | |
47 | - </Col> | |
48 | - <Col xs={ 4 } sm={ 2 }> | |
49 | - <Button | |
50 | - bsStyle="danger" | |
51 | - className="btn-block" | |
52 | - onClick={ handleRemoveDocument.bind( this, _id ) }> | |
53 | - Remove | |
54 | - </Button> | |
55 | - </Col> | |
56 | - </Row> | |
57 | - </ListGroupItem>; | |
58 | - })} | |
59 | - </ListGroup>; | |
60 | - } else { | |
61 | - return <Alert bsStyle="warning">No documents yet.</Alert>; | |
62 | - } | |
63 | -}; | |
5 | +export const DocumentsList = ({ documents }) => ( | |
6 | + documents.length > 0 ? <ListGroup className="documents-list"> | |
7 | + {documents.map((doc) => ( | |
8 | + <Document key={ doc._id } document={ doc } /> | |
9 | + ))} | |
10 | + </ListGroup> : | |
11 | + <Alert bsStyle="warning">No documents yet.</Alert> | |
12 | +); | ... | ... |
imports/ui/components/public-navigation.js
imports/ui/containers/app-navigation.js
1 | 1 | import { composeWithTracker } from 'react-komposer'; |
2 | 2 | import { AppNavigation } from '../components/app-navigation'; |
3 | 3 | |
4 | -const composer = ( props, onData ) => { | |
5 | - onData( null, { hasUser: Meteor.user() } ); | |
4 | +const composer = (props, onData) => { | |
5 | + onData(null, { hasUser: Meteor.user() }); | |
6 | 6 | }; |
7 | 7 | |
8 | -export default composeWithTracker( composer, {}, {}, { pure: false } )( AppNavigation ); | |
8 | +export default composeWithTracker(composer, {}, {}, { pure: false })(AppNavigation); | ... | ... |
imports/ui/containers/documents-list.js
... | ... | @@ -3,12 +3,12 @@ import { composeWithTracker } from 'react-komposer'; |
3 | 3 | import { Documents } from '../../api/documents/documents.js'; |
4 | 4 | import { DocumentsList } from '../components/documents-list.js'; |
5 | 5 | |
6 | -const composer = ( params, onReady ) => { | |
7 | - const subscription = Meteor.subscribe( 'documents' ); | |
8 | - if ( subscription.ready() ) { | |
9 | - let documents = Documents.find().fetch(); | |
10 | - onReady( null, { documents } ); | |
6 | +const composer = (params, onReady) => { | |
7 | + const subscription = Meteor.subscribe('documents'); | |
8 | + if (subscription.ready()) { | |
9 | + const documents = Documents.find().fetch(); | |
10 | + onReady(null, { documents }); | |
11 | 11 | } |
12 | 12 | }; |
13 | 13 | |
14 | -export default composeWithTracker( composer )( DocumentsList ); | |
14 | +export default composeWithTracker(composer)(DocumentsList); | ... | ... |
imports/ui/layouts/app.js
... | ... | @@ -6,7 +6,7 @@ export const App = React.createClass({ |
6 | 6 | contextTypes: { |
7 | 7 | router() { |
8 | 8 | return React.PropTypes.func.isRequired; |
9 | - } | |
9 | + }, | |
10 | 10 | }, |
11 | 11 | render() { |
12 | 12 | const { isActive } = this.context.router; |
... | ... | @@ -16,5 +16,5 @@ export const App = React.createClass({ |
16 | 16 | { this.props.children } |
17 | 17 | </Grid> |
18 | 18 | </div>; |
19 | - } | |
19 | + }, | |
20 | 20 | }); | ... | ... |
imports/ui/pages/documents.js
imports/ui/pages/index.js
imports/ui/pages/login.js
... | ... | @@ -5,10 +5,10 @@ import { handleLogin } from '../../modules/login'; |
5 | 5 | |
6 | 6 | export class Login extends React.Component { |
7 | 7 | componentDidMount() { |
8 | - handleLogin( { component: this } ); | |
8 | + handleLogin({ component: this }); | |
9 | 9 | } |
10 | 10 | |
11 | - handleSubmit( event ) { | |
11 | + handleSubmit(event) { | |
12 | 12 | event.preventDefault(); |
13 | 13 | } |
14 | 14 | |
... | ... | @@ -29,7 +29,13 @@ export class Login extends React.Component { |
29 | 29 | <span className="pull-left">Password</span> |
30 | 30 | <Link className="pull-right" to="/recover-password">Forgot Password?</Link> |
31 | 31 | </label> |
32 | - <input type="password" className="form-control" ref="password" name="password" placeholder="Password" /> | |
32 | + <input | |
33 | + type="password" | |
34 | + className="form-control" | |
35 | + ref="password" | |
36 | + name="password" | |
37 | + placeholder="Password" | |
38 | + /> | |
33 | 39 | </div> |
34 | 40 | <Button type="submit" bsStyle="success">Login</Button> |
35 | 41 | </form> | ... | ... |
imports/ui/pages/not-found.js
imports/ui/pages/recover-password.js
... | ... | @@ -4,10 +4,10 @@ import { handleRecoverPassword } from '../../modules/recover-password'; |
4 | 4 | |
5 | 5 | export class RecoverPassword extends React.Component { |
6 | 6 | componentDidMount() { |
7 | - handleRecoverPassword( { component: this } ); | |
7 | + handleRecoverPassword({ component: this }); | |
8 | 8 | } |
9 | 9 | |
10 | - handleSubmit( event ) { | |
10 | + handleSubmit(event) { | |
11 | 11 | event.preventDefault(); |
12 | 12 | } |
13 | 13 | |
... | ... | @@ -15,7 +15,9 @@ export class RecoverPassword extends React.Component { |
15 | 15 | return <Row> |
16 | 16 | <Col xs={ 12 } sm={ 6 } md={ 4 }> |
17 | 17 | <h4 className="page-header">Recover Password</h4> |
18 | - <Alert bsStyle="info">Enter your email address below to receive a link to reset your password.</Alert> | |
18 | + <Alert bsStyle="info"> | |
19 | + Enter your email address below to receive a link to reset your password. | |
20 | + </Alert> | |
19 | 21 | <form ref="recoverPassword" className="recover-password" onSubmit={ this.handleSubmit }> |
20 | 22 | <Input |
21 | 23 | type="email" | ... | ... |
imports/ui/pages/reset-password.js
... | ... | @@ -6,11 +6,11 @@ export class ResetPassword extends React.Component { |
6 | 6 | componentDidMount() { |
7 | 7 | handleResetPassword({ |
8 | 8 | component: this, |
9 | - token: this.props.params.token | |
9 | + token: this.props.params.token, | |
10 | 10 | }); |
11 | 11 | } |
12 | 12 | |
13 | - handleSubmit( event ) { | |
13 | + handleSubmit(event) { | |
14 | 14 | event.preventDefault(); |
15 | 15 | } |
16 | 16 | |
... | ... | @@ -18,7 +18,10 @@ export class ResetPassword extends React.Component { |
18 | 18 | return <Row> |
19 | 19 | <Col xs={ 12 } sm={ 6 } md={ 4 }> |
20 | 20 | <h4 className="page-header">Reset Password</h4> |
21 | - <Alert bsStyle="info">To reset your password, enter a new one below. You will be logged in with your new password.</Alert> | |
21 | + <Alert bsStyle="info"> | |
22 | + To reset your password, enter a new one below. You will be logged in | |
23 | +with your new password. | |
24 | + </Alert> | |
22 | 25 | <form ref="resetPassword" className="reset-password" onSubmit={ this.handleSubmit }> |
23 | 26 | <Input |
24 | 27 | label="New Password" | ... | ... |
imports/ui/pages/signup.js
... | ... | @@ -5,10 +5,10 @@ import { handleSignup } from '../../modules/signup'; |
5 | 5 | |
6 | 6 | export class Signup extends React.Component { |
7 | 7 | componentDidMount() { |
8 | - handleSignup( { component: this } ); | |
8 | + handleSignup({ component: this }); | |
9 | 9 | } |
10 | 10 | |
11 | - handleSubmit( event ) { | |
11 | + handleSubmit(event) { | |
12 | 12 | event.preventDefault(); |
13 | 13 | } |
14 | 14 | ... | ... |
package.json
... | ... | @@ -10,12 +10,47 @@ |
10 | 10 | "production": "meteor deploy production.meteor.com --settings settings-production.json" |
11 | 11 | }, |
12 | 12 | "devDependencies": {}, |
13 | - "dependencies": { | |
13 | + "eslintConfig": { | |
14 | + "parserOptions": { | |
15 | + "ecmaFeatures": { | |
16 | + "jsx": true | |
17 | + } | |
18 | + }, | |
19 | + "plugins": [ | |
20 | + "meteor", | |
21 | + "react" | |
22 | + ], | |
23 | + "extends": [ | |
24 | + "airbnb/base", | |
25 | + "plugin:meteor/guide" | |
26 | + ], | |
27 | + "globals": { | |
28 | + "$": false, | |
29 | + "Accounts": false, | |
30 | + "Bert": false, | |
31 | + "browser": false, | |
32 | + "expect": false, | |
33 | + "Factory": false, | |
34 | + "Meteor": false, | |
35 | + "server": false, | |
36 | + "SimpleSchema": false, | |
37 | + "ValidatedMethod": false | |
38 | + }, | |
39 | + "rules": {} | |
40 | + }, | |
41 | + "devDependencies": { | |
14 | 42 | "chimp": "^0.33.0", |
15 | - "react": "^0.14.8", | |
16 | - "react-addons-pure-render-mixin": "^0.14.8", | |
43 | + "eslint": "^2.6.0", | |
44 | + "eslint-config-airbnb": "^6.2.0", | |
45 | + "eslint-plugin-meteor": "^3.4.0", | |
46 | + "eslint-plugin-react": "^4.2.3", | |
47 | + "faker": "^3.1.0" | |
48 | + }, | |
49 | + "dependencies": { | |
50 | + "react": "^15.0.1", | |
51 | + "react-addons-pure-render-mixin": "^15.0.1", | |
17 | 52 | "react-bootstrap": "^0.28.4", |
18 | - "react-dom": "^0.14.7", | |
53 | + "react-dom": "^15.0.1", | |
19 | 54 | "react-komposer": "^1.7.1", |
20 | 55 | "react-router": "^2.0.1", |
21 | 56 | "react-router-bootstrap": "^0.20.1" | ... | ... |
tests/login.js
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 ); | |
1 | +/* eslint-env mocha */ | |
2 | +/* eslint-disable func-names, prefer-arrow-callback */ | |
3 | + | |
4 | +describe('Log In', function () { | |
5 | + beforeEach(function () { | |
6 | + server.execute(function () { | |
7 | + const user = Meteor.users.findOne({ 'emails.address': 'carl.winslow@abc.com' }); | |
8 | + if (user) { | |
9 | + Meteor.users.remove(user._id); | |
7 | 10 | } |
8 | 11 | }); |
9 | 12 | }); |
10 | 13 | |
11 | - it( 'should allow us to login', function() { | |
12 | - server.execute( function() { | |
14 | + it('should allow us to login', function () { | |
15 | + server.execute(function () { | |
13 | 16 | Accounts.createUser({ |
14 | 17 | email: 'carl.winslow@abc.com', |
15 | 18 | password: 'bigguy1989', |
16 | 19 | profile: { |
17 | - name: { first: 'Carl', last: 'Winslow' } | |
18 | - } | |
20 | + name: { first: 'Carl', last: 'Winslow' }, | |
21 | + }, | |
19 | 22 | }); |
20 | 23 | }); |
21 | 24 | |
22 | - browser.url( 'http://localhost:3000/login' ) | |
23 | - .setValue( '[name="emailAddress"]', 'carl.winslow@abc.com' ) | |
24 | - .setValue( '[name="password"]', 'bigguy1989' ) | |
25 | - .submitForm( 'form' ); | |
25 | + browser.url('http://localhost:3000/login') | |
26 | + .setValue('[name="emailAddress"]', 'carl.winslow@abc.com') | |
27 | + .setValue('[name="password"]', 'bigguy1989') | |
28 | + .submitForm('form'); | |
26 | 29 | |
27 | - browser.waitForExist( '.jumbotron' ); | |
28 | - expect( browser.getUrl() ).to.equal( 'http://localhost:3000/' ); | |
30 | + browser.waitForExist('.jumbotron'); | |
31 | + expect(browser.getUrl()).to.equal('http://localhost:3000/'); | |
29 | 32 | }); |
30 | 33 | }); | ... | ... |
tests/not-found.js
1 | -describe( '404 Error', function() { | |
2 | - it( 'should render a 404 for a non-existent route', function() { | |
3 | - browser.url( 'http://localhost:3000/dididothat' ) | |
4 | - .waitForExist( '.alert-danger' ); | |
1 | +/* eslint-env mocha */ | |
2 | +/* eslint-disable func-names, prefer-arrow-callback */ | |
5 | 3 | |
6 | - expect( browser.getText( '.alert-danger p' ) ).to.equal( 'Error [404]: /dididothat does not exist.' ); | |
4 | +describe('404 Error', function () { | |
5 | + it('should render a 404 for a non-existent route', function () { | |
6 | + browser.url('http://localhost:3000/dididothat') | |
7 | + .waitForExist('.alert-danger'); | |
8 | + | |
9 | + expect(browser.getText('.alert-danger p')).to.equal('Error [404]: /dididothat does not exist.'); | |
7 | 10 | }); |
8 | 11 | }); | ... | ... |
tests/reset-password.js
... | ... | @@ -1,34 +0,0 @@ |
1 | -describe( 'Reset Password', function() { | |
2 | - beforeEach( function() { | |
3 | - server.execute( function() { | |
4 | - var user = Meteor.users.findOne( { 'emails.address': 'carl.winslow@abc.com' } ); | |
5 | - if ( user ) { Meteor.users.remove( user._id ); } | |
6 | - | |
7 | - Accounts.createUser({ | |
8 | - email: 'carl.winslow@abc.com', | |
9 | - password: 'bigguy1989', | |
10 | - profile: { | |
11 | - name: { first: 'Carl', last: 'Winslow' } | |
12 | - } | |
13 | - }); | |
14 | - }); | |
15 | - }); | |
16 | - | |
17 | - it( 'should send a recovery email when we request a reset @watch', function() { | |
18 | - browser.url( 'http://localhost:3000/recover-password' ) | |
19 | - .setValue( '[name="emailAddress"]', 'carl.winslow@abc.com' ) | |
20 | - .submitForm( 'form' ); | |
21 | - | |
22 | - let emails = server.call( 'emailStub/getEmails' ); | |
23 | - console.log( emails[0] ); // Why no value? | |
24 | - | |
25 | - // browser.url( 'http://localhost:3000' ); | |
26 | - // browser.execute( function() { | |
27 | - // Accounts.onResetPasswordLink( function( token, finished ) { | |
28 | - // expect( token ).to.equal( 'blah' ); | |
29 | - // finished(); | |
30 | - // done(); | |
31 | - // }); | |
32 | - // }); | |
33 | - }); | |
34 | -}); |
tests/signup.js
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 ); | |
1 | +/* eslint-env mocha */ | |
2 | +/* eslint-disable func-names, prefer-arrow-callback */ | |
3 | + | |
4 | +describe('Sign Up', function () { | |
5 | + beforeEach(function () { | |
6 | + server.execute(function () { | |
7 | + const user = Meteor.users.findOne({ 'emails.address': 'carl.winslow@abc.com' }); | |
8 | + if (user) { | |
9 | + Meteor.users.remove(user._id); | |
7 | 10 | } |
8 | 11 | }); |
9 | 12 | }); |
10 | 13 | |
11 | - it( 'should create a new user and login with redirect to index', 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' ); | |
14 | + it('should create a new user and login with redirect to index', function () { | |
15 | + browser.url('http://localhost:3000/signup') | |
16 | + .setValue('[name="firstName"]', 'Carl') | |
17 | + .setValue('[name="lastName"]', 'Winslow') | |
18 | + .setValue('[name="emailAddress"]', 'carl.winslow@abc.com') | |
19 | + .setValue('[name="password"]', 'bigguy1989') | |
20 | + .submitForm('form'); | |
18 | 21 | |
19 | - browser.waitForExist( '.jumbotron' ); | |
20 | - expect( browser.getUrl() ).to.equal( 'http://localhost:3000/' ); | |
22 | + browser.waitForExist('.jumbotron'); | |
23 | + expect(browser.getUrl()).to.equal('http://localhost:3000/'); | |
21 | 24 | }); |
22 | 25 | }); | ... | ... |