Issues (13)

test/mdb.spec.js (3 issues)

1
import mongoose from 'mongoose'
2
import chai from 'chai'
3
import sinon from 'sinon'
4
import User from '../models/user'
5
import { allUsers } from '../app/user'
6
import factories from './factories'
7
8
const expect = chai.expect
9
10
describe('Mongoose Database test', () => {
11
	// Before starting this test, we will create a sandboxed database connection
12
	// Once connection is done, invoke done()
13
14
	before((done) => {
15
		mongoose.Promise = require('bluebird')
16
		mongoose.connect('mongodb://localhost/testApp')
17
		const db = mongoose.connection
18
		db.on('error', () => console.error.bind(console, 'connection error!!'))
19
			.once('open', () => {
20
				console.log('We are connected to database.')
21
				done()
22
			})
23
	})
24
25
	// Test mongoose model ( required: true )
26
	describe('Mongoose model test', () => {
27
		it('Should be invalid if name is empty', done => {
28
			var user = new User()
29
			user.validate(err => {
30
				expect(err.errors.name).to.exist
31
				done()
32
			})
33
		})
34
	
35
		// if canPost = true, isAdmin = false then, canPost is required
36
		it('Should have validation error for canPost if not isAdmin', (done) => {
37
			const user = new User({ canPost: true })
38
39
			user.validate(err => {
40
				expect(err.errors.canPost).to.exist
41
				done()
42
			})
43
		})
44
45
		// if canPost = true, isAdmin = true then, canPost is not required
46
		it('should be valid canPost when isAdmin', done => {
47
			const user = new User({ isAdmin: true, canPost: true})
48
			
49
			user.validate(err => {
50
				expect(err.errors.canPost).to.not.exist
51
				done()
52
			})
53
		})
54
	})
55
56
57
	// Testing model instance methods
58
	describe('Testing model instance methods', () => {
59
		/*
60
		*  You’d typically have two kinds of instance methods on your models:
61
		*  1) Instance methods which do not access the database
62
		*  2) Instance methods which access the database
63
		*/
64
65
		beforeEach(function() {
66
			sinon.stub(User, 'findOne')
67
		})
68
	
69
	
70
		afterEach(function() {
71
			User.findOne.restore()
72
		})
73
74
		// Testing the checkForCanPost method
75
		it('Should check for canpost with the same name', () => {
76
			
77
			/*
78
			 *  This is the function that would get called,
79
			 *  so we stub it out so it doesn’t do any database access.
80
			 *  Stubbing it also allows us to use Sinon to check whether it was called with the
81
			 *  correct parameters.
82
			*/
83
			User.findOne
84
85
			const expectedName = 'This name should be used in the check'
86
			const user = new User({ name: expectedName })
87
88
			user.checkForCanPost(() => {})
89
			
90
			/*
91
			 *  we use sinon.assert.calledWith to check the stubbed finder was called correctly.
92
			*/
93
			sinon.assert.calledWith(User.findOne, {
94
				name: expectedName,
95
				canPost: true
96
			})
97
		})
98
		
99
		//  another test for this to confirm the result from findOne is handled correctly
100
		it('should call back with true when canPost exists', done => {
101
			const canPostObject = { name: 'Madhav'}
102
103
			/*
104
			 *  The yields function on a stub makes it automatically call any callback function
105
			 *  with a certain set of parameters – in this case, we’re passing null to signify
106
			 *  no error, and the cannPostObject to act as a found Mongoose model.
107
			*/
108
			User.findOne.yields(null, canPostObject)
109
			const user = new User({ name: 'Some name' })
110
111
			/*
112
			 *  This time we use a callback in checkForCanPost to do the assertion, as we want to
113
			 *  ensure it was called with the correct value.
114
			*/
115
			user.checkForCanPost(function(hasCanPost) {
116
				expect(hasCanPost).to.be.true
117
				done()
118
			})
119
		})
120
121
122
123
	})
124
125
	describe('Mongoose database external functions test', () => {
126
		beforeEach(function() {
127
			sinon.stub(User, 'find')
128
		})
129
	
130
	
131
		afterEach(function() {
132
			User.find.restore()
133
		})
134
		// Should send all users
135
		it('Should send all users', () => {
136
			const a = factories.validUser
137
			const b = factories.validUser
138
			const expectedModels = [a, b]
139
			User.find.yields(null, expectedModels)
140
			const req = { params: { } }
141
			const res = {
142
				send: sinon.stub()
143
			}
144
145
			allUsers(req, res)
146
			sinon.assert.calledWith(res.send, expectedModels)
147
		})
148
149
		/*
150
		 * In this one we’re setting up some expeced data – in this case, the expected list of models
151
		 *  the find function should return. We also set up the stub to yield the result.
152
		*/
153
		it('Should query for cannot post if set as request parameter', () => {
154
			User.find.yields(null, [])
155
			const req = {
156
				params: {
157
					canPost: true
158
				}
159
			}
160
161
			const res = { send: sinon.stub() }
162
163
			allUsers(req, res)
164
			sinon.assert.calledWith(User.find, { canPost: true })
165
		})
166
	})
167
168
169
	// Now we test the database
170
	describe('Mongoose Database Test', () => {
171
		
172
		// save object with 'name' value of 'John'
173
		it('Should save new name to test database', (done) => {
174
			const testUser = User({
175
				name: 'John'
176
			})
177
			testUser.save(done)
178
		})
179
180
		// Dont save incorrect object to database
181
		it('Should not save wrong object data', (done) => {
182
			const wrongUser = User({
183
				notName: 'Somebody else'
184
			})
185
186
			wrongUser.save(err => {
187
				if (err) return done()
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
188
				throw new Error('Should generate error..')
189
			})
190
		})
191
192
		// Retrieve data from test database
193
		it('Should retrieve data from test database', (done) => {
194
			User.find({ name: 'John' }, (err, user) => {
195
				if (err) throw err
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
196
				if(user.length == 0) throw new Error('No data')
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
197
				done()
198
			})
199
		})
200
201
		// After all test is done drop database and close connection
202
		after(done => {
203
			mongoose.connection.db.dropDatabase(() => {
204
				mongoose.connection.close(done)
205
			})
206
		})
207
	})
208
})
209
210
211