-
-
Notifications
You must be signed in to change notification settings - Fork 189
/
database.spec.js
338 lines (292 loc) · 14.1 KB
/
database.spec.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
'use strict'
/**
* adonis-lucid
*
* (c) Harminder Virk <virk@adonisjs.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/* global describe, it, beforeEach, after, before */
const Database = require('../../src/Database')
const chai = require('chai')
const filesFixtures = require('./fixtures/files')
const modelFixtures = require('./fixtures/model')
const config = require('./helpers/config')
const queryHelpers = require('./helpers/query')
const expect = chai.expect
require('co-mocha')
describe('Database provider', function () {
beforeEach(function () {
Database.close()
})
before(function * () {
Database._setConfigProvider(config)
yield filesFixtures.createDir()
yield modelFixtures.up(Database)
})
after(function * () {
yield modelFixtures.down(Database)
yield modelFixtures.down(Database.connection('alternateConnection'))
Database.close()
})
it('should set config provider', function () {
Database._setConfigProvider(config)
const settings = Database._resolveConnectionKey('sqlite3')
expect(settings).to.equal('sqlite3')
})
it('should setup a knex instance of default connection', function () {
Database._setConfigProvider(config)
const instance = Database.table('users')
expect(instance.client.config.client).to.equal(process.env.DB)
})
it('should throw an error when unable to find connection property on config object', function () {
const Config = {
get: function () {
return null
}
}
Database._setConfigProvider(Config)
const fn = function () {
Database.where()
}
expect(fn).to.throw('InvalidArgumentException: E_MISSING_CONFIG: Make sure to define a connection inside the database config file')
})
it('should throw an error when unable to find connection settings using connection key', function () {
const Config = {
get: function (key) {
if (key === 'database.connection') {
return 'sqlite'
}
return null
}
}
Database._setConfigProvider(Config)
const fn = function () {
Database.where()
}
expect(fn).to.throw('InvalidArgumentException: E_MISSING_CONFIG: Unable to get database client configuration for sqlite')
})
it('should reuse the old pool if exists', function () {
Database._setConfigProvider(config)
Database.table('users')
Database.table('accounts')
const pools = Database.getConnectionPools()
expect(Object.keys(pools).length).to.equal(1)
})
it('should reuse the same connection when default connection is same as the named connection', function () {
Database._setConfigProvider(config)
Database.table('users')
Database.connection(process.env.DB).table('accounts')
const pools = Database.getConnectionPools()
expect(Object.keys(pools).length).to.equal(1)
})
it('should be able to chain all knex methods', function () {
Database._setConfigProvider(config)
const sql = Database.table('users').where('username', 'bar').toSQL().sql
expect(sql).to.equal(queryHelpers.formatQuery('select * from "users" where "username" = ?'))
})
it('should not use global scope for query chain', function () {
Database._setConfigProvider(config)
const user = Database.table('users').where('username', 'foo')
const accounts = Database.table('accounts').where('id', 1)
expect(user.toSQL().sql).to.equal(queryHelpers.formatQuery('select * from "users" where "username" = ?'))
expect(accounts.toSQL().sql).to.equal(queryHelpers.formatQuery('select * from "accounts" where "id" = ?'))
})
it('should spawn a new connection pool when connection method is used', function () {
Database._setConfigProvider(config)
Database.select()
const instance = Database.connection('alternateConnection')
expect(Object.keys(Database.getConnectionPools()).length).to.equal(2)
expect(instance.client.config.client).not.equal(undefined)
})
it('should be able to chain query incrementally', function () {
Database._setConfigProvider(config)
const user = Database.table('users')
user.where('age', 22)
user.where('username', 'virk')
expect(user.toSQL().sql).to.equal(queryHelpers.formatQuery('select * from "users" where "age" = ? and "username" = ?'))
})
it('should close a given connection', function () {
Database._setConfigProvider(config)
Database.table('users')
Database.connection('alternateConnection')
Database.close('default')
expect(Object.keys(Database.getConnectionPools()).length).to.equal(1)
})
it('should close all connection', function () {
Database._setConfigProvider(config)
Database.table('users')
Database.connection('alternateConnection')
Database.close()
expect(Object.keys(Database.getConnectionPools()).length).to.equal(0)
})
it('should be able to create lean transactions', function * () {
const trx = yield Database.beginTransaction()
yield trx.table('users').insert({username: 'db-trx'})
trx.commit()
const user = yield Database.table('users').where('username', 'db-trx')
expect(user).to.be.an('array')
expect(user[0].username).to.equal('db-trx')
})
it('should be able to rollback transactions', function * () {
const trx = yield Database.beginTransaction()
yield trx.table('users').insert({username: 'db-trx1'})
trx.rollback()
const user = yield Database.table('users').where('username', 'db-trx1')
expect(user).to.be.an('array')
expect(user.length).to.equal(0)
})
it('should be able to have multiple transactions', function * () {
const trx = yield Database.beginTransaction()
yield trx.table('users').insert({username: 'multi-trx'})
trx.commit()
const trx1 = yield Database.beginTransaction()
yield trx1.table('users').insert({username: 'multi-trx1'})
trx1.rollback()
const user = yield Database.table('users').where('username', 'multi-trx')
const user1 = yield Database.table('users').where('username', 'multi-trx1')
expect(user).to.be.an('array')
expect(user1).to.be.an('array')
expect(user.length).to.equal(1)
expect(user1.length).to.equal(0)
})
it('should be able to call beginTransaction to a different connection', function * () {
yield modelFixtures.up(Database.connection('alternateConnection'))
const trx = yield Database.connection('alternateConnection').beginTransaction()
yield trx.table('users').insert({username: 'conn2-trx'})
trx.commit()
const user = yield Database.connection('alternateConnection').table('users').where('username', 'conn2-trx')
expect(user).to.be.an('array')
expect(user.length).to.equal(1)
})
it('should be able to commit transactions automatically', function * () {
const response = yield Database.transaction(function * (trx) {
return yield trx.table('users').insert({username: 'auto-trx'}).returning('id')
})
expect(response).to.be.an('array')
expect(response.length).to.equal(1)
})
it('should rollback transactions automatically on error', function * () {
try {
yield Database.transaction(function * (trx) {
return yield trx.table('users').insert({u: 'auto-trx'})
})
expect(true).to.equal(false)
} catch (e) {
expect(e.message).not.equal(undefined)
}
})
it('should be able to run transactions on different connection', function * () {
yield Database.connection('alternateConnection').transaction(function * (trx) {
return yield trx.table('users').insert({username: 'different-trx'})
})
const user = yield Database.connection('alternateConnection').table('users').where('username', 'different-trx')
expect(user).to.be.an('array')
expect(user[0].username).to.equal('different-trx')
})
it('should be able to paginate results', function * () {
const paginatedUsers = yield Database.table('users').paginate(1)
expect(paginatedUsers).to.have.property('total')
expect(paginatedUsers).to.have.property('lastPage')
expect(paginatedUsers).to.have.property('perPage')
expect(paginatedUsers).to.have.property('data')
expect(paginatedUsers.total).to.equal(paginatedUsers.data.length)
})
it('should throw an error when page is not passed', function * () {
try {
yield Database.table('users').paginate()
expect(true).to.equal(false)
} catch (e) {
expect(e.message).to.match(/cannot paginate results for page less than 1/)
}
})
it('should throw an error when page equals 0', function * () {
try {
yield Database.table('users').paginate(0)
expect(true).to.equal(false)
} catch (e) {
expect(e.message).to.match(/cannot paginate results for page less than 1/)
}
})
it('should return proper meta data when paginate returns zero results', function * () {
const paginatedUsers = yield Database.table('users').where('status', 'published').paginate(1)
expect(paginatedUsers.total).to.equal(0)
expect(paginatedUsers.lastPage).to.equal(0)
})
it('should return proper meta data when there are results but page is over the last page', function * () {
const paginatedUsers = yield Database.table('users').paginate(10)
expect(paginatedUsers.total).to.equal(3)
expect(paginatedUsers.lastPage).to.equal(1)
})
it('should be able paginate results using order by on the original query', function * () {
const paginatedUsers = yield Database.table('users').orderBy('id', 'desc').paginate(1)
expect(paginatedUsers).to.have.property('total')
expect(paginatedUsers).to.have.property('lastPage')
expect(paginatedUsers).to.have.property('perPage')
expect(paginatedUsers).to.have.property('data')
expect(paginatedUsers.total).to.equal(paginatedUsers.data.length)
})
it('should be able to get results in chunks', function * () {
let callbackCalledForTimes = 0
const allUsers = yield Database.table('users')
yield Database.table('users').chunk(1, function (user) {
expect(user[0].id).to.equal(allUsers[callbackCalledForTimes].id)
callbackCalledForTimes++
})
expect(callbackCalledForTimes).to.equal(allUsers.length)
})
it('should be able to prefix the database table using a configuration option', function * () {
Database._setConfigProvider(config.withPrefix)
const query = Database.table('users').toSQL()
expect(queryHelpers.formatQuery(query.sql)).to.equal(queryHelpers.formatQuery('select * from "ad_users"'))
})
it('should be able to prefix the database table when table method is called after other methods', function * () {
const query = Database.where('username', 'foo').table('users').toSQL()
expect(queryHelpers.formatQuery(query.sql)).to.equal(queryHelpers.formatQuery('select * from "ad_users" where "username" = ?'))
})
it('should be able to prefix the database table when from method is used', function * () {
const query = Database.from('users').toSQL()
expect(queryHelpers.formatQuery(query.sql)).to.equal(queryHelpers.formatQuery('select * from "ad_users"'))
})
it('should be able to prefix the database table when from method is called after other methods', function * () {
const query = Database.where('username', 'foo').from('users').toSQL()
expect(queryHelpers.formatQuery(query.sql)).to.equal(queryHelpers.formatQuery('select * from "ad_users" where "username" = ?'))
})
it('should be able to prefix the database table when into method is used', function * () {
const query = Database.into('users').toSQL()
expect(queryHelpers.formatQuery(query.sql)).to.equal(queryHelpers.formatQuery('select * from "ad_users"'))
})
it('should be able to prefix the database table when into method is called after other methods', function * () {
const query = Database.where('username', 'foo').into('users').toSQL()
expect(queryHelpers.formatQuery(query.sql)).to.equal(queryHelpers.formatQuery('select * from "ad_users" where "username" = ?'))
})
it('should be able to remove the prefix using the withoutPrefix method', function * () {
const query = Database.withoutPrefix().table('users').toSQL()
expect(queryHelpers.formatQuery(query.sql)).to.equal(queryHelpers.formatQuery('select * from "users"'))
})
it('should be able to remove the prefix when withoutPrefix method is called after other methods', function * () {
const query = Database.where('username', 'foo').withoutPrefix().table('users').toSQL()
expect(queryHelpers.formatQuery(query.sql)).to.equal(queryHelpers.formatQuery('select * from "users" where "username" = ?'))
})
it('should be able to change the prefix using the withPrefix method', function * () {
const query = Database.withPrefix('k_').table('users').toSQL()
expect(queryHelpers.formatQuery(query.sql)).to.equal(queryHelpers.formatQuery('select * from "k_users"'))
})
it('should be able to remove the prefix when withPrefix method is called after other methods', function * () {
const query = Database.where('username', 'foo').withPrefix('k_').table('users').toSQL()
expect(queryHelpers.formatQuery(query.sql)).to.equal(queryHelpers.formatQuery('select * from "k_users" where "username" = ?'))
})
it('should not mess the query builder instance when withPrefix is called on multiple queries at same time', function * () {
const query = Database.where('username', 'foo').withPrefix('k_').table('users')
const query1 = Database.where('username', 'foo').table('users')
expect(queryHelpers.formatQuery(query.toSQL().sql)).to.equal(queryHelpers.formatQuery('select * from "k_users" where "username" = ?'))
expect(queryHelpers.formatQuery(query1.toSQL().sql)).to.equal(queryHelpers.formatQuery('select * from "ad_users" where "username" = ?'))
})
it('should not mess the query builder instance when withoutPrefix is called on multiple queries at same time', function * () {
const query = Database.where('username', 'foo').withoutPrefix().table('users')
const query1 = Database.where('username', 'foo').table('users')
expect(queryHelpers.formatQuery(query.toSQL().sql)).to.equal(queryHelpers.formatQuery('select * from "users" where "username" = ?'))
expect(queryHelpers.formatQuery(query1.toSQL().sql)).to.equal(queryHelpers.formatQuery('select * from "ad_users" where "username" = ?'))
})
})