2013-09-18 11:55:22 -04:00
var _ = require ( 'underscore' ) ;
2013-09-08 15:57:32 -04:00
var when = require ( 'when' ) ;
var Builder = require ( '../../lib/builder' ) . Builder ;
var Common = require ( '../../lib/common' ) . Common ;
var Raw = require ( '../../lib/raw' ) . Raw ;
describe ( 'Builder' , function ( ) {
var builder ;
beforeEach ( function ( ) {
builder = new Builder ( {
query : function ( obj ) {
return when . resolve ( obj ) ;
} ,
2013-09-17 06:54:26 -04:00
grammar : require ( '../../clients/server/mysql/grammar' ) . grammar
2013-09-05 16:36:49 -04:00
} ) ;
2013-09-08 15:57:32 -04:00
} ) ;
2013-09-04 17:32:32 -04:00
2013-09-08 15:57:32 -04:00
describe ( 'constructor' , function ( ) {
2013-09-05 16:36:49 -04:00
2013-09-08 15:57:32 -04:00
it ( 'accepts the current Knex instance, attaching the client, and grammar' , function ( ) {
var grammar = { some : 'grammar' } ;
var client = { some : 'db' } ;
var knex = { client : client , grammar : grammar } ;
var reset = sinon . stub ( Builder . prototype , 'reset' ) ;
var builder = new Builder ( knex ) ;
2013-09-05 16:36:49 -04:00
2013-09-08 15:57:32 -04:00
expect ( builder . knex ) . to . eql ( knex ) ;
expect ( builder . client ) . to . eql ( client ) ;
expect ( builder . grammar ) . to . eql ( grammar ) ;
reset . should . have . been . calledOnce ;
reset . restore ( ) ;
2013-09-05 16:36:49 -04:00
} ) ;
2013-09-08 15:57:32 -04:00
} ) ;
2013-09-05 16:36:49 -04:00
2013-09-08 15:57:32 -04:00
describe ( 'from' , function ( ) {
2013-09-05 16:36:49 -04:00
2013-09-08 15:57:32 -04:00
it ( 'sets the tableName' , function ( ) {
expect ( builder . table ) . to . be . empty ;
var result = builder . from ( 'myTable' ) ;
expect ( builder . table ) . to . equal ( 'myTable' ) ;
expect ( result ) . to . equal ( builder ) ;
} ) ;
2013-09-05 16:36:49 -04:00
2013-09-08 15:57:32 -04:00
it ( 'returns the tableName when no arguments are passed' , function ( ) {
expect ( builder . table ) . to . be . empty ;
var result = builder . from ( 'myTable' ) ;
expect ( builder . from ( ) ) . to . equal ( 'myTable' ) ;
2013-09-05 16:36:49 -04:00
} ) ;
2013-09-08 15:57:32 -04:00
} ) ;
2013-09-05 16:36:49 -04:00
2013-09-08 15:57:32 -04:00
describe ( 'column' , function ( ) {
2013-09-05 16:36:49 -04:00
2013-09-08 15:57:32 -04:00
it ( 'adds a value to the columns array' , function ( ) {
expect ( builder . columns ) . to . have . length ( 0 ) ;
builder . column ( 'myColumn' ) ;
expect ( builder . columns ) . to . have . length ( 1 ) ;
2013-09-05 16:36:49 -04:00
} ) ;
2013-09-08 15:57:32 -04:00
} ) ;
2013-09-05 16:36:49 -04:00
2013-09-08 15:57:32 -04:00
describe ( 'distinct' , function ( ) {
2013-09-05 16:36:49 -04:00
2013-09-08 15:57:32 -04:00
it ( 'sets the isDistinct flag to true' , function ( ) {
builder . distinct ( 'distinctCol' ) ;
expect ( builder . columns [ 0 ] ) . to . equal ( 'distinctCol' ) ;
} ) ;
2013-09-05 16:36:49 -04:00
2013-09-08 15:57:32 -04:00
it ( 'adds the column to the columns array' , function ( ) {
builder . distinct ( 'distinctCol' ) ;
2013-09-13 10:51:12 -04:00
expect ( builder . flags . distinct ) . to . be . true ;
2013-09-05 16:36:49 -04:00
} ) ;
2013-09-08 15:57:32 -04:00
} ) ;
2013-09-05 16:36:49 -04:00
2013-09-08 15:57:32 -04:00
describe ( 'toSql' , function ( ) {
2013-09-05 16:36:49 -04:00
2013-09-08 15:57:32 -04:00
it ( 'sets the type to "select" if not otherwise set' , function ( ) {
expect ( builder . type ) . not . to . exist ;
builder . toSql ( ) ;
expect ( builder . type ) . to . equal ( 'select' ) ;
} ) ;
2013-09-05 16:36:49 -04:00
2013-09-08 15:57:32 -04:00
it ( 'compiles based on the type, passing the current context' , function ( done ) {
var compileSelect = builder . grammar . compileSelect ;
builder . grammar . compileSelect = function ( ctx ) {
expect ( ctx ) . to . eql ( builder ) ;
builder . grammar . compileSelect = compileSelect ;
done ( ) ;
} ;
builder . toSql ( ) ;
2013-09-05 16:36:49 -04:00
} ) ;
2013-09-08 15:57:32 -04:00
} ) ;
2013-09-05 16:36:49 -04:00
2013-09-13 12:59:12 -04:00
describe ( 'toString' , function ( ) {
it ( 'should properly escape the query string' , function ( ) {
var output = "select * from `items` outer join `users` on `items`.`id` = `users`.`id` where `id` = 'User' or `id` = (SELECT id from otheritems)" ;
expect ( builder
. from ( 'items' )
. join ( 'users' , function ( ) {
this . on ( 'items.id' , '=' , 'users.id' ) ;
this . type ( 'outer' ) ;
} )
. where ( 'id' , '=' , 'User' )
. orWhere ( 'id' , '=' , new Raw ( { } ) . query ( '(SELECT id from otheritems)' ) ) . toString ( ) ) . to . equal ( output ) ;
} ) ;
} ) ;
2013-09-08 15:57:32 -04:00
describe ( 'clone' , function ( ) {
2013-09-05 16:36:49 -04:00
2013-10-14 07:20:12 -04:00
it ( 'should keep the correct type when cloning the instance' , function ( ) {
var cloned = builder . insert ( { a : 'value' } ) . into ( 'tableName' ) . clone ( ) ;
expect ( cloned . type ) . to . equal ( 'insert' ) ;
} ) ;
2013-09-08 15:57:32 -04:00
} ) ;
2013-09-05 16:36:49 -04:00
2013-09-08 15:57:32 -04:00
describe ( 'reset' , function ( ) {
2013-09-05 16:36:49 -04:00
2013-09-08 15:57:32 -04:00
} ) ;
2013-09-05 16:36:49 -04:00
2013-09-08 15:57:32 -04:00
describe ( 'join' , function ( ) {
2013-09-05 16:36:49 -04:00
2013-09-08 15:57:32 -04:00
var JoinClause = require ( '../../lib/builder/joinclause' ) . JoinClause ;
2013-09-05 16:36:49 -04:00
2013-09-08 15:57:32 -04:00
it ( 'accepts the joining table, the first column, operator, second column, and (optional) type' , function ( ) {
expect ( builder . joins ) . to . have . length ( 0 ) ;
builder . from ( 'users' ) ;
builder . join ( 'accounts' , 'users.id' , '=' , 'accounts.id' ) ;
expect ( builder . joins ) . to . have . length ( 1 ) ;
expect ( builder . joins [ 0 ] ) . to . be . an . instanceOf ( JoinClause ) ;
expect ( builder . toString ( ) ) . to . equal ( "select * from `users` inner join `accounts` on `users`.`id` = `accounts`.`id`" ) ;
} ) ;
2013-09-05 16:36:49 -04:00
2013-09-08 15:57:32 -04:00
it ( 'accepts a different join type as the fifth parameter' , function ( ) {
builder . from ( 'users' ) ;
builder . join ( 'accounts' , 'users.id' , '=' , 'accounts.id' , 'left outer' ) ;
expect ( builder . toString ( ) ) . to . equal ( "select * from `users` left outer join `accounts` on `users`.`id` = `accounts`.`id`" ) ;
} ) ;
2013-09-05 16:36:49 -04:00
2013-09-08 15:57:32 -04:00
it ( 'may take a function as the second argument, for a grouped join' , function ( ) {
2013-09-05 16:36:49 -04:00
2013-09-08 15:57:32 -04:00
builder . join ( 'accounts' , function ( join ) {
expect ( builder . joins ) . to . have . length ( 0 ) ;
expect ( this ) . to . be . an . instanceOf ( JoinClause ) ;
expect ( join ) . to . be . an . instanceOf ( JoinClause ) ;
2013-09-05 16:36:49 -04:00
} ) ;
} ) ;
2013-09-08 15:57:32 -04:00
} ) ;
describe ( 'where' , function ( ) {
2013-09-05 16:36:49 -04:00
describe ( 'where' , function ( ) {
2013-09-08 15:57:32 -04:00
it ( 'should allow a function as the first argument, for a grouped where clause' , function ( ) {
builder . where ( 'id' , '=' , 1 ) ;
expect ( builder . wheres ) . to . have . length ( 1 ) ;
expect ( builder . bindings ) . to . have . length ( 1 ) ;
var subWhere = function ( qb ) {
expect ( this ) . to . equal ( qb ) ;
expect ( this ) . to . be . an . instanceOf ( Builder ) ;
this . where ( { id : 3 } ) . orWhere ( 'id' , 4 ) ;
} ;
builder . where ( subWhere ) ;
expect ( builder . bindings ) . to . have . length ( 3 ) ;
expect ( builder . wheres ) . to . have . length ( 2 ) ;
expect ( builder . from ( 'test' ) . toString ( ) ) . to . equal ( "select * from `test` where `id` = 1 and (`id` = 3 or `id` = 4)" ) ;
} ) ;
2013-09-05 16:36:49 -04:00
2013-09-08 15:57:32 -04:00
it ( 'should allow a raw instance as the first argument, which will add a whereRaw clause' , function ( ) {
builder . where ( new Raw ( { } ) . query ( 'id > ?' , 2 ) ) ;
expect ( builder . wheres ) . to . have . length ( 1 ) ;
expect ( builder . bindings ) . to . have . length ( 1 ) ;
expect ( builder . bindings [ 0 ] ) . to . equal ( 2 ) ;
} ) ;
2013-09-05 16:36:49 -04:00
2013-09-08 15:57:32 -04:00
it ( 'should allow an object as the first argument, which will assume to be a k/v pair of where "="' , function ( ) {
builder . where ( { id : 2 , name : 'Test' } ) ;
expect ( builder . wheres ) . to . have . length ( 2 ) ;
expect ( builder . bindings ) . to . have . length ( 2 ) ;
} ) ;
2013-09-05 16:36:49 -04:00
2013-09-08 15:57:32 -04:00
it ( 'should assume that if the second argument is not an operator, it should be an "="' , function ( ) {
builder . where ( 'id' , 2 ) ;
expect ( builder . wheres ) . to . have . length ( 1 ) ;
expect ( builder . bindings [ 0 ] ) . to . equal ( 2 ) ;
} ) ;
2013-09-05 16:36:49 -04:00
2013-09-08 15:57:32 -04:00
it ( 'should accept a function as the "value", for a sub select' , function ( ) {
builder . where ( 'id' , '=' , function ( qb ) {
expect ( this ) . to . equal ( qb ) ;
expect ( this ) . to . be . an . instanceOf ( Builder ) ;
this . select ( 'account_id' ) . from ( 'names' ) . where ( 'names.id' , '>' , 1 ) . orWhere ( function ( ) {
this . where ( 'names.first_name' , 'like' , 'Tim%' ) . andWhere ( 'names.id' , '>' , 10 ) ;
2013-09-05 16:36:49 -04:00
} ) ;
} ) ;
2013-09-08 15:57:32 -04:00
expect ( builder . bindings ) . to . have . length ( 3 ) ;
2013-09-13 12:59:12 -04:00
expect ( builder . toString ( ) ) . to . equal ( "select * where `id` = (select `account_id` from `names` where `names`.`id` > 1 or (`names`.`first_name` like 'Tim%' and `names`.`id` > 10))" ) ;
2013-09-08 15:57:32 -04:00
} ) ;
2013-09-05 16:36:49 -04:00
2013-09-16 10:49:30 -04:00
it ( 'should not do whereNull on where("foo", "<>", null) #76' , function ( ) {
var query = builder . where ( 'foo' , '<>' , null ) ;
expect ( query . toString ( ) ) . to . equal ( 'select * where `foo` <> NULL' ) ;
2013-09-08 15:57:32 -04:00
} ) ;
2013-09-05 16:36:49 -04:00
2013-09-16 10:49:30 -04:00
it ( 'should expand where("foo", "!=") to - where id = "!="' , function ( ) {
var query = builder . where ( 'foo' , '!=' ) ;
expect ( query . toString ( ) ) . to . equal ( "select * where `foo` = '!='" ) ;
2013-09-05 16:36:49 -04:00
} ) ;
2013-09-08 15:57:32 -04:00
} ) ;
2013-09-05 16:36:49 -04:00
2013-09-08 15:57:32 -04:00
describe ( 'whereRaw' , function ( ) {
2013-09-05 16:36:49 -04:00
2013-09-08 15:57:32 -04:00
it ( 'is called by orWhereRaw, passing the sql, bindings, and "or"' , function ( ) {
2013-09-05 16:36:49 -04:00
} ) ;
2013-09-08 15:57:32 -04:00
} ) ;
2013-09-05 16:36:49 -04:00
2013-09-08 15:57:32 -04:00
describe ( 'whereExists' , function ( ) {
2013-09-05 16:36:49 -04:00
} ) ;
2013-09-08 15:57:32 -04:00
} ) ;
2013-09-05 16:36:49 -04:00
2013-09-08 15:57:32 -04:00
describe ( 'groupBy' , function ( ) {
2013-09-05 16:36:49 -04:00
2013-09-08 15:57:32 -04:00
} ) ;
2013-09-05 16:36:49 -04:00
2013-09-08 15:57:32 -04:00
describe ( 'orderBy' , function ( ) {
2013-09-05 16:36:49 -04:00
2013-09-08 15:57:32 -04:00
} ) ;
2013-09-05 16:36:49 -04:00
2013-09-08 15:57:32 -04:00
describe ( 'union' , function ( ) {
2013-09-05 16:36:49 -04:00
2013-09-08 15:57:32 -04:00
} ) ;
2013-09-05 16:36:49 -04:00
2013-09-08 15:57:32 -04:00
describe ( 'having' , function ( ) {
2013-09-05 16:36:49 -04:00
2013-09-08 15:57:32 -04:00
} ) ;
2013-09-05 16:36:49 -04:00
2013-09-08 15:57:32 -04:00
describe ( 'offset / limit' , function ( ) {
} ) ;
2013-09-05 16:36:49 -04:00
2013-09-08 15:57:32 -04:00
describe ( 'aggregate' , function ( ) {
2013-09-05 16:36:49 -04:00
2013-09-08 15:57:32 -04:00
} ) ;
2013-09-05 16:36:49 -04:00
2013-09-08 15:57:32 -04:00
describe ( 'select' , function ( ) {
2013-09-05 16:36:49 -04:00
2013-09-08 15:57:32 -04:00
it ( 'should throw if a table has not been specified when compiling' ) ;
2013-09-05 16:36:49 -04:00
2013-09-08 15:57:32 -04:00
} ) ;
2013-09-05 16:36:49 -04:00
2013-09-08 15:57:32 -04:00
describe ( 'insert' , function ( ) {
2013-09-05 16:36:49 -04:00
2013-09-08 15:57:32 -04:00
it ( 'sets the type to insert' , function ( ) {
builder . insert ( ) ;
expect ( builder . type ) . to . equal ( 'insert' ) ;
2013-09-05 16:36:49 -04:00
} ) ;
2013-09-08 15:57:32 -04:00
it ( 'sets the values to be insert' , function ( ) {
2013-09-12 01:13:07 -04:00
var spy = sinon . spy ( builder , 'prepValues' ) ;
2013-09-08 15:57:32 -04:00
builder . insert ( { key : 1 , key2 : 2 } ) ;
spy . should . have . been . calledOnce ;
} ) ;
2013-09-05 16:36:49 -04:00
2013-09-08 15:57:32 -04:00
it ( 'sorts the values in arrays' , function ( ) {
builder . insert ( [ { key1 : 'tim' , key2 : 'test' } , { key2 : 'test2' , key1 : null } ] ) ;
expect ( _ . map ( builder . values , function ( val ) {
return _ . pluck ( val , '0' ) ;
} ) ) . to . eql ( [ [ 'key1' , 'key2' ] , [ 'key1' , 'key2' ] ] ) ;
2013-09-05 16:36:49 -04:00
} ) ;
2013-09-08 15:57:32 -04:00
it ( 'does not mutate the values being inserted' , function ( ) {
var x = [ { a : 1 } , { b : 2 } ] ;
var y = [ { a : 1 } , { b : 2 } ] ;
builder . insert ( x ) ;
expect ( x ) . to . eql ( y ) ;
} ) ;
2013-09-05 16:36:49 -04:00
2013-09-08 15:57:32 -04:00
it ( 'takes a second argument to set the isReturning, using the returning method' , function ( ) {
2013-09-13 10:51:12 -04:00
expect ( builder . flags . returning ) . to . be . empty ;
2013-09-13 17:21:20 -04:00
builder . insert ( { 'insert' : 'val' } , 'user_id' ) ;
2013-09-13 10:51:12 -04:00
expect ( builder . flags . returning ) . to . equal ( 'user_id' ) ;
2013-09-05 16:36:49 -04:00
} ) ;
2013-09-08 15:57:32 -04:00
} ) ;
2013-09-05 16:36:49 -04:00
2013-09-08 15:57:32 -04:00
describe ( 'update' , function ( ) {
it ( 'sorts the values in arrays' , function ( ) {
builder . update ( { key1 : 'tim' , key2 : 'test' } ) ;
expect ( _ . pluck ( builder . values , '0' ) ) . to . eql ( [ 'key1' , 'key2' ] ) ;
expect ( builder . bindings ) . to . have . length ( 2 ) ;
2013-09-05 16:36:49 -04:00
} ) ;
2013-09-04 17:32:32 -04:00
} ) ;
2013-09-08 15:57:32 -04:00
describe ( 'delete' , function ( ) {
} ) ;
describe ( 'truncate' , function ( ) {
} ) ;
} ) ;