Skip to content

Commit 1e10941

Browse files
committed
Test specificity improved for reducer, compose function, auth actions, populate utils, and events utils.
1 parent c5727ce commit 1e10941

File tree

9 files changed

+234
-66
lines changed

9 files changed

+234
-66
lines changed

src/actions/auth.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -267,7 +267,7 @@ export const createUser = (dispatch, firebase, { email, password, signIn }, prof
267267

268268
if (!email || !password) {
269269
dispatchLoginError(dispatch, new Error('Email and Password are required to create user'))
270-
return Promise.reject('Email and Password are Required')
270+
return Promise.reject(new Error('Email and Password are Required'))
271271
}
272272

273273
return firebase.auth()
@@ -311,7 +311,7 @@ export const resetPassword = (dispatch, firebase, email) => {
311311
.catch((err) => {
312312
if (err) {
313313
switch (err.code) {
314-
case 'INVALID_USER':
314+
case 'auth/user-not-found':
315315
dispatchLoginError(dispatch, new Error('The specified user account does not exist.'))
316316
break
317317
default:

src/compose.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,9 +114,9 @@ export default (config, otherConfig) => next =>
114114
// Expose Firebase instance
115115
export const getFirebase = () => {
116116
// TODO: Handle recieveing config and creating firebase instance if it doesn't exist
117+
/* istanbul ignore next: Firebase instance always exists during tests */
117118
if (!firebaseInstance) {
118-
console.error('Firebase instance does not yet exist. Check your compose function.') // eslint-disable-line no-console
119-
return null
119+
throw new Error('Firebase instance does not yet exist. Check your compose function.') // eslint-disable-line no-console
120120
}
121121
return firebaseInstance
122122
}

src/utils/events.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ export const getEventsFromInput = paths =>
5656
}
5757

5858
if (isObject(path)) {
59-
if (!path) {
59+
if (!path.path) {
6060
throw new Error('Path is a required parameter within definition object')
6161
}
6262
if (!path.type) {

src/utils/populate.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -76,10 +76,10 @@ export const promisesForPopulate = (firebase, originalData, populates) => {
7676
if (isString(idOrList)) {
7777
return promisesArray.push(
7878
getPopulateChild(firebase, p, idOrList)
79-
.then((v) =>
80-
// replace parameter with loaded object
81-
set(originalData, `${key}.${p.child}`, v)
82-
)
79+
.then((v) =>
80+
// replace parameter with loaded object
81+
set(originalData, `${key}.${p.child}`, v)
82+
)
8383
)
8484
}
8585

test/unit/actions/auth.spec.js

Lines changed: 84 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,8 @@ import {
1414
} from '../../../src/actions/auth'
1515
let functionSpy
1616
let dispatchSpy
17-
const dispatch = () => {
18-
console.log('dispatch')
19-
}
20-
17+
const dispatch = sinon.spy()
18+
const fakeLogin = { email: '[email protected]', password: 'asdfasdf' }
2119
const fakeFirebase = {
2220
_: {
2321
authUid: '123',
@@ -40,8 +38,10 @@ const fakeFirebase = {
4038
},
4139
signOut: () =>
4240
Promise.resolve({}),
43-
createUserWithEmailAndPassword: () =>
44-
Promise.resolve({ uid: '123', email: '[email protected]', providerData: [{}] }),
41+
createUserWithEmailAndPassword: (email, password) =>
42+
email === 'error'
43+
? Promise.reject({ code: 'asdfasdf' })
44+
: Promise.resolve({ uid: '123', email: '[email protected]', providerData: [{}] }),
4545
signInWithCustomToken: () => {
4646
return Promise.resolve({
4747
toJSON: () => ({
@@ -51,7 +51,19 @@ const fakeFirebase = {
5151
uid: 'asdfasdfsdf'
5252
})
5353
})
54-
}
54+
},
55+
signInWithEmailAndPassword: (email, password) =>
56+
email.indexOf('error2') !== -1
57+
? Promise.reject({ code: 'asdfasdf' })
58+
: email === 'error3'
59+
? Promise.reject({ code: 'auth/user-not-found' })
60+
: Promise.resolve({ uid: '123', email: '[email protected]', providerData: [{}] }),
61+
sendPasswordResetEmail: (email) =>
62+
email === 'error'
63+
? Promise.reject({code: 'auth/user-not-found'})
64+
: email === 'error2'
65+
? Promise.reject({code: 'asdfasdf'})
66+
: Promise.resolve({some: 'val'})
5567
})
5668
}
5769

@@ -87,6 +99,9 @@ describe('Actions: Auth', () => {
8799
})
88100

89101
describe('watchUserProfile', () => {
102+
beforeEach(() => {
103+
functionSpy = sinon.spy()
104+
})
90105
it('calls profile unwatch', () => {
91106
watchUserProfile(dispatch, fakeFirebase)
92107
expect(firebase._.profileWatch).to.be.a.function
@@ -95,6 +110,17 @@ describe('Actions: Auth', () => {
95110
watchUserProfile(dispatch, firebase)
96111
expect(firebase._.profileWatch).to.be.a.function
97112
})
113+
it('sets populates using array', () => {
114+
firebase._.config.profileParamsToPopulate = ['asdfasdf']
115+
watchUserProfile(dispatch, firebase)
116+
expect(firebase._.profileWatch).to.be.a.function
117+
})
118+
it('sets populates using string', () => {
119+
firebase._.config.profileParamsToPopulate = 'asdfasdf'
120+
watchUserProfile(dispatch, firebase)
121+
expect(firebase._.profileWatch).to.be.a.function
122+
})
123+
98124
})
99125

100126
describe('createUserProfile', () => {
@@ -108,7 +134,7 @@ describe('Actions: Auth', () => {
108134

109135
describe('login', () => {
110136
it('handles invalid email login', () => {
111-
return login(dispatch, firebase, { email: '[email protected]', password: 'asdfasdf' })
137+
return login(dispatch, firebase, fakeLogin)
112138
.catch((err) => {
113139
expect(err.code).to.equal('auth/user-not-found')
114140
})
@@ -141,10 +167,7 @@ describe('Actions: Auth', () => {
141167
expect(functionSpy).to.have.been.calledOnce
142168
})
143169
})
144-
it('calls firebase.auth().signOut()', () => {
145-
logout(dispatch, firebase)
146-
expect(functionSpy).to.have.been.calledOnce
147-
})
170+
148171
it('sets authUid to null', () => {
149172
fakeFirebase._.authUid = 'asdfasdf'
150173
return logout(dispatch, fakeFirebase)
@@ -162,41 +185,68 @@ describe('Actions: Auth', () => {
162185
})
163186

164187
describe('createUser', () => {
165-
// Skipped because of TypeError: Cannot read property 'apply' of undefined
166-
it.skip('creates user', () => {
167-
return createUser(dispatch, fakeFirebase, { email: '[email protected]', password: 'asdf' }, { email: '[email protected]', password: 'asdf' })
188+
it('creates user', () =>
189+
createUser(dispatch, fakeFirebase, fakeLogin, fakeLogin)
168190
.then(userData => {
169191
expect(userData).to.be.an.object
170192
})
171-
})
172-
it('handles no email', () => {
173-
return createUser(dispatch, fakeFirebase, { password: 'asdf' })
193+
)
194+
it('creates user without profile', () =>
195+
createUser(dispatch, fakeFirebase, fakeLogin)
196+
.then(userData => {
197+
expect(userData).to.be.an.object
198+
})
199+
)
200+
it('handles no email', () =>
201+
createUser(dispatch, fakeFirebase, { password: fakeLogin.password })
174202
.catch((err) => {
175-
expect(err).to.be.a.string
203+
expect(err).to.be.an.object
176204
})
177-
})
178-
it('handles no password', () => {
179-
return createUser(dispatch, fakeFirebase, { email: '[email protected]' })
205+
)
206+
it('handles no password', () =>
207+
createUser(dispatch, fakeFirebase, { email: fakeLogin.email })
180208
.catch((err) => {
181-
expect(err).to.be.a.string
209+
expect(err).to.be.an.object
182210
})
183-
})
184-
}, 4000)
211+
)
212+
it('handles error with createUserWithEmailAndPassword', () =>
213+
createUser(dispatch, fakeFirebase, { email: 'error', password: 'error' })
214+
.catch((err) => {
215+
expect(err).to.be.an.object
216+
})
217+
)
218+
it('handles error with login', () =>
219+
createUser(dispatch, fakeFirebase, { email: 'error2', password: 'error2' })
220+
.catch((err) => {
221+
expect(err).to.be.an.object
222+
})
223+
)
224+
it('handles user-not-found error', () =>
225+
createUser(dispatch, fakeFirebase, { email: 'error3', password: 'error2' })
226+
.catch((err) => {
227+
expect(err).to.be.an.object
228+
})
229+
)
230+
})
185231

186232
describe('resetPassword', () => {
187-
beforeEach(() => {
188-
functionSpy = sinon.spy(firebase.auth(), 'sendPasswordResetEmail')
189-
})
190-
afterEach(() => {
191-
firebase.auth().sendPasswordResetEmail.restore()
233+
it('resets password for real user', () => {
234+
return resetPassword(dispatch, fakeFirebase, '[email protected]')
235+
.catch((err) => {
236+
expect(err.code).to.equal('auth/user-not-found')
237+
})
192238
})
193239
it('dispatches error for invalid user', () => {
194-
return resetPassword(dispatch, firebase, '[email protected]')
240+
return resetPassword(dispatch, fakeFirebase, 'error')
195241
.catch((err) => {
196-
console.log('error', err)
197242
expect(err.code).to.equal('auth/user-not-found')
198-
expect(functionSpy).to.have.been.calledOnce
199243
})
200-
}, 4000)
244+
})
245+
it('dispatches for all other errors', () => {
246+
return resetPassword(dispatch, fakeFirebase, 'error2')
247+
.catch((err) => {
248+
expect(err.code).to.be.a.string
249+
})
250+
})
201251
})
202252
})

test/unit/compose.spec.js

Lines changed: 98 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
/* global describe expect it */
22
import { omit } from 'lodash'
33
import { createStore, combineReducers, compose } from 'redux'
4-
import composeFunc from '../../src/compose'
4+
import composeFunc, { getFirebase } from '../../src/compose'
55
const exampleData = { data: { some: 'data' } }
6-
const reducer = () => console.log('reducer', {})
6+
const reducer = sinon.spy()
77
const generateCreateStore = (params) =>
88
compose(composeFunc(
9-
omit(fbConfig, params),
9+
params ? omit(fbConfig, params) : fbConfig,
1010
{ userProfile: 'users', enableLogging: true }
1111
))(createStore)
12+
const helpers = generateCreateStore()(reducer).firebase.helpers
1213

1314
describe('Compose', () => {
1415
it('is a function', () => {
@@ -18,23 +19,108 @@ describe('Compose', () => {
1819
expect(composeFunc(fbConfig)).to.be.a.function
1920
})
2021
it('allows enabling of Firebase database logging', () => {
21-
const createStoreWithFirebase = compose(composeFunc(
22-
fbConfig,
23-
{ userProfile: 'users', enableLogging: true }
24-
))(createStore)
25-
expect(createStoreWithFirebase(reducer)).to.be.an.object
22+
expect(generateCreateStore()(reducer))
23+
.to.be.an.object
24+
})
25+
26+
describe('helpers', () => {
27+
describe('set', () =>
28+
helpers.set('test', {some: 'asdf'})
29+
)
30+
31+
describe('push', () =>
32+
helpers.push('test', {some: 'asdf'})
33+
)
34+
35+
describe('update', () =>
36+
helpers.update('test', {some: 'asdf'})
37+
)
38+
39+
describe('uniqueSet', () =>{
40+
// remove test root after test are complete
41+
after(() =>
42+
helpers.remove('test')
43+
)
44+
it('sets if unique', () =>
45+
helpers.uniqueSet('test/unique', {some: 'asdf'})
46+
)
47+
it('throws if not unique', () =>
48+
helpers.uniqueSet('test', {some: 'asdf'})
49+
.catch((err) => {
50+
expect(err.toString()).to.equal('Error: Path already exists.')
51+
})
52+
)
53+
it('has on err onComplete', () => {
54+
const func = sinon.spy()
55+
helpers.uniqueSet('test', {some: 'asdf'}, func)
56+
.catch((err) => {
57+
expect(func).to.have.been.calledOnce
58+
})
59+
})
60+
})
61+
62+
describe('remove', () =>
63+
helpers.remove('test')
64+
)
65+
66+
describe('watchEvent', () =>
67+
helpers.watchEvent('value', 'test')
68+
)
69+
70+
describe('unWatchEvent', () =>
71+
helpers.unWatchEvent('value', 'test')
72+
)
73+
74+
describe('login', () => {
75+
try {
76+
helpers.login({ email: 'test' })
77+
} catch (err) {
78+
expect(err).to.be.an.object
79+
}
80+
})
81+
82+
describe('logout', () =>
83+
helpers.logout()
84+
)
85+
86+
describe('createUser', () =>
87+
helpers.createUser({ email: 'test' }, { email: 'test' })
88+
)
89+
90+
describe('resetPassword', () => {
91+
try {
92+
helpers.resetPassword({ email: 'test' })
93+
} catch (err) {
94+
expect(err).to.be.an.object
95+
}
96+
})
97+
describe('storage', () => {
98+
try {
99+
helpers.storage()
100+
} catch(err) {
101+
expect(err).to.be.an.object
102+
}
103+
})
26104
})
27-
describe('throws for missing fbConfig parameters', () => {
28105

106+
describe('throws for missing fbConfig parameters', () => {
29107
it('databaseURL', () => {
30-
expect(() => generateCreateStore('databaseURL')(reducer)).to.throw('Firebase databaseURL is required')
108+
expect(() => generateCreateStore('databaseURL')(reducer))
109+
.to.throw('Firebase databaseURL is required')
31110
})
32111
it('authDomain', () => {
33-
expect(() => generateCreateStore('authDomain')(reducer)).to.throw('Firebase authDomain is required')
112+
expect(() => generateCreateStore('authDomain')(reducer))
113+
.to.throw('Firebase authDomain is required')
34114
})
35115
it('apiKey', () => {
36-
expect(() => generateCreateStore('apiKey')(reducer)).to.throw('Firebase apiKey is required')
116+
expect(() => generateCreateStore('apiKey')(reducer))
117+
.to.throw('Firebase apiKey is required')
37118
})
38119
})
39120

121+
describe('getFirebase', () => {
122+
it('exports firebase instance', () => {
123+
expect(getFirebase()).to.be.an.object
124+
})
125+
})
40126
})

0 commit comments

Comments
 (0)