不要怂,就是干,撸起袖子干!

Commit 194a42c2 by Sascha Depold

Merge pull request #772 from durango/buster

Got rid of Jasmine in favor of Buster.
2 parents 7ea02763 e55bbe96
Showing with 3492 additions and 3894 deletions
{
"globals": {
"jasmine": false,
"spyOn": false,
"it": false,
"console": false,
......
......@@ -4,7 +4,6 @@ before_script:
script:
- "npm run test-buster-travis"
- "npm run test-jasmine"
notifications:
email:
......
......@@ -140,9 +140,7 @@ $ npm install
### 4. Run the tests ###
Right now, the test base is split into the `spec` folder (which contains the
lovely [BusterJS](http://busterjs.org) tests) and the `spec-jasmine` folder
(which contains the ugly and awkward node-jasmine based tests). A main goal
is to get rid of the jasmine tests!
lovely [BusterJS](http://busterjs.org) tests).
As you might haven't installed all of the supported SQL dialects, here is how
to run the test suites for your development environment:
......@@ -151,9 +149,6 @@ to run the test suites for your development environment:
$ # run all tests at once:
$ npm test
$ # run only the jasmine tests (for all dialects):
$ npm run test-jasmine
$ # run all of the buster specs (for all dialects):
$ npm run test-buster
......@@ -237,7 +232,6 @@ for (var key in obj) {
```js
{
"globals": {
"jasmine": false,
"spyOn": false,
"it": false,
"console": false,
......
......@@ -111,7 +111,7 @@ SqlString.dateToString = function(date, timeZone, dialect) {
// TODO: Ideally all dialects would work a bit more like this
if (dialect === "postgres") {
return moment(dt).format("YYYY-MM-DD HH:mm:ss.SSS Z");
return moment(dt).zone('+00:00').format("YYYY-MM-DD HH:mm:ss.SSS Z");
}
if (timeZone !== 'local') {
......
......@@ -44,7 +44,6 @@
"promise": "~3.2.0"
},
"devDependencies": {
"jasmine-node": "~1.10.2",
"sqlite3": "~2.1.12",
"mysql": "~2.0.0-alpha8",
"pg": "~2.1.0",
......@@ -61,8 +60,7 @@
],
"main": "index",
"scripts": {
"test": "npm run test-jasmine && npm run test-buster",
"test-jasmine": "jasmine-node spec-jasmine/",
"test": "npm run test-buster",
"test-buster": "npm run test-buster-mysql && npm run test-buster-postgres && npm run test-buster-postgres-native && npm run test-buster-sqlite",
"test-buster-travis": "buster-test",
"test-buster-mysql": "DIALECT=mysql buster-test",
......
module.exports = {
up: function(migration, DataTypes) {
migration.createTable('Person', {
name: DataTypes.STRING,
isBetaMember: {
type: DataTypes.BOOLEAN,
defaultValue: false,
allowNull: false
}
})
},
down: function(migration) {
migration.dropTable('Person')
}
}
module.exports = {
up: function() {},
down: function() {}
}
module.exports = {
up: function(migration, DataTypes) {
migration.renameTable('Person', 'User')
},
down: function(migration, DataTypes) {
migration.renameTable('User', 'Person')
}
}
module.exports = {
up: function(migration, DataTypes) {
migration.addColumn('User', 'signature', DataTypes.TEXT)
migration.addColumn('User', 'shopId', { type: DataTypes.INTEGER, allowNull: true })
migration.addColumn('User', 'isAdmin', { type: DataTypes.BOOLEAN, defaultValue: false, allowNull: false })
},
down: function(migration, DataTypes) {
migration.removeColumn('User', 'signature')
migration.removeColumn('User', 'shopId')
migration.removeColumn('User', 'isAdmin')
}
}
module.exports = {
up: function(migration, DataTypes) {
migration.removeColumn('User', 'shopId')
},
down: function(migration, DataTypes) {
migration.addColumn('User', 'shopId', { type: DataTypes.INTEGER, allowNull: true })
}
}
module.exports = {
up: function(migration, DataTypes) {
migration.changeColumn('User', 'signature', {
type: DataTypes.STRING,
allowNull: false,
defaultValue: 'Signature'
})
},
down: function(migration, DataTypes) {}
}
module.exports = {
up: function(migration, DataTypes) {
migration.renameColumn('User', 'signature', 'sig')
},
down: function(migration, DataTypes) {
migration.renameColumn('User', 'sig', 'signature')
}
}
module.exports = function(sequelize, DataTypes) {
return sequelize.define('Project' + parseInt(Math.random() * 9999999999999999), {
name: DataTypes.STRING
})
}
\ No newline at end of file
var config = require("../config/config")
, Sequelize = require("../../index")
, sequelize = new Sequelize(config.mysql.database, config.mysql.username, config.mysql.password, { pool: config.mysql.pool, logging: false, host: config.mysql.host, port: config.mysql.port })
, Helpers = new (require("../config/helpers"))(sequelize)
describe('BelongsTo', function() {
var User = null
, Task = null
var setup = function() {
User = sequelize.define('User', { username: Sequelize.STRING, enabled: {
type: Sequelize.BOOLEAN,
defaultValue: true
}})
Task = sequelize.define('Task', { title: Sequelize.STRING })
}
beforeEach(function() { Helpers.dropAllTables(); setup() })
afterEach(function() { Helpers.dropAllTables() })
it('adds the foreign key', function() {
Task.belongsTo(User)
expect(Task.attributes['UserId']).toEqual("INTEGER")
})
it("underscores the foreign key", function() {
Task = sequelize.define('Task', { title: Sequelize.STRING }, {underscored: true})
Task.belongsTo(User)
expect(Task.attributes['user_id']).toEqual("INTEGER")
})
it("uses the passed foreign key", function() {
Task.belongsTo(User, {foreignKey: 'person_id'})
expect(Task.attributes['person_id']).toEqual("INTEGER")
})
it("defines getters and setters", function() {
Task.belongsTo(User)
var task = Task.build({title: 'asd'})
expect(task.setUser).toBeDefined()
expect(task.getUser).toBeDefined()
})
it("aliases the getters and setters according to the passed 'as' option", function() {
Task.belongsTo(User, {as: 'Person'})
var task = Task.build({title: 'asd'})
expect(task.setPerson).toBeDefined()
expect(task.getPerson).toBeDefined()
})
it("aliases associations to the same table according to the passed 'as' option", function() {
Task.belongsTo(User, {as: 'Poster'})
Task.belongsTo(User, {as: 'Owner'})
var task = Task.build({title: 'asd'})
expect(task.getPoster).toBeDefined()
expect(task.setPoster).toBeDefined()
expect(task.getOwner).toBeDefined()
expect(task.setOwner).toBeDefined()
})
it("intializes the foreign key with null", function() {
Task.belongsTo(User)
var task = Task.build({title: 'asd'})
expect(task['UserId']).not.toBeDefined();
})
it("sets and gets the correct objects", function() {
Task.belongsTo(User, {as: 'User'})
Helpers.async(function(done) {
User.sync({force: true}).success(function() {
Task.sync({force: true}).success(done)
})
})
Helpers.async(function(done) {
User.create({username: 'asd'}).success(function(u) {
Task.create({title: 'a task'}).success(function(t) {
t.setUser(u).success(function() {
t.getUser().success(function(user) {
expect(user.username).toEqual('asd')
done()
})
})
})
})
})
})
it('extends the id where param with the supplied where params', function() {
Task.belongsTo(User, {as: 'User'})
Helpers.async(function(done) {
User.sync({force: true}).success(function() {
Task.sync({force: true}).success(done)
})
})
Helpers.async(function(done) {
User.create({username: 'asd', enabled: false}).success(function(u) {
Task.create({title: 'a task'}).success(function(t) {
t.setUser(u).success(function() {
t.getUser({where: {enabled: true}}).success(function(user) {
expect(user).toEqual(null)
done()
})
})
})
})
})
})
it("handles self associations", function() {
Helpers.async(function(done) {
var Person = sequelize.define('Person', { name: Sequelize.STRING })
Person.belongsTo(Person, {as: 'Mother', foreignKey: 'MotherId'})
Person.belongsTo(Person, {as: 'Father', foreignKey: 'FatherId'})
Person.sync({force: true}).success(function() {
var p = Person.build()
expect(p.setFather).toBeDefined()
expect(p.setMother).toBeDefined()
done()
})
})
})
it("sets the foreign key in self associations", function() {
var Person = sequelize.define('Person', { name: Sequelize.STRING })
Person.belongsTo(Person, {as: 'Mother'})
expect(Person.associations.MotherPersons.options.foreignKey).toEqual('MotherId')
})
})
var config = require("../config/config")
, Sequelize = require("../../index")
, sequelize = new Sequelize(config.mysql.database, config.mysql.username, config.mysql.password, { pool: config.mysql.pool, logging: false, host: config.mysql.host, port: config.mysql.port })
, Helpers = new (require("../config/helpers"))(sequelize)
describe('HasMany', function() {
var User = null
, Task = null
, sequelize = null
, Helpers = null
var setup = function() {
sequelize = new Sequelize(config.mysql.database, config.mysql.username, config.mysql.password, { pool: config.mysql.pool, logging: false, host: config.mysql.host, port: config.mysql.port })
Helpers = new (require("../config/helpers"))(sequelize)
Helpers.dropAllTables()
User = sequelize.define('User', { username: Sequelize.STRING })
Task = sequelize.define('Task', { title: Sequelize.STRING })
}
beforeEach(function() { setup() })
afterEach(function() { Helpers.dropAllTables() })
describe('mono-directional', function() {
it("adds the foreign key", function() {
User.hasMany(Task)
expect(Task.attributes.UserId).toEqual("INTEGER")
})
it('adds the foreign key with underscore', function() {
User = sequelize.define('User', { username: Sequelize.STRING })
Task = sequelize.define('Task', { title: Sequelize.STRING }, { underscored: true })
Task.hasMany(User)
expect(User.attributes.task_id).toBeDefined()
})
it('uses the passed foreign key', function() {
User.hasMany(Task, { foreignKey: 'person_id' })
expect(Task.attributes.person_id).toEqual("INTEGER")
})
it('defines getters and setters', function() {
User.hasMany(Task)
var u = User.build({username: 'asd'})
expect(u.setTasks).toBeDefined()
expect(u.getTasks).toBeDefined()
})
it("defines getters and setters according to the 'as' option", function() {
User.hasMany(Task, {as: 'Tasks'})
var u = User.build({username: 'asd'})
expect(u.setTasks).toBeDefined()
expect(u.getTasks).toBeDefined()
})
it("sets and gets associated objects", function() {
var user, task1, task2;
User.hasMany(Task, { as: 'Tasks' })
Helpers.async(function(done) {
User.sync({ force: true }).success(function() {
Task.sync({ force: true }).success(done)
})
})
Helpers.async(function(done) {
User.create({username: 'name'}).success(function(_user) {
Task.create({title: 'task1'}).success(function(_task1) {
Task.create({title: 'task2'}).success(function(_task2) {
user = _user
task1 = _task1
task2 = _task2
done()
})
})
})
})
Helpers.async(function(done) {
user.setTasks([task1, task2]).success(function() {
user.getTasks().success(function(tasks) {
expect(tasks.length).toEqual(2)
user.getTasks({attributes: ['title']}).success(function(tasks) {
expect(tasks[0].selectedValues.title).toEqual('task1')
expect(tasks[0].selectedValues.id).toEqual(null)
done()
})
})
})
})
})
it("should allow selfAssociation to be single linked (only one DAO is created)", function() {
var oldLength = sequelize.daoFactoryManager.daos.length;
var Comment = sequelize.define('Comment', { content: Sequelize.STRING })
Comment.belongsTo(Comment, {as: "Parent"});
Comment.hasMany(Comment, {as: 'Children', foreignKey: "ParentId", useJunctionTable: false})
expect(sequelize.daoFactoryManager.daos.length).toEqual(oldLength + 1)
Helpers.async(function(done) {
Comment.sync({force: true}).success(function() {
done()
})
})
var parent
Helpers.async(function(done) {
Comment.create({ content: 'parentComment' }).success(function(p) {
parent = p
done()
})
})
Helpers.async(function(done) {
Comment.create({ content: 'child1' }).success(function(child1) {
child1.setParent(parent).success(function() {
done()
})
})
})
Helpers.async(function(done) {
Comment.create({ content: 'child2' }).success(function(child2) {
child2.setParent(parent).success(function() {
done()
})
})
})
Helpers.async(function(done) {
Comment.find({where: { content: 'parentComment' }}).success(function(parent) {
parent.getChildren().success(function(children) {
expect(children.length).toEqual(2)
done()
})
})
})
})
it("should still use many to many for selfAssociation by default (two DAOs are created)", function() {
Helpers.async(function(done) {
var oldLength = sequelize.daoFactoryManager.daos.length;
var Comment = sequelize.define('Comment', { content: Sequelize.STRING })
Comment.belongsTo(Comment, {as: "Parent"})
Comment.hasMany(Comment, {as: 'Children'})
expect(sequelize.daoFactoryManager.daos.length).toEqual(oldLength + 2)
done();
})
})
})
describe('bi-directional', function() {
it('adds the foreign key', function() {
Task.hasMany(User)
User.hasMany(Task)
expect(Task.attributes.UserId).toBeUndefined()
expect(User.attributes.UserId).toBeUndefined()
var daos = sequelize.daoFactoryManager.daos.filter(function(dao) {
return (dao.tableName == (Task.tableName + User.tableName))
})
daos.forEach(function(dao) {
expect(dao.attributes.UserId).toBeDefined()
expect(dao.attributes.TaskId).toBeDefined()
})
})
it("adds the foreign key with underscores", function() {
User = sequelize.define('User', { username: Sequelize.STRING }, { underscored: true })
Task = sequelize.define('Task', { title: Sequelize.STRING })
Task.hasMany(User)
User.hasMany(Task)
expect(Task.attributes.user_id).toBeUndefined()
expect(User.attributes.user_id).toBeUndefined()
var daos = sequelize.daoFactoryManager.daos.filter(function(dao) {
return (dao.tableName == (Task.tableName + User.tableName))
})
daos.forEach(function(dao) {
expect(dao.attributes.user_id).toBeDefined()
expect(dao.attributes.TaskId).toBeDefined()
})
})
it("uses the passed foreign keys", function() {
User.hasMany(Task, { foreignKey: 'person_id' })
Task.hasMany(User, { foreignKey: 'work_item_id' })
var daos = sequelize.daoFactoryManager.daos.filter(function(dao) {
return (dao.tableName == (Task.tableName + User.tableName))
})
daos.forEach(function(dao) {
expect(dao.attributes.person_id).toBeDefined()
expect(dao.attributes.work_item_id).toBeDefined()
})
})
it("defines getters and setters", function() {
User.hasMany(Task)
Task.hasMany(User)
var u = User.build({ username: 'asd' })
expect(u.setTasks).toBeDefined()
expect(u.getTasks).toBeDefined()
var t = Task.build({ title: 'foobar' })
expect(t.setUsers).toBeDefined()
expect(t.getUsers).toBeDefined()
})
it("defines getters and setters according to the 'as' option", function() {
User.hasMany(Task, { as: 'Tasks' })
Task.hasMany(User, { as: 'Users' })
var u = User.build({ username: 'asd' })
expect(u.setTasks).toBeDefined()
expect(u.getTasks).toBeDefined()
var t = Task.build({ title: 'asd' })
expect(t.setUsers).toBeDefined()
expect(t.getUsers).toBeDefined()
})
it("sets and gets the corrected associated objects", function() {
var users = []
, tasks = []
User.hasMany(Task, {as: 'Tasks'})
Task.hasMany(User, {as: 'Users'})
Helpers.async(function(done) {
User.sync({force: true}).success(function() {
Task.sync({force: true}).success(done)
})
})
Helpers.async(function(done) {
User.create({username: 'name'}).success(function(user1) {
User.create({username: 'name2'}).success(function(user2) {
Task.create({title: 'task1'}).success(function(task1) {
Task.create({title: 'task2'}).success(function(task2) {
users.push(user1)
users.push(user2)
tasks.push(task1)
tasks.push(task2)
done()
})
})
})
})
})
Helpers.async(function(done) {
users[0].setTasks(tasks).success(function() {
users[0].getTasks().success(function(_tasks) {
expect(_tasks.length).toEqual(2)
tasks[1].setUsers(users).success(function() {
tasks[1].getUsers().success(function(_users) {
expect(users.length).toEqual(2)
done()
})
})
})
})
})
})
})
it("build the connector daos name", function() {
Helpers.async(function(done) {
var Person = sequelize.define('Person', { name: Sequelize.STRING })
Person.hasMany(Person, {as: 'Children'})
Person.hasMany(Person, {as: 'Friends'})
Person.hasMany(Person, {as: 'CoWorkers'})
Person.sync({force: true}).success(function() {
var daoNames = sequelize.daoFactoryManager.daos.map(function(dao) { return dao.tableName })
, expectation = ["Persons", "ChildrenPersons", "CoWorkersPersons", "FriendsPersons"]
expectation.forEach(function(ex) {
expect(daoNames.indexOf(ex) > -1).toBeTruthy()
})
done()
})
})
})
it("allows join table to be specified", function() {
Helpers.async(function(done) {
var Child = sequelize.define('Child', { name: Sequelize.STRING }, {underscore: true, freezeTableName: true})
var Parent = sequelize.define('Parent', { name: Sequelize.STRING }, {underscore: true, freezeTableName: true})
var ParentJoin = sequelize.define('ParentRelationship', { parent_id: Sequelize.INTEGER, child_id: Sequelize.INTEGER }, {underscore: true, freezeTableName: true})
Parent.hasMany(Child, {as: 'Children', foreignKey: 'child_id', joinTableName: 'ParentRelationship'})
Child.hasMany(Parent, {as: 'Parents', foreignKey: 'parent_id', joinTableName: 'ParentRelationship'})
var parents = []
ParentJoin.sync({force: true}).success(function() {
Parent.sync({force: true}).success(function() {
Child.sync({force: true}).success(function() {
Parent.create({name: 'mom'}).success(function(mom) {
parents.push(mom)
Parent.create({name: 'dad'}).success(function(dad) {
parents.push(dad)
Child.create({name: 'baby'}).success(function(baby) {
baby.setParents(parents).success(function(){
parents[0].getChildren().success(function(children){
expect(children).not.toBe(null)
expect(children.length).toBeDefined()
expect(children.length).toEqual(1)
expect(children[0]).toBeDefined()
expect(children[0].name).toEqual('baby')
done()
})
})
})
})
})
})
})
})
})
})
it("allows join table to be mapped and specified", function() {
var User = sequelize.define('User', { name: Sequelize.STRING }, {underscore: true, freezeTableName: true})
var Company = sequelize.define('Company', { name: Sequelize.STRING }, {underscore: true, freezeTableName: true})
var CompanyAccess = sequelize.define('CompanyAccess', { company_id: Sequelize.INTEGER, user_id: Sequelize.INTEGER, permission: Sequelize.STRING }, {underscore: true, freezeTableName: true})
CompanyAccess.belongsTo(User, {as: 'User', foreignKey: 'user_id'})
CompanyAccess.belongsTo(Company, {as: 'Company', foreignKey: 'company_id'})
User.hasMany(Company, {as: 'Companies', foreignKey: 'user_id', joinTableName: 'CompanyAccess'})
Company.hasMany(User, {as: 'Users', foreignKey: 'company_id', joinTableName: 'CompanyAccess'})
Helpers.async(function(done) {
var companies = []
CompanyAccess.sync({force: true}).success(function() {
User.sync({force: true}).success(function() {
Company.sync({force: true}).success(function() {
Company.create({name: 'IBM'}).success(function(ibm) {
companies.push(ibm)
Company.create({name: 'EA'}).success(function(ea) {
companies.push(ea)
User.create({name: 'joe@ibm.com'}).success(function(joe) {
joe.setCompanies(companies).success(function(){
User.find({where: {name: 'joe@ibm.com'}}).success(function(joe) {
expect(joe).not.toEqual(null)
joe.getCompanies().success(function(comps) {
expect(comps).not.toEqual(null)
expect(comps.length).toEqual(2)
done()
})
})
})
})
})
})
})
})
})
})
})
it("gets and sets the connector daos", function() {
Helpers.async(function(done) {
var Person = sequelize.define('Person', { name: Sequelize.STRING })
Person.hasMany(Person, {as: 'Children'})
Person.hasMany(Person, {as: 'Friends'})
Person.hasMany(Person, {as: 'CoWorkers'})
Person.sync({force: true}).success(function() {
Person.create({name: 'foobar'}).success(function(person) {
Person.create({name: 'friend'}).success(function(friend) {
person.setFriends([friend]).success(function() {
person.getFriends().success(function(friends) {
expect(friends.length).toEqual(1)
expect(friends[0].name).toEqual('friend')
done()
})
})
})
})
})
})
})
})
var config = require("../config/config")
, Sequelize = require("../../index")
, sequelize = new Sequelize(config.mysql.database, config.mysql.username, config.mysql.password, { pool: config.mysql.pool, logging: false, host: config.mysql.host, port: config.mysql.port })
, Helpers = new (require("../config/helpers"))(sequelize)
describe('HasOne', function() {
var User = null
, Task = null
var setup = function() {
User = sequelize.define('User', { username: Sequelize.STRING })
Task = sequelize.define('Task', { title: Sequelize.STRING })
}
beforeEach(function() { Helpers.dropAllTables(); setup() })
afterEach(function() { Helpers.dropAllTables() })
it("adds the foreign key", function() {
User.hasOne(Task)
expect(Task.attributes.UserId).toEqual("INTEGER")
})
it("adds an underscored foreign key", function() {
User = sequelize.define('User', { username: Sequelize.STRING }, {underscored: true})
Task = sequelize.define('Task', { title: Sequelize.STRING })
User.hasOne(Task)
expect(Task.attributes.user_id).toEqual("INTEGER")
})
it("uses the passed foreign key", function() {
User = sequelize.define('User', { username: Sequelize.STRING }, {underscored: true})
Task = sequelize.define('Task', { title: Sequelize.STRING })
User.hasOne(Task, {foreignKey: 'person_id'})
expect(Task.attributes.person_id).toEqual("INTEGER")
})
it("defines the getter and the setter", function() {
User.hasOne(Task)
var u = User.build({username: 'asd'})
expect(u.setTask).toBeDefined()
expect(u.getTask).toBeDefined()
})
it("defined the getter and the setter according to the passed 'as' option", function() {
User.hasOne(Task, {as: 'Work'})
var u = User.build({username: 'asd'})
expect(u.setWork).toBeDefined()
expect(u.getWork).toBeDefined()
})
it("aliases associations to the same table according to the passed 'as' option", function() {
User.hasOne(Task, {as: 'Work'});
User.hasOne(Task, {as: 'Play'});
var u = User.build({username: 'asd'})
expect(u.getWork).toBeDefined()
expect(u.setWork).toBeDefined()
expect(u.getPlay).toBeDefined()
expect(u.setPlay).toBeDefined()
})
it("gets and sets the correct objects", function() {
var user, task;
User.hasOne(Task, {as: 'Task'})
Helpers.async(function(done) {
User.sync({force: true}).success(function() {
Task.sync({force: true}).success(function() {
User.create({username: 'name'}).success(function(_user) {
Task.create({title: 'snafu'}).success(function(_task) {
user = _user
task = _task
done()
})
})
})
})
})
Helpers.async(function(done) {
user.setTask(task).on('success', function() {
user.getTask().on('success', function(task2) {
expect(task.title).toEqual(task2.title)
user.getTask({attributes: ['title']}).on('success', function(task2) {
expect(task2.selectedValues.title).toEqual('snafu')
expect(task2.selectedValues.id).toEqual(null)
done()
})
})
})
})
})
it("unsets unassociated objects", function() {
var user, task1, task2;
User.hasOne(Task, {as: 'Task'})
Helpers.async(function(done) {
User.sync({force: true}).success(function() {
Task.sync({force: true}).success(function() {
User.create({username: 'name'}).success(function(_user) {
Task.create({title: 'snafu'}).success(function(_task1) {
Task.create({title: 'another task'}).success(function(_task2) {
user = _user
task1 = _task1
task2 = _task2
done()
})
})
})
})
})
})
Helpers.async(function(done) {
user.setTask(task1).success(function() {
user.getTask().success(function(_task) {
expect(task1.title).toEqual(_task.title)
user.setTask(task2).success(function() {
user.getTask().success(function(_task2) {
expect(task2.title).toEqual(task2.title)
done()
})
})
})
})
})
})
it("sets self associations", function() {
Helpers.async(function(done) {
var Person = sequelize.define('Person', { name: Sequelize.STRING })
Person.hasOne(Person, {as: 'Mother', foreignKey: 'MotherId'})
Person.hasOne(Person, {as: 'Father', foreignKey: 'FatherId'})
Person.sync({force: true}).success(function() {
var p = Person.build()
expect(p.setFather).toBeDefined()
expect(p.setMother).toBeDefined()
done()
})
})
})
it("automatically sets the foreign key on self associations", function() {
var Person = sequelize.define('Person', { name: Sequelize.STRING })
Person.hasOne(Person, {as: 'Mother'})
expect(Person.associations.MotherPersons.options.foreignKey).toEqual('MotherId')
})
})
module.exports = {
rand: function() {
return parseInt(Math.random() * 999)
},
//make maxIdleTime small so that tests exit promptly
mysql: {
username: "root",
password: null,
database: 'sequelize_test',
host: '127.0.0.1',
port: 3306,
pool: { maxConnections: 5, maxIdleTime: 30}
},
sqlite: {
},
postgres: {
database: 'sequelize_test',
username: "postgres",
port: 5432,
pool: { maxConnections: 5, maxIdleTime: 30}
}
}
var Factories = module.exports = function(helpers) {
this.helpers = helpers
this.sequelize = this.helpers.sequelize
}
Factories.prototype.DAO = function(daoName, options, callback, count) {
count = count || 1
var self = this
, daos = []
this.helpers.async(function(done) {
var DAO = self.sequelize.daoFactoryManager.getDAO(daoName)
var create = function(cb) {
DAO.create(options).on('success', function(dao) {
daos.push(dao)
cb && cb()
}).on('error', function(err) {
console.log(err)
done()
})
}
var cb = function() {
if(--count) {
create(cb)
} else {
done()
callback && callback(daos)
}
}
create(cb)
})
}
Factories.prototype.User = function(options, callback, count) {
this.DAO('User', options, callback, count)
}
Sequelize = require("../../index")
var Helpers = module.exports = function(sequelize) {
this.sequelize = sequelize
this.Factories = new (require("./factories"))(this)
}
Helpers.prototype.sync = function() {
var self = this
this.async(function(done) {
self.sequelize
.sync({force: true})
.success(done)
.failure(function(err) { console.log(err) })
})
}
Helpers.prototype.drop = function() {
var self = this
this.async(function(done) {
self.sequelize
.drop()
.on('success', done)
.on('error', function(err) { console.log(err) })
})
}
Helpers.prototype.dropAllTables = function() {
var self = this
this.async(function(done) {
self.sequelize
.getQueryInterface()
.dropAllTables()
.success(done)
.error(function(err) { console.log(err) })
})
}
Helpers.prototype.async = function(fct) {
var done = false
runs(function() {
fct(function() { return done = true })
})
waitsFor(function(){ return done })
}
var config = require("./config/config")
, Sequelize = require("../index")
, dialects = ['sqlite', 'mysql', 'postgres']
describe('DAOFactory', function() {
dialects.forEach(function(dialect) {
describe('with dialect "' + dialect + '"', function() {
var User = null
, sequelize = new Sequelize(
config[dialect].database,
config[dialect].username,
config[dialect].password,
{
logging: false,
dialect: dialect,
port: config[dialect].port
}
)
, Helpers = new (require("./config/helpers"))(sequelize)
var setup = function(options) {
User = sequelize.define('User', options || {
age: Sequelize.INTEGER,
name: Sequelize.STRING,
bio: Sequelize.TEXT
})
Helpers.dropAllTables()
Helpers.async(function(done) {
User.sync({force: true}).success(done).error(function(err) { console.log(err) })
})
}
var checkMatchForDialects = function(value, expectations) {
if(!!expectations[dialect])
expect(value).toMatch(expectations[dialect])
else
throw new Error('Undefined expectation for "' + dialect + '"!')
}
beforeEach(function() { setup() })
afterEach(function() { Helpers.dropAllTables() })
describe('destroy', function() {
it('deletes a record from the database if dao is not paranoid', function() {
Helpers.async(function(done) {
User = sequelize.define('User', {
name: Sequelize.STRING,
bio: Sequelize.TEXT
})
User.sync({force: true}).success(done)
})
Helpers.async(function(done) {
User.create({name: 'hallo', bio: 'welt'}).success(function(u) {
User.all().success(function(users) {
expect(users.length).toEqual(1)
u.destroy().success(function() {
User.all().success(function(users) {
expect(users.length).toEqual(0)
done()
}).error(function(err) { console.log(err) })
}).error(function(err) { console.log(err) })
}).error(function(err) { console.log(err) })
})
})
})
it('allows sql logging of delete statements', function() {
Helpers.async(function(done) {
User = sequelize.define('User', {
name: Sequelize.STRING,
bio: Sequelize.TEXT
})
User.sync({force: true}).success(done)
})
Helpers.async(function(done) {
User.create({name: 'hallo', bio: 'welt'}).success(function(u) {
User.all().success(function(users) {
expect(users.length).toEqual(1)
u.destroy().on('sql', function(sql) {
expect(sql).toBeDefined()
expect(sql.toUpperCase().indexOf("DELETE")).toBeGreaterThan(-1)
done()
}).error(function(err) { console.log(err) })
}).error(function(err) { console.log(err) })
})
})
})
it('allows sql logging of update statements', function() {
Helpers.async(function(done) {
User = sequelize.define('User', {
name: Sequelize.STRING, bio: Sequelize.TEXT
}, { paranoid:true })
User.sync({ force: true }).success(done)
})
Helpers.async(function(done) {
User.create({ name: 'meg', bio: 'none' }).success(function(u) {
expect(u).toBeDefined()
expect(u).not.toBe(null)
u.destroy().on('sql', function(sql) {
expect(sql).toBeDefined()
expect(sql.toUpperCase().indexOf("UPDATE")).toBeGreaterThan(-1)
done()
})
})
})
})
})
describe('findAll', function() {
var users = []
beforeEach(function() {
Helpers.Factories.User({name: 'user', bio: 'foobar'}, function(_users) {
users = _users
}, 2)
})
it("finds all entries", function() {
Helpers.async(function(done) {
User.findAll().on('success', function(_users) {
expect(_users.length).toEqual(2)
done()
})
})
})
it("finds all users matching the passed conditions", function() {
Helpers.async(function(done) {
User.findAll({where: "id != " + users[1].id}).success(function(_users) {
expect(_users.length).toEqual(1)
done()
})
})
})
it("can also handle array notation", function() {
Helpers.async(function(done){
User.findAll({where: ['id = ?', users[1].id]}).success(function(_users) {
expect(_users.length).toEqual(1)
expect(_users[0].id).toEqual(users[1].id)
done()
})
})
})
it("sorts the results via id", function() {
Helpers.Factories.User({name: 'user', bio: 'foobar'}, function(_users) {
users = _users
}, 2)
Helpers.async(function(done) {
setTimeout(function() {
User.create({name: 'user', bio: 'foobar'}).success(function(user) {
users.push(user)
done()
})
}, 2000)
})
Helpers.async(function(done) {
User.findAll({ order: "id DESC" }).success(function(users) {
expect(users[0].id).toBeGreaterThan(users[2].id)
done()
})
})
})
it("sorts the results via createdAt", function() {
Helpers.Factories.User({name: 'user', bio: 'foobar'}, function(_users) {
users = _users
}, 2)
Helpers.async(function(done) {
setTimeout(function() {
User.create({name: 'user', bio: 'foobar'}).success(function(user) {
users.push(user)
done()
})
}, 2000)
})
Helpers.async(function(done) {
User.findAll({ order: 'createdAt DESC' }).success(function(users) {
expect(users[0].id).toBeGreaterThan(users[2].id)
done()
})
})
})
it("handles offset and limit", function() {
setup()
Helpers.Factories.User({name: 'user', bio: 'foobar'}, null, 10)
Helpers.async(function(done) {
User.findAll({ limit: 2, offset: 2 }).success(function(users) {
expect(users.length).toEqual(2)
expect(users[0].id).toEqual(3)
done()
})
})
})
})
describe('findAndCountAll', function() {
var users = [], fullcount = 3
beforeEach(function() {
Helpers.Factories.User({name: 'user', bio: 'foobar'}, function(_users) {
users = _users
}, fullcount)
})
it("handles where clause [only]", function() {
Helpers.async(function(done) {
User.findAndCountAll({where: "id != " + users[0].id}).success(function(info) {
expect(info.count).toEqual(fullcount - 1)
expect(Array.isArray(info.rows)).toBeTruthy()
expect(info.rows.length).toEqual(fullcount - 1)
done()
})
})
})
it("handles where clause with ordering [only]", function() {
Helpers.async(function(done) {
User.findAndCountAll({where: "id != " + users[0].id, order: 'id ASC'}).success(function(info) {
expect(info.count).toEqual(fullcount - 1)
expect(Array.isArray(info.rows)).toBeTruthy()
expect(info.rows.length).toEqual(fullcount - 1)
done()
})
})
})
it("handles offset", function() {
Helpers.async(function(done) {
User.findAndCountAll({offset: 1}).success(function(info) {
expect(info.count).toEqual(fullcount)
expect(Array.isArray(info.rows)).toBeTruthy()
expect(info.rows.length).toEqual(fullcount - 1)
done()
})
})
})
it("handles limit", function() {
Helpers.async(function(done) {
User.findAndCountAll({limit: 1}).success(function(info) {
expect(info.count).toEqual(fullcount)
expect(Array.isArray(info.rows)).toBeTruthy()
expect(info.rows.length).toEqual(1)
done()
})
})
})
it("handles offset and limit", function() {
Helpers.async(function(done) {
User.findAndCountAll({offset: 1, limit: 1}).success(function(info) {
expect(info.count).toEqual(fullcount)
expect(Array.isArray(info.rows)).toBeTruthy()
expect(info.rows.length).toEqual(1)
done()
})
})
})
})
describe('all', function() {
beforeEach(function() {
Helpers.Factories.User({name: 'user', bio: 'foobar'}, null, 2)
})
it("should return all users", function() {
Helpers.async(function(done) {
User.all().on('success', function(users) {
done()
expect(users.length).toEqual(2)
}).on('error', function(err) { console.log(err) })
})
})
})
describe('count', function() {
it('counts all created objects', function() {
Helpers.async(function(done) {
User.create({name: 'user1'}).success(function() {
User.create({name: 'user2'}).success(done)
})
})
Helpers.async(function(done) {
User.count().success(function(count) {
expect(count).toEqual(2)
done()
})
})
})
it('allows sql logging', function() {
Helpers.async(function(done) {
User.count()
.on('sql', function(sql) {
expect(sql).toBeDefined()
expect(sql.toUpperCase().indexOf("SELECT")).toBeGreaterThan(-1)
done()
})
})
})
it('filters object', function() {
Helpers.async(function(done) {
User.create({name: 'user1'}).success(function() {
User.create({name: 'foo'}).success(done)
})
})
Helpers.async(function(done) {
User.count({where: "name LIKE '%us%'"}).success(function(count) {
expect(count).toEqual(1)
done()
})
})
})
})
describe('equals', function() {
it("correctly determines equality of objects", function() {
setup({ name: Sequelize.STRING, bio: Sequelize.TEXT })
Helpers.async(function(done) {
User.create({name: 'hallo', bio: 'welt'}).success(function(u) {
expect(u.equals(u)).toBeTruthy()
done()
})
})
})
// sqlite can't handle multiple primary keys
if(dialect != 'sqlite') {
it("correctly determines equality with multiple primary keys", function() {
setup({
foo: {type: Sequelize.STRING, primaryKey: true},
bar: {type: Sequelize.STRING, primaryKey: true},
name: Sequelize.STRING, bio: Sequelize.TEXT
})
Helpers.async(function(done) {
User.create({foo: '1', bar: '2', name: 'hallo', bio: 'welt'}).success(function(u) {
expect(u.equals(u)).toBeTruthy()
done()
}).error(function(err) { console.log(err) })
})
})
}
})
describe('equalsOneOf', function() {
// sqlite can't handle multiple primary keys
if(dialect != 'sqlite') {
beforeEach(function() {
setup({
foo: {type: Sequelize.STRING, primaryKey: true},
bar: {type: Sequelize.STRING, primaryKey: true},
name: Sequelize.STRING, bio: Sequelize.TEXT
})
})
it('determines equality if one is matching', function() {
Helpers.async(function(done) {
User.create({foo: '1', bar: '2', name: 'hallo', bio: 'welt'}).success(function(u) {
expect(u.equalsOneOf([u, {a:1}])).toBeTruthy()
done()
})
})
})
it("doesn't determine equality if none is matching", function() {
Helpers.async(function(done) {
User.create({foo: '1', bar: '2', name: 'hallo', bio: 'welt'}).success(function(u) {
expect(u.equalsOneOf([{b:2}, {a:1}])).toBeFalsy()
done()
})
})
})
}
})
describe('Mixin', function() {
var DAOFactory = require("../lib/dao-factory")
it("adds the mixed-in functions to the dao", function() {
expect(DAOFactory.prototype.hasOne).toBeDefined()
expect(DAOFactory.prototype.hasMany).toBeDefined()
expect(DAOFactory.prototype.belongsTo).toBeDefined()
})
})
describe('sync', function() {
it('works with correct database credentials', function() {
Helpers.async(function(done) {
User.sync().success(done)
})
})
it("fails with incorrect database credentials", function() {
Helpers.async(function(done) {
var sequelize2 = new Sequelize('foo', 'bar', null, { logging: false })
, User2 = sequelize2.define('User', { name: Sequelize.STRING, bio: Sequelize.TEXT })
User2.sync().error(function(err) {
expect(err.message).toMatch(/.*Access\ denied.*/)
done()
})
})
})
})
describe('drop should work', function() {
it('correctly succeeds', function() {
Helpers.async(function(done) {
User.drop().success(done)
})
})
})
})
})
})
var config = require("./config/config")
, Sequelize = require("../index")
, dialects = ['sqlite', 'mysql', 'postgres']
describe('DAO', function() {
dialects.forEach(function(dialect) {
describe('with dialect "' + dialect + '"', function() {
var User = null
, sequelize = new Sequelize(
config[dialect].database,
config[dialect].username,
config[dialect].password,
{
logging: false,
dialect: dialect,
port: config[dialect].port,
host: config[dialect].host
}
)
, Helpers = new (require("./config/helpers"))(sequelize)
var setup = function() {
Helpers.async(function(done) {
User = sequelize.define('User', {
username: Sequelize.STRING,
birthDate: Sequelize.DATE
})
User.sync({ force: true }).success(done)
})
}
beforeEach(function() { Helpers.dropAllTables(); setup() })
afterEach(function() { Helpers.dropAllTables() })
describe('Escaping', function() {
it('is done properly for special characters', function() {
var User = sequelize.define('User', {
bio: Sequelize.TEXT
}, { timestamps: false, logging: false })
Helpers.async(function(done) {
User.sync({ force: true }).success(done)
})
Helpers.async(function(done) {
// Ideally we should test more: "\0\n\r\b\t\\\'\"\x1a"
// But this causes sqlite to fail and exits the entire test suite immediately
var bio = dialect + "'\"\n"; // Need to add the dialect here so in case of failure I know what DB it failed for
User.create({ bio: bio }).success(function(u1) {
User.find(u1.id).success(function(u2) {
expect(u2.bio).toEqual(bio)
done()
})
})
})
})
})
describe('isNewRecord', function() {
it('returns true for non-saved objects', function() {
var user = User.build({ username: 'user' })
expect(user.id).toBeNull()
expect(user.isNewRecord).toBeTruthy()
})
it("returns false for saved objects", function() {
Helpers.async(function(done) {
User.build({ username: 'user' }).save().success(function(user) {
expect(user.isNewRecord).toBeFalsy()
done()
})
})
})
it("returns false for created objects", function() {
Helpers.async(function(done) {
User.create({ username: 'user' }).success(function(user) {
expect(user.isNewRecord).toBeFalsy()
done()
})
})
})
it("returns false for objects found by find method", function() {
Helpers.async(function(done) {
User.create({ username: 'user' }).success(function(user) {
User.create({ username: 'user' }).success(function(user) {
User.find(user.id).success(function(user) {
expect(user.isNewRecord).toBeFalsy()
done()
})
})
})
})
})
it("returns false for objects found by findAll method", function() {
var chainer = new Sequelize.Utils.QueryChainer
for(var i = 0; i < 10; i++)
chainer.add(User.create({ username: 'user' }))
Helpers.async(function(done) {
chainer.run().success(function() {
User.findAll().success(function(users) {
users.forEach(function(u) {
expect(u.isNewRecord).toBeFalsy()
})
done()
})
})
})
})
})
describe('save', function() {
it('only updates fields in passed array', function() {
var user = null
, user2 = null
, userId = null
, date = new Date(1990, 01, 01)
Helpers.async(function(done) {
User.create({
username: 'foo',
birthDate: new Date()
}).success(function(_user) {
user = _user
done()
}).error(function(err) {
console.log(err)
})
})
Helpers.async(function(done) {
user.username = 'fizz'
user.birthDate = date
done()
})
Helpers.async(function(done) {
user.save(['username']).success(function(){
// re-select user
User.find(user.id).success(function(_user2) {
user2 = _user2
done()
})
})
})
Helpers.async(function(done) {
// name should have changed
expect(user2.username).toEqual('fizz')
// bio should be unchanged
expect(user2.birthDate).toNotEqual(date)
done()
})
})
it("stores an entry in the database", function() {
var username = 'user'
, user = User.build({
username: username,
birthDate: new Date(1984, 8, 23)
})
Helpers.async(function(done) {
User.all().success(function(users) {
expect(users.length).toEqual(0)
done()
})
})
Helpers.async(function(done) {
user.save().success(done)
})
Helpers.async(function(done) {
User.all().success(function(users) {
expect(users.length).toEqual(1)
expect(users[0].username).toEqual(username)
expect(users[0].birthDate instanceof Date).toBe(true)
expect(users[0].birthDate).toEqual(new Date(1984, 8, 23))
done()
})
})
})
it("updates the timestamps", function() {
var now = Date.now()
, user = null
, updatedAt = null
Helpers.async(function(done) {
// timeout is needed, in order to check the update of the timestamp
setTimeout(function() {
user = User.build({ username: 'user' })
updatedAt = user.updatedAt
expect(updatedAt.getTime()).toBeGreaterThan(now)
done()
}, 1000)
})
Helpers.async(function(done) {
setTimeout(function() {
user.save().success(function() {
expect(updatedAt.getTime()).toBeLessThan(user.updatedAt.getTime())
done()
})
}, 1000)
})
})
describe('without timestamps option', function() {
var User2 = sequelize.define('User2', {
username: Sequelize.STRING,
updatedAt: Sequelize.DATE
}, {
timestamps: false
})
beforeEach(function() {
Helpers.async(function(done) {
User2.sync({ force: true }).success(done)
})
})
it("doesn't update the updatedAt column", function() {
Helpers.async(function(done) {
User2.create({ username: 'john doe' }).success(function(johnDoe) {
// sqlite and mysql return undefined, whereas postgres returns null
expect([undefined, null].indexOf(johnDoe.updatedAt)).not.toBe(-1);
done()
})
})
})
})
})
describe('updateAttributes', function() {
it("updates attributes in the database", function() {
Helpers.async(function(done) {
User.create({ username: 'user' }).success(function(user) {
expect(user.username).toEqual('user')
user.updateAttributes({ username: 'person' }).success(function(user) {
expect(user.username).toEqual('person')
done()
})
})
})
})
it("ignores unknown attributes", function() {
Helpers.async(function(done) {
User.create({ username: 'user' }).success(function(user) {
user.updateAttributes({ username: 'person', foo: 'bar'}).success(function(user) {
expect(user.username).toEqual('person')
expect(user.foo).toBeUndefined()
done()
})
})
})
})
it("doesn't update primary keys or timestamps", function() {
var User = sequelize.define('User' + config.rand(), {
name: Sequelize.STRING, bio: Sequelize.TEXT, identifier: {type: Sequelize.STRING, primaryKey: true}
})
Helpers.async(function(done) {
User.sync({ force: true }).success(done)
})
Helpers.async(function(done) {
User.create({
name: 'snafu',
identifier: 'identifier'
}).success(function(user) {
var oldCreatedAt = user.createdAt
, oldIdentifier = user.identifier
user.updateAttributes({
name: 'foobar',
createdAt: new Date(2000, 1, 1),
identifier: 'another identifier'
}).success(function(user) {
expect(user.createdAt).toEqual(oldCreatedAt)
expect(user.identifier).toEqual(oldIdentifier)
done()
})
})
})
})
it("uses primary keys in where clause", function() {
var User = sequelize.define('User' + config.rand(), {
name: Sequelize.STRING, bio: Sequelize.TEXT, identifier: {type: Sequelize.STRING, primaryKey: true}
})
Helpers.async(function(done) {
User.sync({ force:true }).success(done)
})
Helpers.async(function(done) {
User.create({
name: 'snafu',
identifier: 'identifier'
}).success(function(user) {
var emitter = user.updateAttributes({name: 'foobar'})
emitter.success(function() {
expect(emitter.query.sql).toMatch(/WHERE [`"]identifier[`"]..identifier./)
done()
})
})
})
})
})
describe('values', function() {
it('returns all values', function() {
var User = sequelize.define('User', {
username: Sequelize.STRING
}, { timestamps: false, logging: false })
Helpers.async(function(done) {
User.sync({ force: true }).success(done)
})
Helpers.async(function(done) {
var user = User.build({ username: 'foo' })
expect(user.values).toEqual({ username: "foo", id: null })
done()
})
})
})
})
})
})
var config = require("../config/config")
, Sequelize = require("../../index")
, sequelize = new Sequelize(config.mysql.database, config.mysql.username, config.mysql.password, { pool: config.mysql.pool, logging: false, host: config.mysql.host, port: config.mysql.port })
, Helpers = new (require("../config/helpers"))(sequelize)
describe('HasMany', function() {
beforeEach(function() { Helpers.sync() })
afterEach(function() { Helpers.drop() })
//prevent periods from occurring in the table name since they are used to delimit (table.column)
var User = sequelize.define('User' + Math.ceil(Math.random()*10000000), { name: Sequelize.STRING })
, Task = sequelize.define('Task' + Math.ceil(Math.random()*10000000), { name: Sequelize.STRING })
, users = null
, tasks = null
User.hasMany(Task, {as:'Tasks'})
Task.hasMany(User, {as:'Users'})
beforeEach(function() {
Helpers.async(function(_done) {
Helpers.Factories.DAO(User.name, {name: 'User' + Math.random()}, function(_users) {
users = _users; _done()
}, 5)
})
Helpers.async(function(_done) {
Helpers.Factories.DAO(Task.name, {name: 'Task' + Math.random()}, function(_tasks) {
tasks = _tasks; _done()
}, 2)
})
})
describe('addDAO / getDAO', function() {
var user = null
, task = null
beforeEach(function() {
Helpers.async(function(done) {
User.all().on('success', function(_users) {
Task.all().on('success', function(_tasks) {
user = _users[0]
task = _tasks[0]
done()
})
})
})
})
it('should correctly add an association to the dao', function() {
Helpers.async(function(done) {
user.getTasks().on('success', function(_tasks) {
expect(_tasks.length).toEqual(0)
user.addTask(task).on('success', function() {
user.getTasks().on('success', function(_tasks) {
expect(_tasks.length).toEqual(1)
done()
})
})
})
})
})
})
describe('removeDAO', function() {
var user = null
, tasks = null
beforeEach(function() {
Helpers.async(function(done) {
User.all().on('success', function(users) {
Task.all().on('success', function(_tasks) {
user = users[0]
tasks = _tasks
done()
})
})
})
})
it("should correctly remove associated objects", function() {
Helpers.async(function(done) {
user.getTasks().on('success', function(__tasks) {
expect(__tasks.length).toEqual(0)
user.setTasks(tasks).on('success', function() {
user.getTasks().on('success', function(_tasks) {
expect(_tasks.length).toEqual(tasks.length)
user.removeTask(tasks[0]).on('success', function() {
user.getTasks().on('success', function(_tasks) {
expect(_tasks.length).toEqual(tasks.length - 1)
done()
})
})
})
})
})
})
})
})
})
var config = require("../config/config")
, Sequelize = require("../../index")
, sequelize = new Sequelize(config.mysql.database, config.mysql.username, config.mysql.password, { pool: config.mysql.pool, logging: false, host: config.mysql.host, port: config.mysql.port })
, Helpers = new (require("../config/helpers"))(sequelize)
describe('Associations', function() {
beforeEach(function() { Helpers.sync() })
afterEach(function() { Helpers.drop() })
/////////// many-to-many with same prefix ////////////
describe('many-to-many', function() {
describe('where tables have the same prefix', function() {
var Table2 = sequelize.define('wp_table2', {foo: Sequelize.STRING})
, Table1 = sequelize.define('wp_table1', {foo: Sequelize.STRING})
Table1.hasMany(Table2)
Table2.hasMany(Table1)
it("should create a table wp_table1wp_table2s", function() {
Helpers.async(function(done) {
expect(sequelize.daoFactoryManager.getDAO('wp_table1swp_table2s')).toBeDefined()
done()
})
})
})
describe('when join table name is specified', function() {
var Table2 = sequelize.define('ms_table1', {foo: Sequelize.STRING})
, Table1 = sequelize.define('ms_table2', {foo: Sequelize.STRING})
Table1.hasMany(Table2, {joinTableName: 'table1_to_table2'})
Table2.hasMany(Table1, {joinTableName: 'table1_to_table2'})
it("should not use a combined name", function() {
expect(sequelize.daoFactoryManager.getDAO('ms_table1sms_table2s')).toBeUndefined()
})
it("should use the specified name", function() {
expect(sequelize.daoFactoryManager.getDAO('table1_to_table2')).toBeDefined()
})
})
})
})
var config = require("../config/config")
, Sequelize = require("../../index")
, sequelize = new Sequelize(config.mysql.database, config.mysql.username, config.mysql.password, { pool: config.mysql.pool, logging: false, host: config.mysql.host, port: config.mysql.port })
, Helpers = new (require("../config/helpers"))(sequelize)
describe('ConnectorManager', function() {
beforeEach(function() {
Helpers.dropAllTables()
})
afterEach(function() {
Helpers.dropAllTables()
})
it('works correctly after being idle', function() {
var User = sequelize.define('User', { username: Sequelize.STRING })
Helpers.async(function(done) {
User.sync({force: true}).on('success', function() {
User.create({username: 'user1'}).on('success', function() {
User.count().on('success', function(count) {
expect(count).toEqual(1)
done()
})
})
})
})
Helpers.async(function(done) {
setTimeout(function() {
User.count().on('success', function(count) {
expect(count).toEqual(1)
done()
})
}, 1000)
})
})
})
var config = require("../config/config")
, Sequelize = require("../../index")
, sequelize = new Sequelize(config.mysql.database, config.mysql.username, config.mysql.password, { pool: config.mysql.pool, logging: false, host: config.mysql.host, port: config.mysql.port })
, Helpers = new (require("../config/helpers"))(sequelize)
describe('DAOFactory', function() {
beforeEach(function() { Helpers.sync() })
afterEach(function() { Helpers.drop() })
var User = sequelize.define('User', { age: Sequelize.INTEGER, name: Sequelize.STRING, bio: Sequelize.TEXT })
describe('constructor', function() {
it("handles extended attributes (unique)", function() {
var User = sequelize.define('User' + config.rand(), {
username: { type: Sequelize.STRING, unique: true }
}, { timestamps: false })
expect(User.attributes).toEqual({username:"VARCHAR(255) UNIQUE",id:"INTEGER NOT NULL auto_increment PRIMARY KEY"})
})
it("handles extended attributes (default)", function() {
var User = sequelize.define('User' + config.rand(), {
username: {type: Sequelize.STRING, defaultValue: 'foo'}
}, { timestamps: false })
expect(User.attributes).toEqual({username:"VARCHAR(255) DEFAULT 'foo'",id:"INTEGER NOT NULL auto_increment PRIMARY KEY"})
})
it("handles extended attributes (null)", function() {
var User = sequelize.define('User' + config.rand(), {
username: {type: Sequelize.STRING, allowNull: false}
}, { timestamps: false })
expect(User.attributes).toEqual({username:"VARCHAR(255) NOT NULL",id:"INTEGER NOT NULL auto_increment PRIMARY KEY"})
})
it("handles extended attributes (comment)", function() {
var User = sequelize.define('User' + config.rand(), {
username: {type: Sequelize.STRING, comment: 'This be\'s a comment'}
}, { timestamps: false })
expect(User.attributes).toEqual({username:"VARCHAR(255) COMMENT 'This be\\'s a comment'",id:"INTEGER NOT NULL auto_increment PRIMARY KEY"})
})
it("handles extended attributes (primaryKey)", function() {
var User = sequelize.define('User' + config.rand(), {
username: {type: Sequelize.STRING, primaryKey: true}
}, { timestamps: false })
expect(User.attributes).toEqual({username:"VARCHAR(255) PRIMARY KEY"})
})
it("adds timestamps", function() {
var User1 = sequelize.define('User' + config.rand(), {})
var User2 = sequelize.define('User' + config.rand(), {}, { timestamps: true })
expect(User1.attributes).toEqual({id:"INTEGER NOT NULL auto_increment PRIMARY KEY", updatedAt:"DATETIME NOT NULL", createdAt:"DATETIME NOT NULL"})
expect(User2.attributes).toEqual({id:"INTEGER NOT NULL auto_increment PRIMARY KEY", updatedAt:"DATETIME NOT NULL", createdAt:"DATETIME NOT NULL"})
})
it("adds deletedAt if paranoid", function() {
var User = sequelize.define('User' + config.rand(), {}, { paranoid: true })
expect(User.attributes).toEqual({id:"INTEGER NOT NULL auto_increment PRIMARY KEY", deletedAt:"DATETIME", updatedAt:"DATETIME NOT NULL", createdAt:"DATETIME NOT NULL"})
})
it("underscores timestamps if underscored", function() {
var User = sequelize.define('User' + config.rand(), {}, { paranoid: true, underscored: true })
expect(User.attributes).toEqual({id:"INTEGER NOT NULL auto_increment PRIMARY KEY", deleted_at:"DATETIME", updated_at:"DATETIME NOT NULL", created_at:"DATETIME NOT NULL"})
})
})
describe('primaryKeys', function() {
it("determines the correct primaryKeys", function() {
var User = sequelize.define('User' + config.rand(), {
foo: {type: Sequelize.STRING, primaryKey: true},
bar: Sequelize.STRING
})
expect(User.primaryKeys).toEqual({"foo":"VARCHAR(255) PRIMARY KEY"})
})
})
})
var config = require("../config/config")
, Sequelize = require("../../index")
, sequelize = new Sequelize(config.postgres.database, config.postgres.username, config.postgres.password, {
logging: false,
port: config.postgres.port,
dialect: 'postgres'
})
, Helpers = new (require("../config/helpers"))(sequelize)
describe('HasMany', function() {
beforeEach(function() { Helpers.sync() })
afterEach(function() { Helpers.drop() })
//prevent periods from occurring in the table name since they are used to delimit (table.column)
var User = sequelize.define('User' + Math.ceil(Math.random()*10000000), { name: Sequelize.STRING })
, Task = sequelize.define('Task' + Math.ceil(Math.random()*10000000), { name: Sequelize.STRING })
, users = null
, tasks = null
User.hasMany(Task, {as:'Tasks'})
Task.hasMany(User, {as:'Users'})
beforeEach(function() {
Helpers.async(function(_done) {
Helpers.Factories.DAO(User.name, {name: 'User' + Math.random()}, function(_users) {
users = _users; _done()
}, 5)
})
Helpers.async(function(_done) {
Helpers.Factories.DAO(Task.name, {name: 'Task' + Math.random()}, function(_tasks) {
tasks = _tasks; _done()
}, 2)
})
})
describe('addDAO / getDAO', function() {
var user = null
, task = null
beforeEach(function() {
Helpers.async(function(done) {
User.all().on('success', function(_users) {
Task.all().on('success', function(_tasks) {
user = _users[0]
task = _tasks[0]
done()
})
})
})
})
it('should correctly add an association to the dao', function() {
Helpers.async(function(done) {
user.getTasks().on('success', function(_tasks) {
expect(_tasks.length).toEqual(0)
user.addTask(task).on('success', function() {
user.getTasks().on('success', function(_tasks) {
expect(_tasks.length).toEqual(1)
done()
})
})
})
})
})
})
describe('removeDAO', function() {
var user = null
, tasks = null
beforeEach(function() {
Helpers.async(function(done) {
User.all().on('success', function(users) {
Task.all().on('success', function(_tasks) {
user = users[0]
tasks = _tasks
done()
})
})
})
})
it("should correctly remove associated objects", function() {
Helpers.async(function(done) {
user.getTasks().on('success', function(__tasks) {
expect(__tasks.length).toEqual(0)
user.setTasks(tasks).on('success', function() {
user.getTasks().on('success', function(_tasks) {
expect(_tasks.length).toEqual(tasks.length)
user.removeTask(tasks[0]).on('success', function() {
user.getTasks().on('success', function(_tasks) {
expect(_tasks.length).toEqual(tasks.length - 1)
done()
})
})
})
})
})
})
})
})
})
var config = require("../config/config")
, Sequelize = require("../../index")
, sequelize = new Sequelize(config.postgres.database, config.postgres.username, config.postgres.password, {
logging: false,
port: config.postgres.port,
dialect: 'postgres'
})
, Helpers = new (require("../config/helpers"))(sequelize)
describe('Associations', function() {
beforeEach(function() { Helpers.sync() })
afterEach(function() { Helpers.drop() })
/////////// many-to-many with same prefix ////////////
describe('many-to-many', function() {
describe('where tables have the same prefix', function() {
var Table2 = sequelize.define('wp_table2', {foo: Sequelize.STRING})
, Table1 = sequelize.define('wp_table1', {foo: Sequelize.STRING})
Table1.hasMany(Table2)
Table2.hasMany(Table1)
it("should create a table wp_table1wp_table2s", function() {
Helpers.async(function(done) {
expect(sequelize.daoFactoryManager.getDAO('wp_table1swp_table2s')).toBeDefined()
done()
})
})
})
describe('when join table name is specified', function() {
var Table2 = sequelize.define('ms_table1', {foo: Sequelize.STRING})
, Table1 = sequelize.define('ms_table2', {foo: Sequelize.STRING})
Table1.hasMany(Table2, {joinTableName: 'table1_to_table2'})
Table2.hasMany(Table1, {joinTableName: 'table1_to_table2'})
it("should not use a combined name", function() {
expect(sequelize.daoFactoryManager.getDAO('ms_table1sms_table2s')).toBeUndefined()
})
it("should use the specified name", function() {
expect(sequelize.daoFactoryManager.getDAO('table1_to_table2')).toBeDefined()
})
})
})
})
var config = require("./config/config")
, Sequelize = require("../index")
, QueryInterface = require("../lib/query-interface")
describe('Sequelize', function() {
var sequelize = null
, Helpers = null
var setup = function(options) {
options = options || {}
if (!options.hasOwnProperty('pool'))
options.pool = config.mysql.pool
if (!options.hasOwnProperty('logging'))
options.logging = false
if (!options.hasOwnProperty('host'))
options.host = config.mysql.host
if (!options.hasOwnProperty('port'))
options.port = config.mysql.port
sequelize = new Sequelize(config.mysql.database, config.mysql.username, config.mysql.password, options)
Helpers = new (require("./config/helpers"))(sequelize)
return options
}
beforeEach(function() { setup() })
afterEach(function() { sequelize = null })
describe('constructor', function() {
it('should pass the global options correctly', function() {
setup({ logging: false, define: { underscored:true } })
var DAO = sequelize.define('dao', {name: Sequelize.STRING})
expect(DAO.options.underscored).toBeTruthy()
})
it('should correctly set the host and the port', function() {
var options = setup({ host: '127.0.0.1', port: 1234 })
expect(sequelize.config.host).toEqual(options.host)
expect(sequelize.config.port).toEqual(options.port)
})
})
describe('define', function() {
it("adds a new dao to the dao manager", function() {
expect(sequelize.daoFactoryManager.all.length).toEqual(0)
sequelize.define('foo', { title: Sequelize.STRING })
expect(sequelize.daoFactoryManager.all.length).toEqual(1)
})
it("overwrites global options", function() {
setup({ define: { collate: 'utf8_general_ci' } })
var DAO = sequelize.define('foo', {bar: Sequelize.STRING}, {collate: 'utf8_bin'})
expect(DAO.options.collate).toEqual('utf8_bin')
})
it("inherits global collate option", function() {
setup({ define: { collate: 'utf8_general_ci' } })
var DAO = sequelize.define('foo', {bar: Sequelize.STRING})
expect(DAO.options.collate).toEqual('utf8_general_ci')
})
it("inherits global classMethods and instanceMethods", function() {
setup({
define: {
classMethods : { globalClassMethod : function() {} },
instanceMethods : { globalInstanceMethod : function() {} }
}
})
var DAO = sequelize.define('foo', {bar: Sequelize.STRING}, {
classMethods : { localClassMethod : function() {} }
})
expect(typeof DAO.options.classMethods.globalClassMethod).toEqual('function')
expect(typeof DAO.options.classMethods.localClassMethod).toEqual('function')
expect(typeof DAO.options.instanceMethods.globalInstanceMethod).toEqual('function')
})
it("uses the passed tableName", function(done) {
var Photo = sequelize.define('Foto', { name: Sequelize.STRING }, { tableName: 'photos' })
Photo.sync({ force: true }).success(function() {
sequelize.getQueryInterface().showAllTables().success(function(tableNames) {
expect(tableNames).toContain('photos')
done()
})
})
})
})
describe('sync', function() {
it("synchronizes all daos", function() {
var Project = sequelize.define('project' + config.rand(), { title: Sequelize.STRING })
var Task = sequelize.define('task' + config.rand(), { title: Sequelize.STRING })
Helpers.async(function(done) {
sequelize.sync().success(function() {
Project.create({title: 'bla'}).success(function() {
Task.create({title: 'bla'}).success(done)
})
})
})
})
})
describe('import', function() {
it("imports a dao definition from a file", function() {
var Project = sequelize.import(__dirname + "/assets/project")
expect(Project).toBeDefined()
})
})
})
var config = require("../config/config")
, Sequelize = require("../../index")
, dbFile = __dirname + '/test.sqlite'
, storages = [':memory:', dbFile]
describe('DAOFactory', function() {
storages.forEach(function(storage) {
describe('with storage "' + storage + '"', function() {
var User = null
, sequelize = null
, Helpers = null
beforeEach(function() {
sequelize = new Sequelize(config.database, config.username, config.password, {
logging: false,
dialect: 'sqlite',
storage: storage
})
Helpers = new (require("../config/helpers"))(sequelize)
User = sequelize.define('User', {
age: Sequelize.INTEGER,
name: Sequelize.STRING,
bio: Sequelize.TEXT
})
Helpers.sync()
})
afterEach(function() {
Helpers.dropAllTables()
if(storage == dbFile) {
Helpers.async(function(done) {
require("fs").unlink(__dirname + '/test.sqlite', done)
})
}
})
describe('create', function() {
it('creates a table entry', function() {
Helpers.async(function(done) {
User
.create({ age: 21, name: 'John Wayne', bio: 'noot noot' })
.success(done)
.error(function(err) { console.log(err) })
})
Helpers.async(function(done) {
User.all().success(function(users) {
var usernames = users.map(function(user) {
return user.name
})
expect(usernames).toEqual(['John Wayne'])
done()
}).error(function(err){ console.log(err) })
})
})
it('should allow the creation of an object with options as attribute', function() {
var Person = sequelize.define('Person', {
name: Sequelize.STRING,
options: Sequelize.TEXT
})
Helpers.async(function(done) {
Person.sync({force: true}).success(done)
})
Helpers.async(function(done) {
var options = JSON.stringify({ foo: 'bar', bar: 'foo' })
Helpers.Factories.DAO('Person', {
name: 'John Doe',
options: options
}, function(people) {
expect(people[0].options).toEqual(options)
done()
})
})
})
it('should allow the creation of an object with a boolean (true) as attribute', function() {
var Person = sequelize.define('Person', {
name: Sequelize.STRING,
has_swag: Sequelize.BOOLEAN
})
Helpers.async(function(done) {
Person.sync({force: true}).success(done)
})
Helpers.async(function(done) {
Helpers.Factories.DAO('Person', {
name: 'John Doe',
has_swag: true
}, function(people) {
expect(people[0].has_swag).toBeTruthy();
done()
})
})
})
it('should allow the creation of an object with a boolean (false) as attribute', function() {
var Person = sequelize.define('Person', {
name: Sequelize.STRING,
has_swag: Sequelize.BOOLEAN
})
Helpers.async(function(done) {
Person.sync({force: true}).success(done)
})
Helpers.async(function(done) {
Helpers.Factories.DAO('Person', {
name: 'John Doe',
has_swag: false
}, function(people) {
expect(people[0].has_swag).toBeFalsy();
done()
})
})
})
})
////////// find //////////////
describe('.find', function() {
beforeEach(function() {
Helpers.Factories.User({name: 'user', bio: 'foobar'}, null, 2)
})
it("finds normal lookups", function() {
Helpers.async(function(done) {
User.find({ where: { name:'user' } }).success(function(user) {
expect(user.name).toEqual('user')
done()
})
})
})
it("should make aliased attributes available", function() {
Helpers.async(function(done) {
User.find({ where: { name:'user' }, attributes: ['id', ['name', 'username']] }).success(function(user) {
expect(user.username).toEqual('user')
done()
})
})
})
})
////////// all //////////////
describe('.all', function() {
beforeEach(function() {
Helpers.Factories.User({name: 'user', bio: 'foobar'}, null, 2)
})
it("should return all users", function() {
Helpers.async(function(done) {
User.all().on('success', function(users) {
done()
expect(users.length).toEqual(2)
}).on('error', function(err) { console.log(err) })
})
})
})
////////// min //////////////
describe('.min', function() {
it("should return the min value", function() {
for(var i = 2; i < 5; i++) Helpers.Factories.User({ age: i })
Helpers.async(function(done) {
User.min('age').on('success', function(min) {
expect(min).toEqual(2); done()
})
})
})
})
////////// max //////////////
describe('.max', function() {
it("should return the max value", function() {
for(var i = 2; i <= 5; i++) Helpers.Factories.User({ age: i })
Helpers.async(function(done) {
User.max('age').on('success', function(min) {
expect(min).toEqual(5); done()
})
})
})
})
})
})
})
// var config = require("./config/config")
// , Sequelize = require("../index")
// , User = null
// , sequelize = new Sequelize(config.database, config.username, config.password, {
// logging: false,
// dialect: dialect
// })
// , Helpers = new (require("./config/helpers"))(sequelize)
// describe('DAO', function() {
// var setup = function() {
// Helpers.async(function(done) {
// User = sequelize.define('User', { username: Sequelize.STRING })
// User.sync({ force: true }).success(done)
// })
// }
// beforeEach(function() { Helpers.dropAllTables(); setup() })
// afterEach(function() { Helpers.dropAllTables() })
// describe('findAll', function() {
// it("can handle dates correctly", function() {
// })
// })
// })
/* jshint camelcase: false */
if (typeof require === 'function') {
const buster = require("buster")
, Helpers = require('../buster-helpers')
......@@ -19,6 +20,137 @@ describe(Helpers.getTestDialectTeaser("BelongsTo"), function() {
})
})
describe('general usage', function() {
before(function(done) {
this.User = this.sequelize.define('User', {
username: Helpers.Sequelize.STRING,
enabled: {
type: Helpers.Sequelize.BOOLEAN,
defaultValue: true
}
})
this.Task = this.sequelize.define('Task', {
title: Helpers.Sequelize.STRING
})
this.sequelize.sync({ force: true }).success(done)
})
it('adds the foreign key', function(done) {
this.Task.belongsTo(this.User)
expect(this.Task.attributes.UserId).toEqual("INTEGER")
done()
})
it("underscores the foreign key", function(done) {
var Task = this.sequelize.define('Task', { title: Sequelize.STRING }, {underscored: true})
Task.belongsTo(this.User)
expect(Task.attributes.user_id).toEqual("INTEGER")
done()
})
it("uses the passed foreign key", function(done) {
this.Task.belongsTo(this.User, {foreignKey: 'person_id'})
expect(this.Task.attributes.person_id).toEqual("INTEGER")
done()
})
it("defines getters and setters", function(done) {
this.Task.belongsTo(this.User)
var task = this.Task.build({title: 'asd'})
expect(task.setUser).toBeDefined()
expect(task.getUser).toBeDefined()
done()
})
it("aliases the getters and setters according to the passed 'as' option", function(done) {
this.Task.belongsTo(this.User, {as: 'Person'})
var task = this.Task.build({title: 'asd'})
expect(task.setPerson).toBeDefined()
expect(task.getPerson).toBeDefined()
done()
})
it("aliases associations to the same table according to the passed 'as' option", function(done) {
this.Task.belongsTo(this.User, {as: 'Poster'})
this.Task.belongsTo(this.User, {as: 'Owner'})
var task = this.Task.build({title: 'asd'})
expect(task.getPoster).toBeDefined()
expect(task.setPoster).toBeDefined()
expect(task.getOwner).toBeDefined()
expect(task.setOwner).toBeDefined()
done()
})
it("intializes the foreign key with null", function(done) {
this.Task.belongsTo(this.User)
var task = this.Task.build({title: 'asd'})
expect(task.UserId).not.toBeDefined();
done()
})
it("sets and gets the correct objects", function(done) {
var self = this
this.Task.belongsTo(this.User, {as: 'User'})
this.sequelize.sync({ force: true }).success(function() {
self.User.create({username: 'asd'}).success(function(u) {
self.Task.create({title: 'a task'}).success(function(t) {
t.setUser(u).success(function() {
t.getUser().success(function(user) {
expect(user.username).toEqual('asd')
done()
})
})
})
})
})
})
it('extends the id where param with the supplied where params', function(done) {
var self = this
this.Task.belongsTo(this.User, {as: 'User'})
this.sequelize.sync({ force: true }).success(function() {
self.User.create({username: 'asd', enabled: false}).success(function(u) {
self.Task.create({title: 'a task'}).success(function(t) {
t.setUser(u).success(function() {
t.getUser({where: {enabled: true}}).success(function(user) {
expect(user).toEqual(null)
done()
})
})
})
})
})
})
it("handles self associations", function(done) {
var Person = this.sequelize.define('Person', { name: Helpers.Sequelize.STRING })
Person.belongsTo(Person, {as: 'Mother', foreignKey: 'MotherId'})
Person.belongsTo(Person, {as: 'Father', foreignKey: 'FatherId'})
Person.sync({force: true}).success(function() {
var p = Person.build()
expect(p.setFather).toBeDefined()
expect(p.setMother).toBeDefined()
done()
})
})
it("sets the foreign key in self associations", function(done) {
var Person = this.sequelize.define('Person', { name: Helpers.Sequelize.STRING })
Person.belongsTo(Person, {as: 'Mother'})
expect(Person.associations.MotherPersons.options.foreignKey).toEqual('MotherId')
done()
})
})
describe('setAssociation', function() {
it('clears the association if null is passed', function(done) {
var User = this.sequelize.define('UserXYZ', { username: Sequelize.STRING })
......
/* jshint camelcase: false */
if (typeof require === 'function') {
const buster = require("buster")
, Helpers = require('../buster-helpers')
......@@ -11,7 +12,6 @@ buster.spec.expose()
buster.testRunner.timeout = 500
describe(Helpers.getTestDialectTeaser("HasMany"), function() {
before(function(done) {
var self = this
......@@ -22,6 +22,350 @@ describe(Helpers.getTestDialectTeaser("HasMany"), function() {
})
})
describe('general usage', function() {
before(function(done) {
this.User = this.sequelize.define('User', { username: Helpers.Sequelize.STRING })
this.Task = this.sequelize.define('Task', { title: Helpers.Sequelize.STRING })
this.sequelize.sync({ force: true }).success(done)
})
describe('mono-directional', function() {
it("adds the foreign key", function(done) {
this.User.hasMany(this.Task)
expect(this.Task.attributes.UserId).toEqual("INTEGER")
done()
})
it('adds the foreign key with underscore', function(done) {
var User = this.sequelize.define('User', { username: Helpers.Sequelize.STRING })
, Task = this.sequelize.define('Task', { title: Helpers.Sequelize.STRING }, { underscored: true })
Task.hasMany(User)
expect(User.attributes.task_id).toBeDefined()
done()
})
it('uses the passed foreign key', function(done) {
this.User.hasMany(this.Task, { foreignKey: 'person_id' })
expect(this.Task.attributes.person_id).toEqual("INTEGER")
done()
})
it('defines getters and setters', function(done) {
this.User.hasMany(this.Task)
var u = this.User.build({username: 'asd'})
expect(u.setTasks).toBeDefined()
expect(u.getTasks).toBeDefined()
done()
})
it("defines getters and setters according to the 'as' option", function(done) {
this.User.hasMany(this.Task, {as: 'Tasks'})
var u = this.User.build({username: 'asd'})
expect(u.setTasks).toBeDefined()
expect(u.getTasks).toBeDefined()
done()
})
it("sets and gets associated objects", function(done) {
var self = this
this.User.hasMany(this.Task, { as: 'Tasks' })
this.sequelize.sync({ force: true }).success(function() {
self.User.create({username: 'name'}).success(function(user) {
self.Task.create({title: 'task1'}).success(function(task1) {
self.Task.create({title: 'task2'}).success(function(task2) {
user.setTasks([task1, task2]).success(function() {
user.getTasks().success(function(tasks) {
expect(tasks.length).toEqual(2)
user.getTasks({attributes: ['title']}).success(function(tasks) {
expect(tasks[0].selectedValues.title).toEqual('task1')
expect(tasks[0].selectedValues.id).not.toBeDefined()
done()
})
})
})
})
})
})
})
})
})
it("should allow selfAssociation to be single linked (only one DAO is created)", function(done) {
var oldLength = this.sequelize.daoFactoryManager.daos.length
, Comment = this.sequelize.define('Comment', { content: Helpers.Sequelize.STRING })
Comment.belongsTo(Comment, {as: "Parent"});
Comment.hasMany(Comment, {as: 'Children', foreignKey: "ParentId", useJunctionTable: false})
expect(this.sequelize.daoFactoryManager.daos.length).toEqual(oldLength + 1)
Comment.sync({force: true}).success(function() {
Comment.create({ content: 'parentComment' }).success(function(parent) {
Comment.create({ content: 'child1' }).success(function(child1) {
child1.setParent(parent).success(function() {
Comment.create({ content: 'child2' }).success(function(child2) {
child2.setParent(parent).success(function() {
Comment.find({where: { content: 'parentComment' }}).success(function(parent) {
parent.getChildren().success(function(children) {
expect(children.length).toEqual(2)
done()
})
})
})
})
})
})
})
})
})
it("should still use many to many for selfAssociation by default (two DAOs are created)", function(done) {
var oldLength = this.sequelize.daoFactoryManager.daos.length
, Comment = this.sequelize.define('Comment', { content: Sequelize.STRING })
Comment.belongsTo(Comment, {as: "Parent"})
Comment.hasMany(Comment, {as: 'Children'})
expect(this.sequelize.daoFactoryManager.daos.length).toEqual(oldLength + 2)
done();
})
describe('bi-directional', function() {
it('adds the foreign key', function(done) {
var self = this
this.Task.hasMany(this.User)
this.User.hasMany(this.Task)
expect(this.Task.attributes.UserId).not.toBeDefined()
expect(this.User.attributes.UserId).not.toBeDefined()
var daos = this.sequelize.daoFactoryManager.daos.filter(function(dao) {
return (dao.tableName == (self.Task.tableName + self.User.tableName))
})
daos.forEach(function(dao) {
expect(dao.attributes.UserId).toBeDefined()
expect(dao.attributes.TaskId).toBeDefined()
})
done()
})
it("adds the foreign key with underscores", function(done) {
var User = this.sequelize.define('User', { username: Helpers.Sequelize.STRING }, { underscored: true })
, Task = this.sequelize.define('Task', { title: Helpers.Sequelize.STRING })
Task.hasMany(User)
User.hasMany(Task)
expect(Task.attributes.user_id).not.toBeDefined()
expect(User.attributes.user_id).not.toBeDefined()
var daos = this.sequelize.daoFactoryManager.daos.filter(function(dao) {
return (dao.tableName == (Task.tableName + User.tableName))
})
daos.forEach(function(dao) {
expect(dao.attributes.user_id).toBeDefined()
expect(dao.attributes.TaskId).toBeDefined()
})
done()
})
it("uses the passed foreign keys", function(done) {
var self = this
this.User.hasMany(this.Task, { foreignKey: 'person_id' })
this.Task.hasMany(this.User, { foreignKey: 'work_item_id' })
var daos = this.sequelize.daoFactoryManager.daos.filter(function(dao) {
return (dao.tableName == (self.Task.tableName + self.User.tableName))
})
daos.forEach(function(dao) {
expect(dao.attributes.person_id).toBeDefined()
expect(dao.attributes.work_item_id).toBeDefined()
})
done()
})
it("defines getters and setters", function(done) {
this.User.hasMany(this.Task)
this.Task.hasMany(this.User)
var u = this.User.build({ username: 'asd' })
expect(u.setTasks).toBeDefined()
expect(u.getTasks).toBeDefined()
var t = this.Task.build({ title: 'foobar' })
expect(t.setUsers).toBeDefined()
expect(t.getUsers).toBeDefined()
done()
})
it("defines getters and setters according to the 'as' option", function(done) {
this.User.hasMany(this.Task, { as: 'Tasks' })
this.Task.hasMany(this.User, { as: 'Users' })
var u = this.User.build({ username: 'asd' })
expect(u.setTasks).toBeDefined()
expect(u.getTasks).toBeDefined()
var t = this.Task.build({ title: 'asd' })
expect(t.setUsers).toBeDefined()
expect(t.getUsers).toBeDefined()
done()
})
it("sets and gets the corrected associated objects", function(done) {
var self = this
var users = []
, tasks = []
this.User.hasMany(this.Task, {as: 'Tasks'})
this.Task.hasMany(this.User, {as: 'Users'})
this.sequelize.sync({ force: true }).success(function() {
self.User.create({username: 'name'}).success(function(user1) {
self.User.create({username: 'name2'}).success(function(user2) {
self.Task.create({title: 'task1'}).success(function(task1) {
self.Task.create({title: 'task2'}).success(function(task2) {
users.push(user1)
users.push(user2)
tasks.push(task1)
tasks.push(task2)
users[0].setTasks(tasks).success(function() {
users[0].getTasks().success(function(_tasks) {
expect(_tasks.length).toEqual(2)
tasks[1].setUsers(users).success(function() {
tasks[1].getUsers().success(function(_users) {
expect(users.length).toEqual(2)
done()
})
})
})
})
})
})
})
})
})
})
})
it("build the connector daos name", function(done) {
var self = this
, Person = this.sequelize.define('Person', { name: Helpers.Sequelize.STRING })
Person.hasMany(Person, {as: 'Children'})
Person.hasMany(Person, {as: 'Friends'})
Person.hasMany(Person, {as: 'CoWorkers'})
Person.sync({force: true}).success(function() {
var daoNames = self.sequelize.daoFactoryManager.daos.map(function(dao) { return dao.tableName })
, expectation = ["Persons", "ChildrenPersons", "CoWorkersPersons", "FriendsPersons"]
expectation.forEach(function(ex) {
expect(daoNames.indexOf(ex) > -1).toBeTruthy()
})
done()
})
})
it("allows join table to be specified", function(done) {
var Child = this.sequelize.define('Child', { name: Helpers.Sequelize.STRING }, {underscore: true, freezeTableName: true})
, Parent = this.sequelize.define('Parent', { name: Helpers.Sequelize.STRING }, {underscore: true, freezeTableName: true})
, ParentJoin = this.sequelize.define('ParentRelationship', { parent_id: Helpers.Sequelize.INTEGER, child_id: Helpers.Sequelize.INTEGER }, {underscore: true, freezeTableName: true})
, parents = []
Parent.hasMany(Child, {as: 'Children', foreignKey: 'child_id', joinTableName: 'ParentRelationship'})
Child.hasMany(Parent, {as: 'Parents', foreignKey: 'parent_id', joinTableName: 'ParentRelationship'})
this.sequelize.sync({ force: true }).success(function() {
Parent.create({name: 'mom'}).success(function(mom) {
parents.push(mom)
Parent.create({name: 'dad'}).success(function(dad) {
parents.push(dad)
Child.create({name: 'baby'}).success(function(baby) {
baby.setParents(parents).success(function(){
parents[0].getChildren().success(function(children){
expect(children).not.toBe(null)
expect(children.length).toBeDefined()
expect(children.length).toEqual(1)
expect(children[0]).toBeDefined()
expect(children[0].name).toEqual('baby')
done()
})
})
})
})
})
})
})
it("allows join table to be mapped and specified", function(done) {
var User = this.sequelize.define('User', { name: Helpers.Sequelize.STRING }, {underscore: true, freezeTableName: true})
, Company = this.sequelize.define('Company', { name: Helpers.Sequelize.STRING }, {underscore: true, freezeTableName: true})
, CompanyAccess = this.sequelize.define('CompanyAccess', { company_id: Helpers.Sequelize.INTEGER, user_id: Helpers.Sequelize.INTEGER, permission: Helpers.Sequelize.STRING }, {underscore: true, freezeTableName: true})
, companies = []
CompanyAccess.belongsTo(User, {as: 'User', foreignKey: 'user_id'})
CompanyAccess.belongsTo(Company, {as: 'Company', foreignKey: 'company_id'})
User.hasMany(Company, {as: 'Companies', foreignKey: 'user_id', joinTableName: 'CompanyAccess'})
Company.hasMany(User, {as: 'Users', foreignKey: 'company_id', joinTableName: 'CompanyAccess'})
this.sequelize.sync({ force: true }).success(function() {
Company.create({name: 'IBM'}).success(function(ibm) {
companies.push(ibm)
Company.create({name: 'EA'}).success(function(ea) {
companies.push(ea)
User.create({name: 'joe@ibm.com'}).success(function(joe) {
joe.setCompanies(companies).success(function(){
User.find({where: {name: 'joe@ibm.com'}}).success(function(joe) {
expect(joe).not.toEqual(null)
joe.getCompanies().success(function(comps) {
expect(comps).not.toEqual(null)
expect(comps.length).toEqual(2)
done()
})
})
})
})
})
})
})
})
it("gets and sets the connector daos", function(done) {
var Person = this.sequelize.define('Person', { name: Helpers.Sequelize.STRING })
Person.hasMany(Person, {as: 'Children'})
Person.hasMany(Person, {as: 'Friends'})
Person.hasMany(Person, {as: 'CoWorkers'})
Person.sync({ force: true }).success(function() {
Person.create({name: 'foobar'}).success(function(person) {
Person.create({name: 'friend'}).success(function(friend) {
person.setFriends([friend]).success(function() {
person.getFriends().success(function(friends) {
expect(friends.length).toEqual(1)
expect(friends[0].name).toEqual('friend')
done()
})
})
})
})
})
})
})
describe('(1:N)', function() {
describe('hasSingle', function() {
before(function(done) {
......
/* jshint camelcase: false */
if (typeof require === 'function') {
const buster = require("buster")
, Sequelize = require("../../index")
......@@ -19,6 +20,136 @@ describe(Helpers.getTestDialectTeaser("HasOne"), function() {
})
})
describe('general usage', function() {
before(function(done) {
this.User = this.sequelize.define('User', { username: Helpers.Sequelize.STRING })
this.Task = this.sequelize.define('Task', { title: Helpers.Sequelize.STRING })
this.sequelize.sync({ force: true }).success(done)
})
it("adds the foreign key", function(done) {
this.User.hasOne(this.Task)
expect(this.Task.attributes.UserId).toEqual("INTEGER")
done()
})
it("adds an underscored foreign key", function(done) {
var User = this.sequelize.define('User', { username: Helpers.Sequelize.STRING }, {underscored: true})
, Task = this.sequelize.define('Task', { title: Helpers.Sequelize.STRING })
User.hasOne(Task)
expect(Task.attributes.user_id).toEqual("INTEGER")
done()
})
it("uses the passed foreign key", function(done) {
var User = this.sequelize.define('User', { username: Helpers.Sequelize.STRING }, {underscored: true})
, Task = this.sequelize.define('Task', { title: Helpers.Sequelize.STRING })
User.hasOne(Task, {foreignKey: 'person_id'})
expect(Task.attributes.person_id).toEqual("INTEGER")
done()
})
it("defines the getter and the setter", function(done) {
this.User.hasOne(this.Task)
var u = this.User.build({username: 'asd'})
expect(u.setTask).toBeDefined()
expect(u.getTask).toBeDefined()
done()
})
it("defined the getter and the setter according to the passed 'as' option", function(done) {
this.User.hasOne(this.Task, {as: 'Work'})
var u = this.User.build({username: 'asd'})
expect(u.setWork).toBeDefined()
expect(u.getWork).toBeDefined()
done()
})
it("aliases associations to the same table according to the passed 'as' option", function(done) {
this.User.hasOne(this.Task, {as: 'Work'});
this.User.hasOne(this.Task, {as: 'Play'});
var u = this.User.build({username: 'asd'})
expect(u.getWork).toBeDefined()
expect(u.setWork).toBeDefined()
expect(u.getPlay).toBeDefined()
expect(u.setPlay).toBeDefined()
done()
})
it("gets and sets the correct objects", function(done) {
var self = this
this.User.hasOne(this.Task, {as: 'Task'})
this.sequelize.sync({ force: true }).success(function() {
self.User.create({username: 'name'}).success(function(user) {
self.Task.create({title: 'snafu'}).success(function(task) {
user.setTask(task).on('success', function() {
user.getTask().on('success', function(task2) {
expect(task.title).toEqual(task2.title)
user.getTask({attributes: ['title']}).on('success', function(task2) {
expect(task2.selectedValues.title).toEqual('snafu')
expect(task2.selectedValues.id).not.toBeDefined()
done()
})
})
})
})
})
})
})
it("unsets unassociated objects", function(done) {
var self = this
this.User.hasOne(this.Task, {as: 'Task'})
this.sequelize.sync({ force: true }).success(function() {
self.User.create({username: 'name'}).success(function(user) {
self.Task.create({title: 'snafu'}).success(function(task1) {
self.Task.create({title: 'another task'}).success(function(task2) {
user.setTask(task1).success(function() {
user.getTask().success(function(_task) {
expect(task1.title).toEqual(_task.title)
user.setTask(task2).success(function() {
user.getTask().success(function(_task2) {
expect(task2.title).toEqual(_task2.title)
done()
})
})
})
})
})
})
})
})
})
it("sets self associations", function(done) {
var Person = this.sequelize.define('Person', { name: Helpers.Sequelize.STRING })
Person.hasOne(Person, {as: 'Mother', foreignKey: 'MotherId'})
Person.hasOne(Person, {as: 'Father', foreignKey: 'FatherId'})
Person.sync({force: true}).success(function() {
var p = Person.build()
expect(p.setFather).toBeDefined()
expect(p.setMother).toBeDefined()
done()
})
})
it("automatically sets the foreign key on self associations", function(done) {
var Person = this.sequelize.define('Person', { name: Helpers.Sequelize.STRING })
Person.hasOne(Person, {as: 'Mother'})
expect(Person.associations.MotherPersons.options.foreignKey).toEqual('MotherId')
done()
})
})
describe('getAssocation', function() {
it('should be able to handle a where object that\'s a first class citizen.', function(done) {
var User = this.sequelize.define('UserXYZ', { username: Sequelize.STRING })
......@@ -70,7 +201,6 @@ describe(Helpers.getTestDialectTeaser("HasOne"), function() {
})
describe("Foreign key constraints", function() {
it("are not enabled by default", function(done) {
var Task = this.sequelize.define('Task', { title: Sequelize.STRING })
, User = this.sequelize.define('User', { username: Sequelize.STRING })
......
......@@ -18,6 +18,16 @@ describe(Helpers.getTestDialectTeaser("Mixin"), function() {
})
})
describe('Mixin', function() {
var DAOFactory = require("../../lib/dao-factory")
it("adds the mixed-in functions to the dao", function() {
expect(DAOFactory.prototype.hasOne).toBeDefined()
expect(DAOFactory.prototype.hasMany).toBeDefined()
expect(DAOFactory.prototype.belongsTo).toBeDefined()
})
})
describe('getAssociation', function() {
it('returns the respective part of the association for 1:1 associations', function() {
var User = this.sequelize.define('User', {})
......
......@@ -30,23 +30,37 @@ var BusterHelpers = module.exports = {
options.dialect = options.dialect || 'mysql'
options.logging = (options.hasOwnProperty('logging') ? options.logging : false)
options.pool = options.pool || config.pool
var sequelizeOptions = {
logging: options.logging,
dialect: options.dialect,
port: process.env.SEQ_PORT || config[options.dialect].port
port: options.port || process.env.SEQ_PORT || config[options.dialect].port,
pool: options.pool
}
if (!!options.host) {
sequelizeOptions.host = options.host
}
if (!!options.define) {
sequelizeOptions.define = options.define
}
if (process.env.DIALECT === 'postgres-native') {
sequelizeOptions.native = true
}
return new Sequelize(
process.env.SEQ_DB || config[options.dialect].database,
return this.getSequelizeInstance(
process.env.SEQ_DB || config[options.dialect].database,
process.env.SEQ_USER || process.env.SEQ_USERNAME || config[options.dialect].username,
process.env.SEQ_PW || process.env.SEQ_PASSWORD || config[options.dialect].password,
sequelizeOptions
)
)
},
getSequelizeInstance: function(db, user, pass, options) {
return new Sequelize(db, user, pass, options)
},
clearDatabase: function(sequelize, callback) {
......
......@@ -3,6 +3,7 @@ if(typeof require === 'function') {
, Sequelize = require("../index")
, Helpers = require('./buster-helpers')
, _ = require('lodash')
, moment = require('moment')
, dialect = Helpers.getTestDialect()
}
......@@ -742,6 +743,26 @@ describe(Helpers.getTestDialectTeaser("DAOFactory"), function() {
}) // - bulkCreate
describe('update', function() {
it('allows sql logging of updated statements', function(done) {
var User = this.sequelize.define('User', {
name: Sequelize.STRING,
bio: Sequelize.TEXT
}, {
paranoid:true
})
this.sequelize.sync({ force: true }).success(function() {
User.create({ name: 'meg', bio: 'none' }).success(function(u) {
expect(u).toBeDefined()
expect(u).not.toBeNull()
u.updateAttributes({name: 'brian'}).on('sql', function(sql) {
expect(sql).toBeDefined()
expect(sql.toUpperCase().indexOf("UPDATE")).toBeGreaterThan(-1)
done()
})
})
})
})
it('updates only values that match filter', function(done) {
var self = this
......@@ -799,6 +820,45 @@ describe(Helpers.getTestDialectTeaser("DAOFactory"), function() {
}) // - update
describe('destroy', function() {
it('deletes a record from the database if dao is not paranoid', function(done) {
var User = this.sequelize.define('User', {
name: Sequelize.STRING,
bio: Sequelize.TEXT
})
this.sequelize.sync({ force: true }).success(function() {
User.create({name: 'hallo', bio: 'welt'}).success(function(u) {
User.all().success(function(users) {
expect(users.length).toEqual(1)
u.destroy().success(function() {
User.all().success(function(users) {
expect(users.length).toEqual(0)
done()
})
})
})
})
})
})
it('allows sql logging of delete statements', function(done) {
var User = this.sequelize.define('User', {
name: Sequelize.STRING,
bio: Sequelize.TEXT
})
this.sequelize.sync({ force: true }).success(function() {
User.create({name: 'hallo', bio: 'welt'}).success(function(u) {
User.all().success(function(users) {
expect(users.length).toEqual(1)
u.destroy().on('sql', function(sql) {
expect(sql).toBeDefined()
expect(sql.toUpperCase().indexOf("DELETE")).toBeGreaterThan(-1)
done()
})
})
})
})
})
it('deletes values that match filter', function(done) {
var self = this
......@@ -807,14 +867,11 @@ describe(Helpers.getTestDialectTeaser("DAOFactory"), function() {
{ username: 'Bob', secretValue: '43' }]
this.User.bulkCreate(data).success(function() {
self.User.destroy({secretValue: '42'})
.success(function() {
self.User.findAll({order: 'id'}).success(function(users) {
expect(users.length).toEqual(1)
expect(users[0].username).toEqual("Bob")
done()
})
})
......@@ -822,7 +879,6 @@ describe(Helpers.getTestDialectTeaser("DAOFactory"), function() {
})
it('sets deletedAt to the current timestamp if paranoid is true', function(done) {
var self = this
, User = this.sequelize.define('ParanoidUser', {
username: Sequelize.STRING,
......@@ -837,9 +893,7 @@ describe(Helpers.getTestDialectTeaser("DAOFactory"), function() {
{ username: 'Bob', secretValue: '43' }]
User.sync({ force: true }).success(function() {
User.bulkCreate(data).success(function() {
User.destroy({secretValue: '42'})
.success(function() {
User.findAll({order: 'id'}).success(function(users) {
......@@ -856,11 +910,8 @@ describe(Helpers.getTestDialectTeaser("DAOFactory"), function() {
})
})
})
})
})
}) // - destroy
describe('special where conditions', function() {
......@@ -1860,8 +1911,248 @@ describe(Helpers.getTestDialectTeaser("DAOFactory"), function() {
})
}) // - describe: queryOptions
})
describe('normal findAll', function() {
beforeEach(function(done) {
var self = this
this.User.create({username: 'user', data: 'foobar', theDate: moment().toDate()}).success(function(user) {
self.User.create({username: 'user2', data: 'bar', theDate: moment().toDate()}).success(function(user2){
self.users = [user].concat(user2)
done()
})
})
})
it("finds all entries", function(done) {
this.User.findAll().on('success', function(users) {
expect(users.length).toEqual(2)
done()
})
})
it("finds all users matching the passed conditions", function(done) {
this.User.findAll({where: "id != " + this.users[1].id}).success(function(users) {
expect(users.length).toEqual(1)
done()
})
})
it("can also handle array notation", function(done) {
var self = this
this.User.findAll({where: ['id = ?', this.users[1].id]}).success(function(users) {
expect(users.length).toEqual(1)
expect(users[0].id).toEqual(self.users[1].id)
done()
})
})
it("sorts the results via id in ascending order", function(done) {
this.User.findAll().success(function(users) {
expect(users.length).toEqual(2);
expect(users[0].id).toBeLessThan(users[1].id)
done()
})
})
it("sorts the results via id in descending order", function(done) {
this.User.findAll({ order: "id DESC" }).success(function(users) {
expect(users[0].id).toBeGreaterThan(users[1].id)
done()
})
})
it("sorts the results via a date column", function(done) {
var self = this
self.User.create({username: 'user3', data: 'bar', theDate: moment().add('hours', 2).toDate()}).success(function(){
self.User.findAll({ order: 'theDate DESC' }).success(function(users) {
expect(users[0].id).toBeGreaterThan(users[2].id)
done()
})
})
})
it("handles offset and limit", function(done) {
var self = this
this.User.bulkCreate([{username: 'bobby'}, {username: 'tables'}]).success(function() {
self.User.findAll({ limit: 2, offset: 2 }).success(function(users) {
expect(users.length).toEqual(2)
expect(users[0].id).toEqual(3)
done()
})
})
})
})
}) //- describe: findAll
describe('findAndCountAll', function() {
beforeEach(function(done) {
var self = this
this.User.bulkCreate([
{username: 'user', data: 'foobar'},
{username: 'user2', data: 'bar'},
{username: 'bobby', data: 'foo'}
]).success(function() {
self.User.all().success(function(users){
self.users = users
done()
})
})
})
it("handles where clause [only]", function(done) {
this.User.findAndCountAll({where: "id != " + this.users[0].id}).success(function(info) {
expect(info.count).toEqual(2)
expect(Array.isArray(info.rows)).toBeTruthy()
expect(info.rows.length).toEqual(2)
done()
})
})
it("handles where clause with ordering [only]", function(done) {
this.User.findAndCountAll({where: "id != " + this.users[0].id, order: 'id ASC'}).success(function(info) {
expect(info.count).toEqual(2)
expect(Array.isArray(info.rows)).toBeTruthy()
expect(info.rows.length).toEqual(2)
done()
})
})
it("handles offset", function(done) {
this.User.findAndCountAll({offset: 1}).success(function(info) {
expect(info.count).toEqual(3)
expect(Array.isArray(info.rows)).toBeTruthy()
expect(info.rows.length).toEqual(2)
done()
})
})
it("handles limit", function(done) {
this.User.findAndCountAll({limit: 1}).success(function(info) {
expect(info.count).toEqual(3)
expect(Array.isArray(info.rows)).toBeTruthy()
expect(info.rows.length).toEqual(1)
done()
})
})
it("handles offset and limit", function(done) {
this.User.findAndCountAll({offset: 1, limit: 1}).success(function(info) {
expect(info.count).toEqual(3)
expect(Array.isArray(info.rows)).toBeTruthy()
expect(info.rows.length).toEqual(1)
done()
})
})
})
describe('all', function() {
beforeEach(function(done) {
this.User.bulkCreate([
{username: 'user', data: 'foobar'},
{username: 'user2', data: 'bar'}
]).complete(done)
})
it("should return all users", function(done) {
this.User.all().on('success', function(users) {
expect(users.length).toEqual(2)
done()
})
})
})
describe('equals', function() {
it("correctly determines equality of objects", function(done) {
this.User.create({username: 'hallo', data: 'welt'}).success(function(u) {
expect(u.equals(u)).toBeTruthy()
done()
})
})
// sqlite can't handle multiple primary keys
if(dialect !== "sqlite") {
it("correctly determines equality with multiple primary keys", function(done) {
var userKeys = this.sequelize.define('userkeys', {
foo: {type: Sequelize.STRING, primaryKey: true},
bar: {type: Sequelize.STRING, primaryKey: true},
name: Sequelize.STRING,
bio: Sequelize.TEXT
})
this.sequelize.sync({ force: true }).success(function() {
userKeys.create({foo: '1', bar: '2', name: 'hallo', bio: 'welt'}).success(function(u) {
expect(u.equals(u)).toBeTruthy()
done()
})
})
})
}
})
describe('equalsOneOf', function() {
// sqlite can't handle multiple primary keys
if (dialect !== "sqlite") {
beforeEach(function(done) {
this.userKey = this.sequelize.define('userKeys', {
foo: {type: Sequelize.STRING, primaryKey: true},
bar: {type: Sequelize.STRING, primaryKey: true},
name: Sequelize.STRING,
bio: Sequelize.TEXT
})
this.sequelize.sync({ force: true }).success(done)
})
it('determines equality if one is matching', function(done) {
this.userKey.create({foo: '1', bar: '2', name: 'hallo', bio: 'welt'}).success(function(u) {
expect(u.equalsOneOf([u, {a: 1}])).toBeTruthy()
done()
})
})
it("doesn't determine equality if none is matching", function(done) {
this.userKey.create({foo: '1', bar: '2', name: 'hallo', bio: 'welt'}).success(function(u) {
expect(u.equalsOneOf([{b: 2}, {a: 1}])).toBeFalsy()
done()
})
})
}
})
describe('count', function() {
it('counts all created objects', function(done) {
var self = this
this.User.create({username: 'user1'}).success(function() {
self.User.create({username: 'user2'}).success(function() {
self.User.count().success(function(count) {
expect(count).toEqual(2)
done()
})
})
})
})
it('allows sql logging', function(done) {
this.User.count().on('sql', function(sql) {
expect(sql).toBeDefined()
expect(sql.toUpperCase().indexOf("SELECT")).toBeGreaterThan(-1)
done()
})
})
it('filters object', function(done) {
var self = this
this.User.create({username: 'user1'}).success(function() {
self.User.create({username: 'foo'}).success(function() {
self.User.count({where: "username LIKE '%us%'"}).success(function(count) {
expect(count).toEqual(1)
done()
})
})
})
})
})
describe('min', function() {
before(function(done) {
this.UserWithAge = this.sequelize.define('UserWithAge', {
......
......@@ -2,6 +2,8 @@ if (typeof require === 'function') {
const buster = require("buster")
, Helpers = require('./buster-helpers')
, dialect = Helpers.getTestDialect()
, Sequelize = require("../index")
, config = require(__dirname + "/config/config")
, _ = require('lodash')
}
......@@ -39,6 +41,13 @@ describe(Helpers.getTestDialectTeaser("DAO"), function() {
}
})
self.User2 = sequelize.define('User2', {
username: DataTypes.STRING,
updatedAt: DataTypes.DATE
}, {
timestamps: false
})
self.HistoryLog = sequelize.define('HistoryLog', {
someText: { type: DataTypes.STRING },
aNumber: { type: DataTypes.INTEGER },
......@@ -63,6 +72,74 @@ describe(Helpers.getTestDialectTeaser("DAO"), function() {
})
})
describe('Escaping', function() {
it('is done properly for special characters', function(done) {
// Ideally we should test more: "\0\n\r\b\t\\\'\"\x1a"
// But this causes sqlite to fail and exits the entire test suite immediately
var bio = dialect + "'\"\n" // Need to add the dialect here so in case of failure I know what DB it failed for
, self = this
this.User.create({ username: bio }).success(function(u1) {
self.User.find(u1.id).success(function(u2) {
expect(u2.username).toEqual(bio)
done()
})
})
})
})
describe('isNewRecord', function() {
it('returns true for non-saved objects', function(done) {
var user = this.User.build({ username: 'user' })
expect(user.id).toBeNull()
expect(user.isNewRecord).toBeTruthy()
done()
})
it("returns false for saved objects", function(done) {
this.User.build({ username: 'user' }).save().success(function(user) {
expect(user.isNewRecord).toBeFalsy()
done()
})
})
it("returns false for created objects", function(done) {
this.User.create({ username: 'user' }).success(function(user) {
expect(user.isNewRecord).toBeFalsy()
done()
})
})
it("returns false for objects found by find method", function(done) {
var self = this
this.User.create({ username: 'user' }).success(function() {
self.User.create({ username: 'user' }).success(function(user) {
self.User.find(user.id).success(function(user) {
expect(user.isNewRecord).toBeFalsy()
done()
})
})
})
})
it("returns false for objects found by findAll method", function(done) {
var chainer = new Sequelize.Utils.QueryChainer()
, self = this
for (var i = 0; i < 10; i++) {
chainer.add(self.User.create({ username: 'user' }))
}
chainer.run().success(function() {
self.User.findAll().success(function(users) {
users.forEach(function(u) {
expect(u.isNewRecord).toBeFalsy()
})
done()
})
})
})
})
describe('increment', function () {
before(function (done) {
this.User.create({ id: 1, aNumber: 0, bNumber: 0 }).done(done)
......@@ -74,7 +151,6 @@ describe(Helpers.getTestDialectTeaser("DAO"), function() {
// Select something
this.User.find(1).done(function (err, user1) {
user1.increment(['aNumber'], 2).done(function (err, user2) {
self.User.find(1).done(function (err, user3) {
expect(user3.aNumber).toBe(2);
done();
......@@ -89,7 +165,6 @@ describe(Helpers.getTestDialectTeaser("DAO"), function() {
// Select something
this.User.find(1).done(function (err, user1) {
user1.increment('aNumber', 2).done(function (err, user2) {
self.User.find(1).done(function (err, user3) {
expect(user3.aNumber).toBe(2);
done();
......@@ -108,7 +183,6 @@ describe(Helpers.getTestDialectTeaser("DAO"), function() {
aNumber: user2.aNumber + 1
}).done(function (err, user3) {
user1.increment(['aNumber'], 2).done(function (err, user4) {
self.User.find(1).done(function (err, user5) {
expect(user5.aNumber).toBe(3);
done();
......@@ -142,7 +216,6 @@ describe(Helpers.getTestDialectTeaser("DAO"), function() {
// Select something
this.User.find(1).done(function (err, user1) {
user1.increment({ 'aNumber': 1, 'bNumber': 2}).done(function (err, user2) {
self.User.find(1).done(function (err, user3) {
expect(user3.aNumber).toBe(1);
expect(user3.bNumber).toBe(2);
......@@ -164,7 +237,6 @@ describe(Helpers.getTestDialectTeaser("DAO"), function() {
// Select something
this.User.find(1).done(function (err, user1) {
user1.decrement(['aNumber'], 2).done(function (err, user2) {
self.User.find(1).done(function (err, user3) {
expect(user3.aNumber).toBe(-2);
done();
......@@ -179,7 +251,6 @@ describe(Helpers.getTestDialectTeaser("DAO"), function() {
// Select something
this.User.find(1).done(function (err, user1) {
user1.decrement('aNumber', 2).done(function (err, user2) {
self.User.find(1).done(function (err, user3) {
expect(user3.aNumber).toBe(-2);
done();
......@@ -198,7 +269,6 @@ describe(Helpers.getTestDialectTeaser("DAO"), function() {
aNumber: user2.aNumber + 1
}).done(function (err, user3) {
user1.decrement(['aNumber'], 2).done(function (err, user4) {
self.User.find(1).done(function (err, user5) {
expect(user5.aNumber).toBe(-1);
done();
......@@ -232,7 +302,6 @@ describe(Helpers.getTestDialectTeaser("DAO"), function() {
// Select something
this.User.find(1).done(function (err, user1) {
user1.decrement({ 'aNumber': 1, 'bNumber': 2}).done(function (err, user2) {
self.User.find(1).done(function (err, user3) {
expect(user3.aNumber).toBe(-1);
expect(user3.bNumber).toBe(-2);
......@@ -391,6 +460,86 @@ describe(Helpers.getTestDialectTeaser("DAO"), function() {
})
describe('save', function() {
it('only updates fields in passed array', function(done) {
var self = this
, userId = null
, date = new Date(1990, 01, 01)
this.User.create({
username: 'foo',
touchedAt: new Date()
}).success(function(user) {
user.username = 'fizz'
user.touchedAt = date
user.save(['username']).success(function(){
// re-select user
self.User.find(user.id).success(function(user2) {
// name should have changed
expect(user2.username).toEqual('fizz')
// bio should be unchanged
expect(user2.birthDate).not.toEqual(date)
done()
})
})
})
})
it("stores an entry in the database", function(done) {
var username = 'user'
, self = this
, user = this.User.build({
username: username,
touchedAt: new Date(1984, 8, 23)
})
self.User.all().success(function(users) {
expect(users.length).toEqual(0)
user.save().success(function(){
self.User.all().success(function(users) {
expect(users.length).toEqual(1)
expect(users[0].username).toEqual(username)
expect(users[0].touchedAt instanceof Date).toBe(true)
expect(users[0].touchedAt).toEqual(new Date(1984, 8, 23))
done()
})
})
})
})
it("updates the timestamps", function(done) {
this.timeout = 1000 * 5;
var now = Date.now()
, user = null
, updatedAt = null
, self = this
// timeout is needed, in order to check the update of the timestamp
var build = function() {
user = self.User.build({ username: 'user' })
updatedAt = user.updatedAt
expect(updatedAt.getTime()).toBeGreaterThan(now)
setTimeout(function() {
user.save().success(function() {
expect(updatedAt.getTime()).toBeLessThan(user.updatedAt.getTime())
done()
})
}, 1000)
}
setTimeout(build, 1000)
})
describe('without timestamps option', function() {
it("doesn't update the updatedAt column", function(done) {
this.User2.create({ username: 'john doe' }).success(function(johnDoe) {
// sqlite and mysql return undefined, whereas postgres returns null
expect([undefined, null].indexOf(johnDoe.updatedAt)).not.toBe(-1);
done()
})
})
})
it('should fail a validation upon creating', function(done){
this.User.create({aNumber: 0, validateTest: 'hello'}).error(function(err){
expect(err).toBeDefined()
......@@ -780,7 +929,90 @@ describe(Helpers.getTestDialectTeaser("DAO"), function() {
})
})
describe('values', function() {
it('returns all values', function(done) {
var User = this.sequelize.define('UserHelper', {
username: Helpers.Sequelize.STRING
}, { timestamps: false, logging: false })
User.sync({ force: true }).success(function() {
var user = User.build({ username: 'foo' })
expect(user.values).toEqual({ username: "foo", id: null })
done()
})
})
})
describe('updateAttributes', function() {
it("updates attributes in the database", function(done) {
this.User.create({ username: 'user' }).success(function(user) {
expect(user.username).toEqual('user')
user.updateAttributes({ username: 'person' }).success(function(user) {
expect(user.username).toEqual('person')
done()
})
})
})
it("ignores unknown attributes", function(done) {
this.User.create({ username: 'user' }).success(function(user) {
user.updateAttributes({ username: 'person', foo: 'bar'}).success(function(user) {
expect(user.username).toEqual('person')
expect(user.foo).not.toBeDefined()
done()
})
})
})
it("doesn't update primary keys or timestamps", function(done) {
var User = this.sequelize.define('User' + config.rand(), {
name: Helpers.Sequelize.STRING,
bio: Helpers.Sequelize.TEXT,
identifier: {type: Helpers.Sequelize.STRING, primaryKey: true}
})
User.sync({ force: true }).success(function(){
User.create({
name: 'snafu',
identifier: 'identifier'
}).success(function(user) {
var oldCreatedAt = user.createdAt
, oldIdentifier = user.identifier
user.updateAttributes({
name: 'foobar',
createdAt: new Date(2000, 1, 1),
identifier: 'another identifier'
}).success(function(user) {
expect(user.createdAt).toEqual(oldCreatedAt)
expect(user.identifier).toEqual(oldIdentifier)
done()
})
})
})
})
it("uses primary keys in where clause", function(done) {
var User = this.sequelize.define('User' + config.rand(), {
name: Helpers.Sequelize.STRING,
bio: Helpers.Sequelize.TEXT,
identifier: {type: Helpers.Sequelize.STRING, primaryKey: true}
})
User.sync({ force:true }).success(function(){
User.create({
name: 'snafu',
identifier: 'identifier'
}).success(function(user) {
var emitter = user.updateAttributes({name: 'foobar'})
emitter.success(function() {
expect(emitter.query.sql).toMatch(/WHERE [`"]identifier[`"]..identifier./)
done()
})
})
})
})
it('stores and restores null values', function(done) {
var Download = this.sequelize.define('download', {
startedAt: Helpers.Sequelize.DATE,
......
/* jshint camelcase: false */
if(typeof require === 'function') {
const buster = require("buster")
, config = require('../config/config')
, Helpers = require('../buster-helpers')
, dialect = Helpers.getTestDialect()
}
buster.spec.expose()
buster.testRunner.timeout = 1000
if (dialect.match(/^mysql/)) {
describe('[MYSQL] Associations', function() {
before(function(done) {
var self = this
Helpers.initTests({
dialect: dialect,
beforeComplete: function(sequelize, DataTypes) {
self.sequelize = sequelize
},
onComplete: function() {
self.sequelize.sync({ force: true }).success(done)
}
})
})
describe('many-to-many', function() {
describe('where tables have the same prefix', function() {
it("should create a table wp_table1wp_table2s", function(done) {
var Table2 = this.sequelize.define('wp_table2', {foo: Helpers.Sequelize.STRING})
, Table1 = this.sequelize.define('wp_table1', {foo: Helpers.Sequelize.STRING})
, self = this
Table1.hasMany(Table2)
Table2.hasMany(Table1)
this.sequelize.sync({ force: true }).success(function() {
expect(self.sequelize.daoFactoryManager.getDAO('wp_table1swp_table2s')).toBeDefined()
done()
})
})
})
describe('when join table name is specified', function() {
before(function(done){
var Table2 = this.sequelize.define('ms_table1', {foo: Helpers.Sequelize.STRING})
, Table1 = this.sequelize.define('ms_table2', {foo: Helpers.Sequelize.STRING})
Table1.hasMany(Table2, {joinTableName: 'table1_to_table2'})
Table2.hasMany(Table1, {joinTableName: 'table1_to_table2'})
this.sequelize.sync({ force: true }).success(done)
})
it("should not use a combined name", function(done) {
expect(this.sequelize.daoFactoryManager.getDAO('ms_table1sms_table2s')).not.toBeDefined()
done()
})
it("should use the specified name", function(done) {
expect(this.sequelize.daoFactoryManager.getDAO('table1_to_table2')).toBeDefined()
done()
})
})
})
describe('HasMany', function() {
before(function(done) {
//prevent periods from occurring in the table name since they are used to delimit (table.column)
this.User = this.sequelize.define('User' + Math.ceil(Math.random()*10000000), { name: Helpers.Sequelize.STRING })
this.Task = this.sequelize.define('Task' + Math.ceil(Math.random()*10000000), { name: Helpers.Sequelize.STRING })
this.users = null
this.tasks = null
this.User.hasMany(this.Task, {as:'Tasks'})
this.Task.hasMany(this.User, {as:'Users'})
var self = this
, users = []
, tasks = []
for (var i = 0; i < 5; ++i) {
users[users.length] = {name: 'User' + Math.random()}
}
for (var x = 0; x < 5; ++x) {
tasks[tasks.length] = {name: 'Task' + Math.random()}
}
this.sequelize.sync({ force: true }).success(function() {
self.User.bulkCreate(users).success(function() {
self.Task.bulkCreate(tasks).success(done)
})
})
})
describe('addDAO / getDAO', function() {
before(function(done) {
var self = this
self.user = null
self.task = null
self.User.all().success(function(_users) {
self.Task.all().success(function(_tasks) {
self.user = _users[0]
self.task = _tasks[0]
done()
})
})
})
it('should correctly add an association to the dao', function(done) {
var self = this
self.user.getTasks().on('success', function(_tasks) {
expect(_tasks.length).toEqual(0)
self.user.addTask(self.task).on('success', function() {
self.user.getTasks().on('success', function(_tasks) {
expect(_tasks.length).toEqual(1)
done()
})
})
})
})
})
describe('removeDAO', function() {
before(function(done) {
var self = this
self.user = null
self.tasks = null
self.User.all().success(function(_users) {
self.Task.all().success(function(_tasks) {
self.user = _users[0]
self.tasks = _tasks
done()
})
})
})
it("should correctly remove associated objects", function(done) {
var self = this
self.user.getTasks().on('success', function(__tasks) {
expect(__tasks.length).toEqual(0)
self.user.setTasks(self.tasks).on('success', function() {
self.user.getTasks().on('success', function(_tasks) {
expect(_tasks.length).toEqual(self.tasks.length)
self.user.removeTask(self.tasks[0]).on('success', function() {
self.user.getTasks().on('success', function(_tasks) {
expect(_tasks.length).toEqual(self.tasks.length - 1)
done()
})
})
})
})
})
})
})
})
})
}
if(typeof require === 'function') {
const buster = require("buster")
, Helpers = require('../buster-helpers')
, dialect = Helpers.getTestDialect()
}
buster.spec.expose()
buster.testRunner.timeout = 1000
if (dialect.match(/^mysql/)) {
describe('[MYSQL] Connector Manager', function() {
before(function(done) {
var self = this
Helpers.initTests({
dialect: dialect,
beforeComplete: function(sequelize, DataTypes) {
self.sequelize = sequelize
},
onComplete: function() {
self.sequelize.sync({ force: true }).success(done)
}
})
})
it('works correctly after being idle', function(done) {
this.timeout = 1000 * 10
var User = this.sequelize.define('User', { username: Helpers.Sequelize.STRING })
, spy = this.spy()
User.sync({force: true}).on('success', function() {
User.create({username: 'user1'}).on('success', function() {
User.count().on('success', function(count) {
expect(count).toEqual(1)
spy()
setTimeout(function() {
User.count().on('success', function(count) {
expect(count).toEqual(1)
spy()
if (spy.calledTwice) {
done()
}
})
}, 1000)
})
})
})
})
})
}
/* jshint camelcase: false */
if(typeof require === 'function') {
const buster = require("buster")
, config = require('../config/config')
, Helpers = require('../buster-helpers')
, dialect = Helpers.getTestDialect()
}
buster.spec.expose()
buster.testRunner.timeout = 1000
if (dialect.match(/^mysql/)) {
describe('[MYSQL] DAOFactory', function() {
before(function(done) {
var self = this
Helpers.initTests({
dialect: dialect,
beforeComplete: function(sequelize, DataTypes) {
self.sequelize = sequelize
self.User = self.sequelize.define('User', { age: DataTypes.INTEGER, name: DataTypes.STRING, bio: DataTypes.TEXT })
},
onComplete: function() {
self.sequelize.sync({ force: true }).success(done)
}
})
})
describe('constructor', function() {
it("handles extended attributes (unique)", function(done) {
var User = this.sequelize.define('User' + config.rand(), {
username: { type: Helpers.Sequelize.STRING, unique: true }
}, { timestamps: false })
expect(User.attributes).toEqual({username:"VARCHAR(255) UNIQUE",id:"INTEGER NOT NULL auto_increment PRIMARY KEY"})
done()
})
it("handles extended attributes (default)", function(done) {
var User = this.sequelize.define('User' + config.rand(), {
username: {type: Helpers.Sequelize.STRING, defaultValue: 'foo'}
}, { timestamps: false })
expect(User.attributes).toEqual({username:"VARCHAR(255) DEFAULT 'foo'",id:"INTEGER NOT NULL auto_increment PRIMARY KEY"})
done()
})
it("handles extended attributes (null)", function(done) {
var User = this.sequelize.define('User' + config.rand(), {
username: {type: Helpers.Sequelize.STRING, allowNull: false}
}, { timestamps: false })
expect(User.attributes).toEqual({username:"VARCHAR(255) NOT NULL",id:"INTEGER NOT NULL auto_increment PRIMARY KEY"})
done()
})
it("handles extended attributes (comment)", function(done) {
var User = this.sequelize.define('User' + config.rand(), {
username: {type: Helpers.Sequelize.STRING, comment: 'This be\'s a comment'}
}, { timestamps: false })
expect(User.attributes).toEqual({username:"VARCHAR(255) COMMENT 'This be\\'s a comment'",id:"INTEGER NOT NULL auto_increment PRIMARY KEY"})
done()
})
it("handles extended attributes (primaryKey)", function(done) {
var User = this.sequelize.define('User' + config.rand(), {
username: {type: Helpers.Sequelize.STRING, primaryKey: true}
}, { timestamps: false })
expect(User.attributes).toEqual({username:"VARCHAR(255) PRIMARY KEY"})
done()
})
it("adds timestamps", function(done) {
var User1 = this.sequelize.define('User' + config.rand(), {})
var User2 = this.sequelize.define('User' + config.rand(), {}, { timestamps: true })
expect(User1.attributes).toEqual({id:"INTEGER NOT NULL auto_increment PRIMARY KEY", updatedAt:"DATETIME NOT NULL", createdAt:"DATETIME NOT NULL"})
expect(User2.attributes).toEqual({id:"INTEGER NOT NULL auto_increment PRIMARY KEY", updatedAt:"DATETIME NOT NULL", createdAt:"DATETIME NOT NULL"})
done()
})
it("adds deletedAt if paranoid", function(done) {
var User = this.sequelize.define('User' + config.rand(), {}, { paranoid: true })
expect(User.attributes).toEqual({id:"INTEGER NOT NULL auto_increment PRIMARY KEY", deletedAt:"DATETIME", updatedAt:"DATETIME NOT NULL", createdAt:"DATETIME NOT NULL"})
done()
})
it("underscores timestamps if underscored", function(done) {
var User = this.sequelize.define('User' + config.rand(), {}, { paranoid: true, underscored: true })
expect(User.attributes).toEqual({id:"INTEGER NOT NULL auto_increment PRIMARY KEY", deleted_at:"DATETIME", updated_at:"DATETIME NOT NULL", created_at:"DATETIME NOT NULL"})
done()
})
})
describe('primaryKeys', function() {
it("determines the correct primaryKeys", function(done) {
var User = this.sequelize.define('User' + config.rand(), {
foo: {type: Helpers.Sequelize.STRING, primaryKey: true},
bar: Helpers.Sequelize.STRING
})
expect(User.primaryKeys).toEqual({"foo":"VARCHAR(255) PRIMARY KEY"})
done()
})
})
})
}
var config = require("../config/config")
, Sequelize = require("../../index")
, sequelize = new Sequelize(config.mysql.database, config.mysql.username, config.mysql.password, { pool: config.mysql.pool, logging: false, host: config.mysql.host, port: config.mysql.port })
, Helpers = new (require("../config/helpers"))(sequelize)
, QueryGenerator = require("../../lib/dialects/mysql/query-generator")
, util = require("util")
/* jshint camelcase: false */
if(typeof require === 'function') {
const buster = require("buster")
, config = require('../config/config')
, Helpers = require('../buster-helpers')
, dialect = Helpers.getTestDialect()
, QueryGenerator = require("../../lib/dialects/mysql/query-generator")
, util = require("util")
describe('QueryGenerator', function() {
beforeEach(function() { Helpers.sync() })
afterEach(function() { Helpers.drop() })
}
var suites = {
buster.spec.expose()
buster.testRunner.timeout = 1000
attributesToSQL: [
{
arguments: [{id: 'INTEGER'}],
expectation: {id: 'INTEGER'}
},
{
arguments: [{id: 'INTEGER', foo: 'VARCHAR(255)'}],
expectation: {id: 'INTEGER', foo: 'VARCHAR(255)'}
},
{
arguments: [{id: {type: 'INTEGER'}}],
expectation: {id: 'INTEGER'}
},
{
arguments: [{id: {type: 'INTEGER', allowNull: false}}],
expectation: {id: 'INTEGER NOT NULL'}
},
{
arguments: [{id: {type: 'INTEGER', allowNull: true}}],
expectation: {id: 'INTEGER'}
},
{
arguments: [{id: {type: 'INTEGER', primaryKey: true, autoIncrement: true}}],
expectation: {id: 'INTEGER auto_increment PRIMARY KEY'}
},
{
arguments: [{id: {type: 'INTEGER', defaultValue: 0}}],
expectation: {id: 'INTEGER DEFAULT 0'}
},
{
arguments: [{id: {type: 'INTEGER', unique: true}}],
expectation: {id: 'INTEGER UNIQUE'}
},
{
arguments: [{id: {type: 'INTEGER', comment: "I'm a comment!" }}],
expectation: {id: "INTEGER COMMENT 'I\\'m a comment!'" }
},
{
arguments: [{id: {type: 'INTEGER', references: 'Bar'}}],
expectation: {id: 'INTEGER REFERENCES `Bar` (`id`)'}
},
{
arguments: [{id: {type: 'INTEGER', references: 'Bar', referencesKey: 'pk'}}],
expectation: {id: 'INTEGER REFERENCES `Bar` (`pk`)'}
},
{
arguments: [{id: {type: 'INTEGER', references: 'Bar', onDelete: 'CASCADE'}}],
expectation: {id: 'INTEGER REFERENCES `Bar` (`id`) ON DELETE CASCADE'}
},
{
arguments: [{id: {type: 'INTEGER', references: 'Bar', onUpdate: 'RESTRICT'}}],
expectation: {id: 'INTEGER REFERENCES `Bar` (`id`) ON UPDATE RESTRICT'}
},
{
arguments: [{id: {type: 'INTEGER', allowNull: false, autoIncrement: true, defaultValue: 1, references: 'Bar', onDelete: 'CASCADE', onUpdate: 'RESTRICT'}}],
expectation: {id: 'INTEGER NOT NULL auto_increment DEFAULT 1 REFERENCES `Bar` (`id`) ON DELETE CASCADE ON UPDATE RESTRICT'}
},
],
if (dialect.match(/^mysql/)) {
describe('[MYSQL] QueryGenerator', function() {
before(function(done) {
var self = this
createTableQuery: [
{
arguments: ['myTable', {title: 'VARCHAR(255)', name: 'VARCHAR(255)'}],
expectation: "CREATE TABLE IF NOT EXISTS `myTable` (`title` VARCHAR(255), `name` VARCHAR(255)) ENGINE=InnoDB;"
},
{
arguments: ['myTable', {title: "INTEGER COMMENT 'I\\'m a comment!'"}],
expectation: "CREATE TABLE IF NOT EXISTS `myTable` (`title` INTEGER COMMENT 'I\\'m a comment!') ENGINE=InnoDB;"
},
{
arguments: ['myTable', {title: "INTEGER"}, {comment: "I'm a comment!"}],
expectation: "CREATE TABLE IF NOT EXISTS `myTable` (`title` INTEGER) COMMENT 'I\\'m a comment!' ENGINE=InnoDB;"
},
{
arguments: ['myTable', {title: 'VARCHAR(255)', name: 'VARCHAR(255)'}, {engine: 'MyISAM'}],
expectation: "CREATE TABLE IF NOT EXISTS `myTable` (`title` VARCHAR(255), `name` VARCHAR(255)) ENGINE=MyISAM;"
},
{
arguments: ['myTable', {title: 'VARCHAR(255)', name: 'VARCHAR(255)'}, {charset: 'utf8', collate: 'utf8_unicode_ci'}],
expectation: "CREATE TABLE IF NOT EXISTS `myTable` (`title` VARCHAR(255), `name` VARCHAR(255)) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_unicode_ci;"
},
{
arguments: ['myTable', {title: 'VARCHAR(255)', name: 'VARCHAR(255)'}, {charset: 'latin1'}],
expectation: "CREATE TABLE IF NOT EXISTS `myTable` (`title` VARCHAR(255), `name` VARCHAR(255)) ENGINE=InnoDB DEFAULT CHARSET=latin1;"
},
{
arguments: ['myTable', {title: 'ENUM("A", "B", "C")', name: 'VARCHAR(255)'}, {charset: 'latin1'}],
expectation: "CREATE TABLE IF NOT EXISTS `myTable` (`title` ENUM(\"A\", \"B\", \"C\"), `name` VARCHAR(255)) ENGINE=InnoDB DEFAULT CHARSET=latin1;"
},
{
arguments: ['myTable', {title: 'VARCHAR(255)', name: 'VARCHAR(255)', id: 'INTEGER PRIMARY KEY'}],
expectation: "CREATE TABLE IF NOT EXISTS `myTable` (`title` VARCHAR(255), `name` VARCHAR(255), `id` INTEGER , PRIMARY KEY (`id`)) ENGINE=InnoDB;"
},
{
arguments: ['myTable', {title: 'VARCHAR(255)', name: 'VARCHAR(255)', otherId: 'INTEGER REFERENCES `otherTable` (`id`) ON DELETE CASCADE ON UPDATE NO ACTION'}],
expectation: "CREATE TABLE IF NOT EXISTS `myTable` (`title` VARCHAR(255), `name` VARCHAR(255), `otherId` INTEGER, FOREIGN KEY (`otherId`) REFERENCES `otherTable` (`id`) ON DELETE CASCADE ON UPDATE NO ACTION) ENGINE=InnoDB;"
}
],
Helpers.initTests({
dialect: dialect,
beforeComplete: function(sequelize, DataTypes) {
self.sequelize = sequelize
},
onComplete: function() {
self.sequelize.sync({ force: true }).success(done)
}
})
})
var suites = {
attributesToSQL: [
{
arguments: [{id: 'INTEGER'}],
expectation: {id: 'INTEGER'}
},
{
arguments: [{id: 'INTEGER', foo: 'VARCHAR(255)'}],
expectation: {id: 'INTEGER', foo: 'VARCHAR(255)'}
},
{
arguments: [{id: {type: 'INTEGER'}}],
expectation: {id: 'INTEGER'}
},
{
arguments: [{id: {type: 'INTEGER', allowNull: false}}],
expectation: {id: 'INTEGER NOT NULL'}
},
{
arguments: [{id: {type: 'INTEGER', allowNull: true}}],
expectation: {id: 'INTEGER'}
},
{
arguments: [{id: {type: 'INTEGER', primaryKey: true, autoIncrement: true}}],
expectation: {id: 'INTEGER auto_increment PRIMARY KEY'}
},
{
arguments: [{id: {type: 'INTEGER', defaultValue: 0}}],
expectation: {id: 'INTEGER DEFAULT 0'}
},
{
arguments: [{id: {type: 'INTEGER', unique: true}}],
expectation: {id: 'INTEGER UNIQUE'}
},
{
arguments: [{id: {type: 'INTEGER', comment: "I'm a comment!" }}],
expectation: {id: "INTEGER COMMENT 'I\\'m a comment!'" }
},
{
arguments: [{id: {type: 'INTEGER', references: 'Bar'}}],
expectation: {id: 'INTEGER REFERENCES `Bar` (`id`)'}
},
{
arguments: [{id: {type: 'INTEGER', references: 'Bar', referencesKey: 'pk'}}],
expectation: {id: 'INTEGER REFERENCES `Bar` (`pk`)'}
},
{
arguments: [{id: {type: 'INTEGER', references: 'Bar', onDelete: 'CASCADE'}}],
expectation: {id: 'INTEGER REFERENCES `Bar` (`id`) ON DELETE CASCADE'}
},
{
arguments: [{id: {type: 'INTEGER', references: 'Bar', onUpdate: 'RESTRICT'}}],
expectation: {id: 'INTEGER REFERENCES `Bar` (`id`) ON UPDATE RESTRICT'}
},
{
arguments: [{id: {type: 'INTEGER', allowNull: false, autoIncrement: true, defaultValue: 1, references: 'Bar', onDelete: 'CASCADE', onUpdate: 'RESTRICT'}}],
expectation: {id: 'INTEGER NOT NULL auto_increment DEFAULT 1 REFERENCES `Bar` (`id`) ON DELETE CASCADE ON UPDATE RESTRICT'}
},
],
dropTableQuery: [
{
arguments: ['myTable'],
expectation: "DROP TABLE IF EXISTS `myTable`;"
}
],
createTableQuery: [
{
arguments: ['myTable', {title: 'VARCHAR(255)', name: 'VARCHAR(255)'}],
expectation: "CREATE TABLE IF NOT EXISTS `myTable` (`title` VARCHAR(255), `name` VARCHAR(255)) ENGINE=InnoDB;"
},
{
arguments: ['myTable', {title: "INTEGER COMMENT 'I\\'m a comment!'"}],
expectation: "CREATE TABLE IF NOT EXISTS `myTable` (`title` INTEGER COMMENT 'I\\'m a comment!') ENGINE=InnoDB;"
},
{
arguments: ['myTable', {title: "INTEGER"}, {comment: "I'm a comment!"}],
expectation: "CREATE TABLE IF NOT EXISTS `myTable` (`title` INTEGER) COMMENT 'I\\'m a comment!' ENGINE=InnoDB;"
},
{
arguments: ['myTable', {title: 'VARCHAR(255)', name: 'VARCHAR(255)'}, {engine: 'MyISAM'}],
expectation: "CREATE TABLE IF NOT EXISTS `myTable` (`title` VARCHAR(255), `name` VARCHAR(255)) ENGINE=MyISAM;"
},
{
arguments: ['myTable', {title: 'VARCHAR(255)', name: 'VARCHAR(255)'}, {charset: 'utf8', collate: 'utf8_unicode_ci'}],
expectation: "CREATE TABLE IF NOT EXISTS `myTable` (`title` VARCHAR(255), `name` VARCHAR(255)) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_unicode_ci;"
},
{
arguments: ['myTable', {title: 'VARCHAR(255)', name: 'VARCHAR(255)'}, {charset: 'latin1'}],
expectation: "CREATE TABLE IF NOT EXISTS `myTable` (`title` VARCHAR(255), `name` VARCHAR(255)) ENGINE=InnoDB DEFAULT CHARSET=latin1;"
},
{
arguments: ['myTable', {title: 'ENUM("A", "B", "C")', name: 'VARCHAR(255)'}, {charset: 'latin1'}],
expectation: "CREATE TABLE IF NOT EXISTS `myTable` (`title` ENUM(\"A\", \"B\", \"C\"), `name` VARCHAR(255)) ENGINE=InnoDB DEFAULT CHARSET=latin1;"
},
{
arguments: ['myTable', {title: 'VARCHAR(255)', name: 'VARCHAR(255)', id: 'INTEGER PRIMARY KEY'}],
expectation: "CREATE TABLE IF NOT EXISTS `myTable` (`title` VARCHAR(255), `name` VARCHAR(255), `id` INTEGER , PRIMARY KEY (`id`)) ENGINE=InnoDB;"
},
{
arguments: ['myTable', {title: 'VARCHAR(255)', name: 'VARCHAR(255)', otherId: 'INTEGER REFERENCES `otherTable` (`id`) ON DELETE CASCADE ON UPDATE NO ACTION'}],
expectation: "CREATE TABLE IF NOT EXISTS `myTable` (`title` VARCHAR(255), `name` VARCHAR(255), `otherId` INTEGER, FOREIGN KEY (`otherId`) REFERENCES `otherTable` (`id`) ON DELETE CASCADE ON UPDATE NO ACTION) ENGINE=InnoDB;"
}
],
selectQuery: [
{
arguments: ['myTable'],
expectation: "SELECT * FROM `myTable`;",
context: QueryGenerator
}, {
arguments: ['myTable', {attributes: ['id', 'name']}],
expectation: "SELECT `id`, `name` FROM `myTable`;",
context: QueryGenerator
}, {
arguments: ['myTable', {where: {id: 2}}],
expectation: "SELECT * FROM `myTable` WHERE `myTable`.`id`=2;",
context: QueryGenerator
}, {
arguments: ['myTable', {where: {name: 'foo'}}],
expectation: "SELECT * FROM `myTable` WHERE `myTable`.`name`='foo';",
context: QueryGenerator
}, {
arguments: ['myTable', {where: {name: "foo';DROP TABLE myTable;"}}],
expectation: "SELECT * FROM `myTable` WHERE `myTable`.`name`='foo\\';DROP TABLE myTable;';",
context: QueryGenerator
}, {
arguments: ['myTable', {where: 2}],
expectation: "SELECT * FROM `myTable` WHERE `myTable`.`id`=2;",
context: QueryGenerator
}, {
arguments: ['foo', { attributes: [['count(*)', 'count']] }],
expectation: 'SELECT count(*) as `count` FROM `foo`;',
context: QueryGenerator
}, {
arguments: ['myTable', {where: "foo='bar'"}],
expectation: "SELECT * FROM `myTable` WHERE foo='bar';",
context: QueryGenerator
}, {
arguments: ['myTable', {order: "id DESC"}],
expectation: "SELECT * FROM `myTable` ORDER BY id DESC;",
context: QueryGenerator
}, {
arguments: ['myTable', {group: "name"}],
expectation: "SELECT * FROM `myTable` GROUP BY `name`;",
context: QueryGenerator
}, {
arguments: ['myTable', {group: ["name"]}],
expectation: "SELECT * FROM `myTable` GROUP BY `name`;",
context: QueryGenerator
}, {
arguments: ['myTable', {group: ["name", "title"]}],
expectation: "SELECT * FROM `myTable` GROUP BY `name`, `title`;",
context: QueryGenerator
}, {
arguments: ['myTable', {group: "name", order: "id DESC"}],
expectation: "SELECT * FROM `myTable` GROUP BY `name` ORDER BY id DESC;",
context: QueryGenerator
}, {
arguments: ['myTable', {limit: 10}],
expectation: "SELECT * FROM `myTable` LIMIT 10;",
context: QueryGenerator
}, {
arguments: ['myTable', {limit: 10, offset: 2}],
expectation: "SELECT * FROM `myTable` LIMIT 2, 10;",
context: QueryGenerator
}, {
title: 'uses default limit if only offset is specified',
arguments: ['myTable', {offset: 2}],
expectation: "SELECT * FROM `myTable` LIMIT 2, 18440000000000000000;",
context: QueryGenerator
}, {
title: 'multiple where arguments',
arguments: ['myTable', {where: {boat: 'canoe', weather: 'cold'}}],
expectation: "SELECT * FROM `myTable` WHERE `myTable`.`boat`='canoe' AND `myTable`.`weather`='cold';",
context: QueryGenerator
}, {
title: 'no where arguments (object)',
arguments: ['myTable', {where: {}}],
expectation: "SELECT * FROM `myTable` WHERE 1=1;",
context: QueryGenerator
}, {
title: 'no where arguments (string)',
arguments: ['myTable', {where: ''}],
expectation: "SELECT * FROM `myTable` WHERE 1=1;",
context: QueryGenerator
}, {
title: 'no where arguments (null)',
arguments: ['myTable', {where: null}],
expectation: "SELECT * FROM `myTable` WHERE 1=1;",
context: QueryGenerator
}
],
dropTableQuery: [
{
arguments: ['myTable'],
expectation: "DROP TABLE IF EXISTS `myTable`;"
}
],
insertQuery: [
{
arguments: ['myTable', {name: 'foo'}],
expectation: "INSERT INTO `myTable` (`name`) VALUES ('foo');"
}, {
arguments: ['myTable', {name: "foo';DROP TABLE myTable;"}],
expectation: "INSERT INTO `myTable` (`name`) VALUES ('foo\\';DROP TABLE myTable;');"
}, {
arguments: ['myTable', {name: 'foo', birthday: new Date(Date.UTC(2011, 2, 27, 10, 1, 55))}],
expectation: "INSERT INTO `myTable` (`name`,`birthday`) VALUES ('foo','2011-03-27 10:01:55');"
}, {
arguments: ['myTable', {name: 'foo', foo: 1}],
expectation: "INSERT INTO `myTable` (`name`,`foo`) VALUES ('foo',1);"
}, {
arguments: ['myTable', {name: 'foo', foo: 1, nullValue: null}],
expectation: "INSERT INTO `myTable` (`name`,`foo`,`nullValue`) VALUES ('foo',1,NULL);"
}, {
arguments: ['myTable', {name: 'foo', foo: 1, nullValue: null}],
expectation: "INSERT INTO `myTable` (`name`,`foo`,`nullValue`) VALUES ('foo',1,NULL);",
context: {options: {omitNull: false}}
}, {
arguments: ['myTable', {name: 'foo', foo: 1, nullValue: null}],
expectation: "INSERT INTO `myTable` (`name`,`foo`) VALUES ('foo',1);",
context: {options: {omitNull: true}}
}, {
arguments: ['myTable', {name: 'foo', foo: 1, nullValue: undefined}],
expectation: "INSERT INTO `myTable` (`name`,`foo`) VALUES ('foo',1);",
context: {options: {omitNull: true}}
}, {
arguments: ['myTable', {foo: false}],
expectation: "INSERT INTO `myTable` (`foo`) VALUES (false);"
}, {
arguments: ['myTable', {foo: true}],
expectation: "INSERT INTO `myTable` (`foo`) VALUES (true);"
}
],
selectQuery: [
{
arguments: ['myTable'],
expectation: "SELECT * FROM `myTable`;",
context: QueryGenerator
}, {
arguments: ['myTable', {attributes: ['id', 'name']}],
expectation: "SELECT `id`, `name` FROM `myTable`;",
context: QueryGenerator
}, {
arguments: ['myTable', {where: {id: 2}}],
expectation: "SELECT * FROM `myTable` WHERE `myTable`.`id`=2;",
context: QueryGenerator
}, {
arguments: ['myTable', {where: {name: 'foo'}}],
expectation: "SELECT * FROM `myTable` WHERE `myTable`.`name`='foo';",
context: QueryGenerator
}, {
arguments: ['myTable', {where: {name: "foo';DROP TABLE myTable;"}}],
expectation: "SELECT * FROM `myTable` WHERE `myTable`.`name`='foo\\';DROP TABLE myTable;';",
context: QueryGenerator
}, {
arguments: ['myTable', {where: 2}],
expectation: "SELECT * FROM `myTable` WHERE `myTable`.`id`=2;",
context: QueryGenerator
}, {
arguments: ['foo', { attributes: [['count(*)', 'count']] }],
expectation: 'SELECT count(*) as `count` FROM `foo`;',
context: QueryGenerator
}, {
arguments: ['myTable', {where: "foo='bar'"}],
expectation: "SELECT * FROM `myTable` WHERE foo='bar';",
context: QueryGenerator
}, {
arguments: ['myTable', {order: "id DESC"}],
expectation: "SELECT * FROM `myTable` ORDER BY id DESC;",
context: QueryGenerator
}, {
arguments: ['myTable', {group: "name"}],
expectation: "SELECT * FROM `myTable` GROUP BY `name`;",
context: QueryGenerator
}, {
arguments: ['myTable', {group: ["name"]}],
expectation: "SELECT * FROM `myTable` GROUP BY `name`;",
context: QueryGenerator
}, {
arguments: ['myTable', {group: ["name", "title"]}],
expectation: "SELECT * FROM `myTable` GROUP BY `name`, `title`;",
context: QueryGenerator
}, {
arguments: ['myTable', {group: "name", order: "id DESC"}],
expectation: "SELECT * FROM `myTable` GROUP BY `name` ORDER BY id DESC;",
context: QueryGenerator
}, {
arguments: ['myTable', {limit: 10}],
expectation: "SELECT * FROM `myTable` LIMIT 10;",
context: QueryGenerator
}, {
arguments: ['myTable', {limit: 10, offset: 2}],
expectation: "SELECT * FROM `myTable` LIMIT 2, 10;",
context: QueryGenerator
}, {
title: 'uses default limit if only offset is specified',
arguments: ['myTable', {offset: 2}],
expectation: "SELECT * FROM `myTable` LIMIT 2, 18440000000000000000;",
context: QueryGenerator
}, {
title: 'multiple where arguments',
arguments: ['myTable', {where: {boat: 'canoe', weather: 'cold'}}],
expectation: "SELECT * FROM `myTable` WHERE `myTable`.`boat`='canoe' AND `myTable`.`weather`='cold';",
context: QueryGenerator
}, {
title: 'no where arguments (object)',
arguments: ['myTable', {where: {}}],
expectation: "SELECT * FROM `myTable` WHERE 1=1;",
context: QueryGenerator
}, {
title: 'no where arguments (string)',
arguments: ['myTable', {where: ''}],
expectation: "SELECT * FROM `myTable` WHERE 1=1;",
context: QueryGenerator
}, {
title: 'no where arguments (null)',
arguments: ['myTable', {where: null}],
expectation: "SELECT * FROM `myTable` WHERE 1=1;",
context: QueryGenerator
}
],
bulkInsertQuery: [
{
arguments: ['myTable', [{name: 'foo'}, {name: 'bar'}]],
expectation: "INSERT INTO `myTable` (`name`) VALUES ('foo'),('bar');"
}, {
arguments: ['myTable', [{name: "foo';DROP TABLE myTable;"}, {name: 'bar'}]],
expectation: "INSERT INTO `myTable` (`name`) VALUES ('foo\\';DROP TABLE myTable;'),('bar');"
}, {
arguments: ['myTable', [{name: 'foo', birthday: new Date(Date.UTC(2011, 2, 27, 10, 1, 55))}, {name: 'bar', birthday: new Date(Date.UTC(2012, 2, 27, 10, 1, 55))}]],
expectation: "INSERT INTO `myTable` (`name`,`birthday`) VALUES ('foo','2011-03-27 10:01:55'),('bar','2012-03-27 10:01:55');"
}, {
arguments: ['myTable', [{name: 'foo', foo: 1}, {name: 'bar', foo: 2}]],
expectation: "INSERT INTO `myTable` (`name`,`foo`) VALUES ('foo',1),('bar',2);"
}, {
arguments: ['myTable', [{name: 'foo', foo: 1, nullValue: null}, {name: 'bar', nullValue: null}]],
expectation: "INSERT INTO `myTable` (`name`,`foo`,`nullValue`) VALUES ('foo',1,NULL),('bar',NULL);"
}, {
arguments: ['myTable', [{name: 'foo', foo: 1, nullValue: null}, {name: 'bar', foo: 2, nullValue: null}]],
expectation: "INSERT INTO `myTable` (`name`,`foo`,`nullValue`) VALUES ('foo',1,NULL),('bar',2,NULL);",
context: {options: {omitNull: false}}
}, {
arguments: ['myTable', [{name: 'foo', foo: 1, nullValue: null}, {name: 'bar', foo: 2, nullValue: null}]],
expectation: "INSERT INTO `myTable` (`name`,`foo`,`nullValue`) VALUES ('foo',1,NULL),('bar',2,NULL);",
context: {options: {omitNull: true}} // Note: We don't honour this because it makes little sense when some rows may have nulls and others not
}, {
arguments: ['myTable', [{name: 'foo', foo: 1, nullValue: undefined}, {name: 'bar', foo: 2, undefinedValue: undefined}]],
expectation: "INSERT INTO `myTable` (`name`,`foo`,`nullValue`) VALUES ('foo',1,NULL),('bar',2,NULL);",
context: {options: {omitNull: true}} // Note: As above
}, {
arguments: ['myTable', [{name: "foo", value: true}, {name: 'bar', value: false}]],
expectation: "INSERT INTO `myTable` (`name`,`value`) VALUES ('foo',true),('bar',false);"
}
],
insertQuery: [
{
arguments: ['myTable', {name: 'foo'}],
expectation: "INSERT INTO `myTable` (`name`) VALUES ('foo');"
}, {
arguments: ['myTable', {name: "foo';DROP TABLE myTable;"}],
expectation: "INSERT INTO `myTable` (`name`) VALUES ('foo\\';DROP TABLE myTable;');"
}, {
arguments: ['myTable', {name: 'foo', birthday: new Date(Date.UTC(2011, 2, 27, 10, 1, 55))}],
expectation: "INSERT INTO `myTable` (`name`,`birthday`) VALUES ('foo','2011-03-27 10:01:55');"
}, {
arguments: ['myTable', {name: 'foo', foo: 1}],
expectation: "INSERT INTO `myTable` (`name`,`foo`) VALUES ('foo',1);"
}, {
arguments: ['myTable', {name: 'foo', foo: 1, nullValue: null}],
expectation: "INSERT INTO `myTable` (`name`,`foo`,`nullValue`) VALUES ('foo',1,NULL);"
}, {
arguments: ['myTable', {name: 'foo', foo: 1, nullValue: null}],
expectation: "INSERT INTO `myTable` (`name`,`foo`,`nullValue`) VALUES ('foo',1,NULL);",
context: {options: {omitNull: false}}
}, {
arguments: ['myTable', {name: 'foo', foo: 1, nullValue: null}],
expectation: "INSERT INTO `myTable` (`name`,`foo`) VALUES ('foo',1);",
context: {options: {omitNull: true}}
}, {
arguments: ['myTable', {name: 'foo', foo: 1, nullValue: undefined}],
expectation: "INSERT INTO `myTable` (`name`,`foo`) VALUES ('foo',1);",
context: {options: {omitNull: true}}
}, {
arguments: ['myTable', {foo: false}],
expectation: "INSERT INTO `myTable` (`foo`) VALUES (false);"
}, {
arguments: ['myTable', {foo: true}],
expectation: "INSERT INTO `myTable` (`foo`) VALUES (true);"
}
],
updateQuery: [
{
arguments: ['myTable', {name: 'foo', birthday: new Date(Date.UTC(2011, 2, 27, 10, 1, 55))}, {id: 2}],
expectation: "UPDATE `myTable` SET `name`='foo',`birthday`='2011-03-27 10:01:55' WHERE `id`=2"
}, {
arguments: ['myTable', {name: 'foo', birthday: new Date(Date.UTC(2011, 2, 27, 10, 1, 55))}, 2],
expectation: "UPDATE `myTable` SET `name`='foo',`birthday`='2011-03-27 10:01:55' WHERE `id`=2"
}, {
arguments: ['myTable', {bar: 2}, {name: 'foo'}],
expectation: "UPDATE `myTable` SET `bar`=2 WHERE `name`='foo'"
}, {
arguments: ['myTable', {name: "foo';DROP TABLE myTable;"}, {name: 'foo'}],
expectation: "UPDATE `myTable` SET `name`='foo\\';DROP TABLE myTable;' WHERE `name`='foo'"
}, {
arguments: ['myTable', {bar: 2, nullValue: null}, {name: 'foo'}],
expectation: "UPDATE `myTable` SET `bar`=2,`nullValue`=NULL WHERE `name`='foo'"
}, {
arguments: ['myTable', {bar: 2, nullValue: null}, {name: 'foo'}],
expectation: "UPDATE `myTable` SET `bar`=2,`nullValue`=NULL WHERE `name`='foo'",
context: {options: {omitNull: false}}
}, {
arguments: ['myTable', {bar: 2, nullValue: null}, {name: 'foo'}],
expectation: "UPDATE `myTable` SET `bar`=2 WHERE `name`='foo'",
context: {options: {omitNull: true}}
}, {
arguments: ['myTable', {bar: false}, {name: 'foo'}],
expectation: "UPDATE `myTable` SET `bar`=false WHERE `name`='foo'"
}, {
arguments: ['myTable', {bar: true}, {name: 'foo'}],
expectation: "UPDATE `myTable` SET `bar`=true WHERE `name`='foo'"
}
],
bulkInsertQuery: [
{
arguments: ['myTable', [{name: 'foo'}, {name: 'bar'}]],
expectation: "INSERT INTO `myTable` (`name`) VALUES ('foo'),('bar');"
}, {
arguments: ['myTable', [{name: "foo';DROP TABLE myTable;"}, {name: 'bar'}]],
expectation: "INSERT INTO `myTable` (`name`) VALUES ('foo\\';DROP TABLE myTable;'),('bar');"
}, {
arguments: ['myTable', [{name: 'foo', birthday: new Date(Date.UTC(2011, 2, 27, 10, 1, 55))}, {name: 'bar', birthday: new Date(Date.UTC(2012, 2, 27, 10, 1, 55))}]],
expectation: "INSERT INTO `myTable` (`name`,`birthday`) VALUES ('foo','2011-03-27 10:01:55'),('bar','2012-03-27 10:01:55');"
}, {
arguments: ['myTable', [{name: 'foo', foo: 1}, {name: 'bar', foo: 2}]],
expectation: "INSERT INTO `myTable` (`name`,`foo`) VALUES ('foo',1),('bar',2);"
}, {
arguments: ['myTable', [{name: 'foo', foo: 1, nullValue: null}, {name: 'bar', nullValue: null}]],
expectation: "INSERT INTO `myTable` (`name`,`foo`,`nullValue`) VALUES ('foo',1,NULL),('bar',NULL);"
}, {
arguments: ['myTable', [{name: 'foo', foo: 1, nullValue: null}, {name: 'bar', foo: 2, nullValue: null}]],
expectation: "INSERT INTO `myTable` (`name`,`foo`,`nullValue`) VALUES ('foo',1,NULL),('bar',2,NULL);",
context: {options: {omitNull: false}}
}, {
arguments: ['myTable', [{name: 'foo', foo: 1, nullValue: null}, {name: 'bar', foo: 2, nullValue: null}]],
expectation: "INSERT INTO `myTable` (`name`,`foo`,`nullValue`) VALUES ('foo',1,NULL),('bar',2,NULL);",
context: {options: {omitNull: true}} // Note: We don't honour this because it makes little sense when some rows may have nulls and others not
}, {
arguments: ['myTable', [{name: 'foo', foo: 1, nullValue: undefined}, {name: 'bar', foo: 2, undefinedValue: undefined}]],
expectation: "INSERT INTO `myTable` (`name`,`foo`,`nullValue`) VALUES ('foo',1,NULL),('bar',2,NULL);",
context: {options: {omitNull: true}} // Note: As above
}, {
arguments: ['myTable', [{name: "foo", value: true}, {name: 'bar', value: false}]],
expectation: "INSERT INTO `myTable` (`name`,`value`) VALUES ('foo',true),('bar',false);"
}
],
deleteQuery: [
{
arguments: ['myTable', {name: 'foo'}],
expectation: "DELETE FROM `myTable` WHERE `name`='foo' LIMIT 1"
}, {
arguments: ['myTable', 1],
expectation: "DELETE FROM `myTable` WHERE `id`=1 LIMIT 1"
},{
arguments: ['myTable', undefined, {truncate: true}],
expectation: "TRUNCATE `myTable`"
},{
arguments: ['myTable', 1, {limit: 10, truncate: true}],
expectation: "TRUNCATE `myTable`"
}, {
arguments: ['myTable', 1, {limit: 10}],
expectation: "DELETE FROM `myTable` WHERE `id`=1 LIMIT 10"
}, {
arguments: ['myTable', {name: "foo';DROP TABLE myTable;"}, {limit: 10}],
expectation: "DELETE FROM `myTable` WHERE `name`='foo\\';DROP TABLE myTable;' LIMIT 10"
}, {
arguments: ['myTable', {name: 'foo'}, {limit: null}],
expectation: "DELETE FROM `myTable` WHERE `name`='foo'"
}
],
updateQuery: [
{
arguments: ['myTable', {name: 'foo', birthday: new Date(Date.UTC(2011, 2, 27, 10, 1, 55))}, {id: 2}],
expectation: "UPDATE `myTable` SET `name`='foo',`birthday`='2011-03-27 10:01:55' WHERE `id`=2"
}, {
arguments: ['myTable', {name: 'foo', birthday: new Date(Date.UTC(2011, 2, 27, 10, 1, 55))}, 2],
expectation: "UPDATE `myTable` SET `name`='foo',`birthday`='2011-03-27 10:01:55' WHERE `id`=2"
}, {
arguments: ['myTable', {bar: 2}, {name: 'foo'}],
expectation: "UPDATE `myTable` SET `bar`=2 WHERE `name`='foo'"
}, {
arguments: ['myTable', {name: "foo';DROP TABLE myTable;"}, {name: 'foo'}],
expectation: "UPDATE `myTable` SET `name`='foo\\';DROP TABLE myTable;' WHERE `name`='foo'"
}, {
arguments: ['myTable', {bar: 2, nullValue: null}, {name: 'foo'}],
expectation: "UPDATE `myTable` SET `bar`=2,`nullValue`=NULL WHERE `name`='foo'"
}, {
arguments: ['myTable', {bar: 2, nullValue: null}, {name: 'foo'}],
expectation: "UPDATE `myTable` SET `bar`=2,`nullValue`=NULL WHERE `name`='foo'",
context: {options: {omitNull: false}}
}, {
arguments: ['myTable', {bar: 2, nullValue: null}, {name: 'foo'}],
expectation: "UPDATE `myTable` SET `bar`=2 WHERE `name`='foo'",
context: {options: {omitNull: true}}
}, {
arguments: ['myTable', {bar: false}, {name: 'foo'}],
expectation: "UPDATE `myTable` SET `bar`=false WHERE `name`='foo'"
}, {
arguments: ['myTable', {bar: true}, {name: 'foo'}],
expectation: "UPDATE `myTable` SET `bar`=true WHERE `name`='foo'"
}
],
addIndexQuery: [
{
arguments: ['User', ['username', 'isAdmin']],
expectation: 'CREATE INDEX user_username_is_admin ON User (username, isAdmin)'
}, {
arguments: [
'User', [
{ attribute: 'username', length: 10, order: 'ASC'},
'isAdmin'
]
],
expectation: "CREATE INDEX user_username_is_admin ON User (username(10) ASC, isAdmin)"
}, {
arguments: [
'User', ['username', 'isAdmin'], { parser: 'foo', indicesType: 'FULLTEXT', indexName: 'bar'}
],
expectation: "CREATE FULLTEXT INDEX bar ON User (username, isAdmin) WITH PARSER foo"
}
],
deleteQuery: [
{
arguments: ['myTable', {name: 'foo'}],
expectation: "DELETE FROM `myTable` WHERE `name`='foo' LIMIT 1"
}, {
arguments: ['myTable', 1],
expectation: "DELETE FROM `myTable` WHERE `id`=1 LIMIT 1"
},{
arguments: ['myTable', undefined, {truncate: true}],
expectation: "TRUNCATE `myTable`"
},{
arguments: ['myTable', 1, {limit: 10, truncate: true}],
expectation: "TRUNCATE `myTable`"
}, {
arguments: ['myTable', 1, {limit: 10}],
expectation: "DELETE FROM `myTable` WHERE `id`=1 LIMIT 10"
}, {
arguments: ['myTable', {name: "foo';DROP TABLE myTable;"}, {limit: 10}],
expectation: "DELETE FROM `myTable` WHERE `name`='foo\\';DROP TABLE myTable;' LIMIT 10"
}, {
arguments: ['myTable', {name: 'foo'}, {limit: null}],
expectation: "DELETE FROM `myTable` WHERE `name`='foo'"
}
],
showIndexQuery: [
{
arguments: ['User'],
expectation: 'SHOW INDEX FROM User'
}, {
arguments: ['User', { database: 'sequelize' }],
expectation: "SHOW INDEX FROM User FROM sequelize"
}
],
addIndexQuery: [
{
arguments: ['User', ['username', 'isAdmin']],
expectation: 'CREATE INDEX user_username_is_admin ON User (username, isAdmin)'
}, {
arguments: [
'User', [
{ attribute: 'username', length: 10, order: 'ASC'},
'isAdmin'
]
],
expectation: "CREATE INDEX user_username_is_admin ON User (username(10) ASC, isAdmin)"
}, {
arguments: [
'User', ['username', 'isAdmin'], { parser: 'foo', indicesType: 'FULLTEXT', indexName: 'bar'}
],
expectation: "CREATE FULLTEXT INDEX bar ON User (username, isAdmin) WITH PARSER foo"
}
],
removeIndexQuery: [
{
arguments: ['User', 'user_foo_bar'],
expectation: "DROP INDEX user_foo_bar ON User"
}, {
arguments: ['User', ['foo', 'bar']],
expectation: "DROP INDEX user_foo_bar ON User"
}
],
showIndexQuery: [
{
arguments: ['User'],
expectation: 'SHOW INDEX FROM User'
}, {
arguments: ['User', { database: 'sequelize' }],
expectation: "SHOW INDEX FROM User FROM sequelize"
}
],
hashToWhereConditions: [
{
arguments: [{ id: [1,2,3] }],
expectation: "`id` IN (1,2,3)"
},
{
arguments: [{ id: [] }],
expectation: "`id` IN (NULL)"
},
{
arguments: [{ maple: false, bacon: true }],
expectation: "`maple`=false AND `bacon`=true"
},
{
arguments: [{ beaver: [false, true] }],
expectation: "`beaver` IN (false,true)"
},
{
arguments: [{birthday: new Date(Date.UTC(2011, 6, 1, 10, 1, 55))}],
expectation: "`birthday`='2011-07-01 10:01:55'"
},
{
arguments: [{ birthday: new Date(Date.UTC(2011, 6, 1, 10, 1, 55)),
otherday: new Date(Date.UTC(2013, 6, 2, 10, 1, 22)) }],
expectation: "`birthday`='2011-07-01 10:01:55' AND `otherday`='2013-07-02 10:01:22'"
},
{
arguments: [{ birthday: [new Date(Date.UTC(2011, 6, 1, 10, 1, 55)), new Date(Date.UTC(2013, 6, 2, 10, 1, 22))] }],
expectation: "`birthday` IN ('2011-07-01 10:01:55','2013-07-02 10:01:22')"
}
]
}
removeIndexQuery: [
{
arguments: ['User', 'user_foo_bar'],
expectation: "DROP INDEX user_foo_bar ON User"
}, {
arguments: ['User', ['foo', 'bar']],
expectation: "DROP INDEX user_foo_bar ON User"
}
],
Sequelize.Utils._.each(suites, function(tests, suiteTitle) {
describe(suiteTitle, function() {
tests.forEach(function(test) {
var title = test.title || 'MySQL correctly returns ' + test.expectation + ' for ' + util.inspect(test.arguments)
it(title, function() {
// Options would normally be set by the query interface that instantiates the query-generator, but here we specify it explicitly
var context = test.context || {options: {}};
QueryGenerator.options = context.options
var conditions = QueryGenerator[suiteTitle].apply(QueryGenerator, test.arguments)
hashToWhereConditions: [
{
arguments: [{ id: [1,2,3] }],
expectation: "`id` IN (1,2,3)"
},
{
arguments: [{ id: [] }],
expectation: "`id` IN (NULL)"
},
{
arguments: [{ maple: false, bacon: true }],
expectation: "`maple`=false AND `bacon`=true"
},
{
arguments: [{ beaver: [false, true] }],
expectation: "`beaver` IN (false,true)"
},
{
arguments: [{birthday: new Date(Date.UTC(2011, 6, 1, 10, 1, 55))}],
expectation: "`birthday`='2011-07-01 10:01:55'"
},
{
arguments: [{ birthday: new Date(Date.UTC(2011, 6, 1, 10, 1, 55)),
otherday: new Date(Date.UTC(2013, 6, 2, 10, 1, 22)) }],
expectation: "`birthday`='2011-07-01 10:01:55' AND `otherday`='2013-07-02 10:01:22'"
},
{
arguments: [{ birthday: [new Date(Date.UTC(2011, 6, 1, 10, 1, 55)), new Date(Date.UTC(2013, 6, 2, 10, 1, 22))] }],
expectation: "`birthday` IN ('2011-07-01 10:01:55','2013-07-02 10:01:22')"
}
]
}
expect(conditions).toEqual(test.expectation)
Helpers.Sequelize.Utils._.each(suites, function(tests, suiteTitle) {
describe(suiteTitle, function() {
tests.forEach(function(test) {
var title = test.title || 'MySQL correctly returns ' + test.expectation + ' for ' + util.inspect(test.arguments)
it(title, function(done) {
// Options would normally be set by the query interface that instantiates the query-generator, but here we specify it explicitly
var context = test.context || {options: {}};
QueryGenerator.options = context.options
var conditions = QueryGenerator[suiteTitle].apply(QueryGenerator, test.arguments)
expect(conditions).toEqual(test.expectation)
done()
})
})
})
})
})
})
}
if(typeof require === 'function') {
const buster = require("buster")
, Helpers = require('../buster-helpers')
, dialect = Helpers.getTestDialect()
}
buster.spec.expose()
buster.testRunner.timeout = 1000
if (dialect.match(/^postgres/)) {
describe('[POSTGRES] associations', function() {
before(function(done) {
var self = this
Helpers.initTests({
dialect: dialect,
beforeComplete: function(sequelize, DataTypes) {
self.sequelize = sequelize
},
onComplete: function() {
self.sequelize.sync({ force: true }).success(done)
}
})
})
describe('many-to-many', function() {
describe('where tables have the same prefix', function() {
it("should create a table wp_table1wp_table2s", function(done) {
var Table2 = this.sequelize.define('wp_table2', {foo: Helpers.Sequelize.STRING})
, Table1 = this.sequelize.define('wp_table1', {foo: Helpers.Sequelize.STRING})
Table1.hasMany(Table2)
Table2.hasMany(Table1)
expect(this.sequelize.daoFactoryManager.getDAO('wp_table1swp_table2s')).toBeDefined()
done()
})
})
describe('when join table name is specified', function() {
before(function(done){
var Table2 = this.sequelize.define('ms_table1', {foo: Helpers.Sequelize.STRING})
, Table1 = this.sequelize.define('ms_table2', {foo: Helpers.Sequelize.STRING})
Table1.hasMany(Table2, {joinTableName: 'table1_to_table2'})
Table2.hasMany(Table1, {joinTableName: 'table1_to_table2'})
done()
})
it("should not use a combined name", function(done) {
expect(this.sequelize.daoFactoryManager.getDAO('ms_table1sms_table2s')).not.toBeDefined()
done()
})
it("should use the specified name", function(done) {
expect(this.sequelize.daoFactoryManager.getDAO('table1_to_table2')).toBeDefined()
done()
})
})
})
describe('HasMany', function() {
before(function(done) {
//prevent periods from occurring in the table name since they are used to delimit (table.column)
this.User = this.sequelize.define('User' + Math.ceil(Math.random()*10000000), { name: Helpers.Sequelize.STRING })
this.Task = this.sequelize.define('Task' + Math.ceil(Math.random()*10000000), { name: Helpers.Sequelize.STRING })
this.users = null
this.tasks = null
this.User.hasMany(this.Task, {as:'Tasks'})
this.Task.hasMany(this.User, {as:'Users'})
var self = this
, users = []
, tasks = []
for (var i = 0; i < 5; ++i) {
users[users.length] = {name: 'User' + Math.random()}
}
for (var x = 0; x < 5; ++x) {
tasks[tasks.length] = {name: 'Task' + Math.random()}
}
this.sequelize.sync({ force: true }).success(function() {
self.User.bulkCreate(users).success(function() {
self.Task.bulkCreate(tasks).success(done)
})
})
})
describe('addDAO / getDAO', function() {
before(function(done) {
var self = this
self.user = null
self.task = null
self.User.all().success(function(_users) {
self.Task.all().success(function(_tasks) {
self.user = _users[0]
self.task = _tasks[0]
done()
})
})
})
it('should correctly add an association to the dao', function(done) {
var self = this
self.user.getTasks().on('success', function(_tasks) {
expect(_tasks.length).toEqual(0)
self.user.addTask(self.task).on('success', function() {
self.user.getTasks().on('success', function(_tasks) {
expect(_tasks.length).toEqual(1)
done()
})
})
})
})
})
describe('removeDAO', function() {
before(function(done) {
var self = this
self.user = null
self.tasks = null
self.User.all().success(function(_users) {
self.Task.all().success(function(_tasks) {
self.user = _users[0]
self.tasks = _tasks
done()
})
})
})
it("should correctly remove associated objects", function(done) {
var self = this
self.user.getTasks().on('success', function(__tasks) {
expect(__tasks.length).toEqual(0)
self.user.setTasks(self.tasks).on('success', function() {
self.user.getTasks().on('success', function(_tasks) {
expect(_tasks.length).toEqual(self.tasks.length)
self.user.removeTask(self.tasks[0]).on('success', function() {
self.user.getTasks().on('success', function(_tasks) {
expect(_tasks.length).toEqual(self.tasks.length - 1)
done()
})
})
})
})
})
})
})
})
})
}
var config = require("../config/config")
, Sequelize = require("../../index")
, sequelize = new Sequelize(config.postgres.database, config.postgres.username, config.postgres.password, {
logging: false,
dialect: 'postgres',
port: config.postgres.port
})
, Helpers = new (require("../config/helpers"))(sequelize)
, QueryGenerator = require("../../lib/dialects/postgres/query-generator")
, util = require("util")
if(typeof require === 'function') {
const buster = require("buster")
, Helpers = require('../buster-helpers')
, dialect = Helpers.getTestDialect()
, QueryGenerator = require("../../lib/dialects/postgres/query-generator")
, util = require("util")
, moment = require('moment')
}
buster.spec.expose()
buster.testRunner.timeout = 1000
describe('QueryGenerator', function() {
beforeEach(function() { Helpers.sync() })
afterEach(function() { Helpers.drop() })
if (dialect.match(/^postgres/)) {
describe('[POSTGRES] QueryGenerator', function() {
before(function(done) {
var self = this
var suites = {
Helpers.initTests({
dialect: dialect,
beforeComplete: function(sequelize, DataTypes) {
self.sequelize = sequelize
attributesToSQL: [
{
arguments: [{id: 'INTEGER'}],
expectation: {id: 'INTEGER'}
},
{
arguments: [{id: 'INTEGER', foo: 'VARCHAR(255)'}],
expectation: {id: 'INTEGER', foo: 'VARCHAR(255)'}
},
{
arguments: [{id: {type: 'INTEGER'}}],
expectation: {id: 'INTEGER'}
},
{
arguments: [{id: {type: 'INTEGER', allowNull: false}}],
expectation: {id: 'INTEGER NOT NULL'}
},
{
arguments: [{id: {type: 'INTEGER', allowNull: true}}],
expectation: {id: 'INTEGER'}
},
{
arguments: [{id: {type: 'INTEGER', primaryKey: true, autoIncrement: true}}],
expectation: {id: 'INTEGER SERIAL PRIMARY KEY'}
},
{
arguments: [{id: {type: 'INTEGER', defaultValue: 0}}],
expectation: {id: 'INTEGER DEFAULT 0'}
},
{
arguments: [{id: {type: 'INTEGER', unique: true}}],
expectation: {id: 'INTEGER UNIQUE'}
},
{
arguments: [{id: {type: 'INTEGER', comment: "I'm a comment!" }}],
expectation: {id: "INTEGER COMMENT ON COLUMN <%= table %>.\"id\" IS 'I''m a comment!'" }
},
{
arguments: [{id: {type: 'INTEGER', references: 'Bar'}}],
expectation: {id: 'INTEGER REFERENCES "Bar" ("id")'}
},
{
arguments: [{id: {type: 'INTEGER', references: 'Bar', referencesKey: 'pk'}}],
expectation: {id: 'INTEGER REFERENCES "Bar" ("pk")'}
},
{
arguments: [{id: {type: 'INTEGER', references: 'Bar', onDelete: 'CASCADE'}}],
expectation: {id: 'INTEGER REFERENCES "Bar" ("id") ON DELETE CASCADE'}
},
{
arguments: [{id: {type: 'INTEGER', references: 'Bar', onUpdate: 'RESTRICT'}}],
expectation: {id: 'INTEGER REFERENCES "Bar" ("id") ON UPDATE RESTRICT'}
},
{
arguments: [{id: {type: 'INTEGER', allowNull: false, defaultValue: 1, references: 'Bar', onDelete: 'CASCADE', onUpdate: 'RESTRICT'}}],
expectation: {id: 'INTEGER NOT NULL DEFAULT 1 REFERENCES "Bar" ("id") ON DELETE CASCADE ON UPDATE RESTRICT'}
},
self.User = sequelize.define('User', {
username: DataTypes.STRING,
email: {type: DataTypes.ARRAY(DataTypes.TEXT)},
document: {type: DataTypes.HSTORE, defaultValue: '"default"=>"value"'}
})
},
onComplete: function() {
self.User.sync({ force: true }).success(done)
}
})
})
// Variants when quoteIdentifiers is false
{
arguments: [{id: {type: 'INTEGER', references: 'Bar'}}],
expectation: {id: 'INTEGER REFERENCES Bar (id)'},
context: {options: {quoteIdentifiers: false}}
},
{
arguments: [{id: {type: 'INTEGER', references: 'Bar', referencesKey: 'pk'}}],
expectation: {id: 'INTEGER REFERENCES Bar (pk)'},
context: {options: {quoteIdentifiers: false}}
},
{
arguments: [{id: {type: 'INTEGER', references: 'Bar', onDelete: 'CASCADE'}}],
expectation: {id: 'INTEGER REFERENCES Bar (id) ON DELETE CASCADE'},
context: {options: {quoteIdentifiers: false}}
},
{
arguments: [{id: {type: 'INTEGER', references: 'Bar', onUpdate: 'RESTRICT'}}],
expectation: {id: 'INTEGER REFERENCES Bar (id) ON UPDATE RESTRICT'},
context: {options: {quoteIdentifiers: false}}
},
{
arguments: [{id: {type: 'INTEGER', allowNull: false, defaultValue: 1, references: 'Bar', onDelete: 'CASCADE', onUpdate: 'RESTRICT'}}],
expectation: {id: 'INTEGER NOT NULL DEFAULT 1 REFERENCES Bar (id) ON DELETE CASCADE ON UPDATE RESTRICT'},
context: {options: {quoteIdentifiers: false}}
},
var suites = {
attributesToSQL: [
{
arguments: [{id: 'INTEGER'}],
expectation: {id: 'INTEGER'}
},
{
arguments: [{id: 'INTEGER', foo: 'VARCHAR(255)'}],
expectation: {id: 'INTEGER', foo: 'VARCHAR(255)'}
},
{
arguments: [{id: {type: 'INTEGER'}}],
expectation: {id: 'INTEGER'}
},
{
arguments: [{id: {type: 'INTEGER', allowNull: false}}],
expectation: {id: 'INTEGER NOT NULL'}
},
{
arguments: [{id: {type: 'INTEGER', allowNull: true}}],
expectation: {id: 'INTEGER'}
},
{
arguments: [{id: {type: 'INTEGER', primaryKey: true, autoIncrement: true}}],
expectation: {id: 'INTEGER SERIAL PRIMARY KEY'}
},
{
arguments: [{id: {type: 'INTEGER', defaultValue: 0}}],
expectation: {id: 'INTEGER DEFAULT 0'}
},
{
arguments: [{id: {type: 'INTEGER', unique: true}}],
expectation: {id: 'INTEGER UNIQUE'}
},
{
arguments: [{id: {type: 'INTEGER', comment: "I'm a comment!" }}],
expectation: {id: "INTEGER COMMENT ON COLUMN <%= table %>.\"id\" IS 'I''m a comment!'" }
},
{
arguments: [{id: {type: 'INTEGER', references: 'Bar'}}],
expectation: {id: 'INTEGER REFERENCES "Bar" ("id")'}
},
{
arguments: [{id: {type: 'INTEGER', references: 'Bar', referencesKey: 'pk'}}],
expectation: {id: 'INTEGER REFERENCES "Bar" ("pk")'}
},
{
arguments: [{id: {type: 'INTEGER', references: 'Bar', onDelete: 'CASCADE'}}],
expectation: {id: 'INTEGER REFERENCES "Bar" ("id") ON DELETE CASCADE'}
},
{
arguments: [{id: {type: 'INTEGER', references: 'Bar', onUpdate: 'RESTRICT'}}],
expectation: {id: 'INTEGER REFERENCES "Bar" ("id") ON UPDATE RESTRICT'}
},
{
arguments: [{id: {type: 'INTEGER', allowNull: false, defaultValue: 1, references: 'Bar', onDelete: 'CASCADE', onUpdate: 'RESTRICT'}}],
expectation: {id: 'INTEGER NOT NULL DEFAULT 1 REFERENCES "Bar" ("id") ON DELETE CASCADE ON UPDATE RESTRICT'}
},
],
// Variants when quoteIdentifiers is false
{
arguments: [{id: {type: 'INTEGER', references: 'Bar'}}],
expectation: {id: 'INTEGER REFERENCES Bar (id)'},
context: {options: {quoteIdentifiers: false}}
},
{
arguments: [{id: {type: 'INTEGER', references: 'Bar', referencesKey: 'pk'}}],
expectation: {id: 'INTEGER REFERENCES Bar (pk)'},
context: {options: {quoteIdentifiers: false}}
},
{
arguments: [{id: {type: 'INTEGER', references: 'Bar', onDelete: 'CASCADE'}}],
expectation: {id: 'INTEGER REFERENCES Bar (id) ON DELETE CASCADE'},
context: {options: {quoteIdentifiers: false}}
},
{
arguments: [{id: {type: 'INTEGER', references: 'Bar', onUpdate: 'RESTRICT'}}],
expectation: {id: 'INTEGER REFERENCES Bar (id) ON UPDATE RESTRICT'},
context: {options: {quoteIdentifiers: false}}
},
{
arguments: [{id: {type: 'INTEGER', allowNull: false, defaultValue: 1, references: 'Bar', onDelete: 'CASCADE', onUpdate: 'RESTRICT'}}],
expectation: {id: 'INTEGER NOT NULL DEFAULT 1 REFERENCES Bar (id) ON DELETE CASCADE ON UPDATE RESTRICT'},
context: {options: {quoteIdentifiers: false}}
},
createTableQuery: [
{
arguments: ['myTable', {title: 'VARCHAR(255)', name: 'VARCHAR(255)'}],
expectation: "CREATE TABLE IF NOT EXISTS \"myTable\" (\"title\" VARCHAR(255), \"name\" VARCHAR(255));",
},
{
arguments: ['myTable', {title: "INTEGER COMMENT ON COLUMN <%= table %>.\"title\" IS 'I''m a comment!'"}],
expectation: "CREATE TABLE IF NOT EXISTS \"myTable\" (\"title\" INTEGER ); COMMENT ON COLUMN \"myTable\".\"title\" IS 'I''m a comment!';",
},
{
arguments: ['myTable', {title: "INTEGER"}, {comment: "I'm a comment!"}],
expectation: "CREATE TABLE IF NOT EXISTS \"myTable\" (\"title\" INTEGER); COMMENT ON TABLE \"myTable\" IS 'I''m a comment!';",
},
{
arguments: ['mySchema.myTable', {title: 'VARCHAR(255)', name: 'VARCHAR(255)'}],
expectation: "CREATE TABLE IF NOT EXISTS \"mySchema\".\"myTable\" (\"title\" VARCHAR(255), \"name\" VARCHAR(255));"
},
{
arguments: ['myTable', {title: 'ENUM("A", "B", "C")', name: 'VARCHAR(255)'}],
expectation: "DROP TYPE IF EXISTS \"enum_myTable_title\"; CREATE TYPE \"enum_myTable_title\" AS ENUM(\"A\", \"B\", \"C\"); CREATE TABLE IF NOT EXISTS \"myTable\" (\"title\" \"enum_myTable_title\", \"name\" VARCHAR(255));"
},
{
arguments: ['myTable', {title: 'VARCHAR(255)', name: 'VARCHAR(255)', id: 'INTEGER PRIMARY KEY'}],
expectation: "CREATE TABLE IF NOT EXISTS \"myTable\" (\"title\" VARCHAR(255), \"name\" VARCHAR(255), \"id\" INTEGER , PRIMARY KEY (\"id\"));"
},
{
arguments: ['myTable', {title: 'VARCHAR(255)', name: 'VARCHAR(255)', otherId: 'INTEGER REFERENCES "otherTable" ("id") ON DELETE CASCADE ON UPDATE NO ACTION'}],
expectation: "CREATE TABLE IF NOT EXISTS \"myTable\" (\"title\" VARCHAR(255), \"name\" VARCHAR(255), \"otherId\" INTEGER REFERENCES \"otherTable\" (\"id\") ON DELETE CASCADE ON UPDATE NO ACTION);"
},
],
// Variants when quoteIdentifiers is false
{
arguments: ['myTable', {title: 'VARCHAR(255)', name: 'VARCHAR(255)'}],
expectation: "CREATE TABLE IF NOT EXISTS myTable (title VARCHAR(255), name VARCHAR(255));",
context: {options: {quoteIdentifiers: false}}
},
{
arguments: ['mySchema.myTable', {title: 'VARCHAR(255)', name: 'VARCHAR(255)'}],
expectation: "CREATE TABLE IF NOT EXISTS mySchema.myTable (title VARCHAR(255), name VARCHAR(255));",
context: {options: {quoteIdentifiers: false}}
},
{
arguments: ['myTable', {title: 'ENUM("A", "B", "C")', name: 'VARCHAR(255)'}],
expectation: "DROP TYPE IF EXISTS enum_myTable_title; CREATE TYPE enum_myTable_title AS ENUM(\"A\", \"B\", \"C\"); CREATE TABLE IF NOT EXISTS myTable (title enum_myTable_title, name VARCHAR(255));",
context: {options: {quoteIdentifiers: false}}
},
{
arguments: ['myTable', {title: 'VARCHAR(255)', name: 'VARCHAR(255)', id: 'INTEGER PRIMARY KEY'}],
expectation: "CREATE TABLE IF NOT EXISTS myTable (title VARCHAR(255), name VARCHAR(255), id INTEGER , PRIMARY KEY (id));",
context: {options: {quoteIdentifiers: false}}
},
{
arguments: ['myTable', {title: 'VARCHAR(255)', name: 'VARCHAR(255)', otherId: 'INTEGER REFERENCES otherTable (id) ON DELETE CASCADE ON UPDATE NO ACTION'}],
expectation: "CREATE TABLE IF NOT EXISTS myTable (title VARCHAR(255), name VARCHAR(255), otherId INTEGER REFERENCES otherTable (id) ON DELETE CASCADE ON UPDATE NO ACTION);",
context: {options: {quoteIdentifiers: false}}
}
],
createTableQuery: [
{
arguments: ['myTable', {title: 'VARCHAR(255)', name: 'VARCHAR(255)'}],
expectation: "CREATE TABLE IF NOT EXISTS \"myTable\" (\"title\" VARCHAR(255), \"name\" VARCHAR(255));",
},
{
arguments: ['myTable', {title: "INTEGER COMMENT ON COLUMN <%= table %>.\"title\" IS 'I''m a comment!'"}],
expectation: "CREATE TABLE IF NOT EXISTS \"myTable\" (\"title\" INTEGER ); COMMENT ON COLUMN \"myTable\".\"title\" IS 'I''m a comment!';",
},
{
arguments: ['myTable', {title: "INTEGER"}, {comment: "I'm a comment!"}],
expectation: "CREATE TABLE IF NOT EXISTS \"myTable\" (\"title\" INTEGER); COMMENT ON TABLE \"myTable\" IS 'I''m a comment!';",
},
{
arguments: ['mySchema.myTable', {title: 'VARCHAR(255)', name: 'VARCHAR(255)'}],
expectation: "CREATE TABLE IF NOT EXISTS \"mySchema\".\"myTable\" (\"title\" VARCHAR(255), \"name\" VARCHAR(255));"
},
{
arguments: ['myTable', {title: 'ENUM("A", "B", "C")', name: 'VARCHAR(255)'}],
expectation: "DROP TYPE IF EXISTS \"enum_myTable_title\"; CREATE TYPE \"enum_myTable_title\" AS ENUM(\"A\", \"B\", \"C\"); CREATE TABLE IF NOT EXISTS \"myTable\" (\"title\" \"enum_myTable_title\", \"name\" VARCHAR(255));"
},
{
arguments: ['myTable', {title: 'VARCHAR(255)', name: 'VARCHAR(255)', id: 'INTEGER PRIMARY KEY'}],
expectation: "CREATE TABLE IF NOT EXISTS \"myTable\" (\"title\" VARCHAR(255), \"name\" VARCHAR(255), \"id\" INTEGER , PRIMARY KEY (\"id\"));"
},
{
arguments: ['myTable', {title: 'VARCHAR(255)', name: 'VARCHAR(255)', otherId: 'INTEGER REFERENCES "otherTable" ("id") ON DELETE CASCADE ON UPDATE NO ACTION'}],
expectation: "CREATE TABLE IF NOT EXISTS \"myTable\" (\"title\" VARCHAR(255), \"name\" VARCHAR(255), \"otherId\" INTEGER REFERENCES \"otherTable\" (\"id\") ON DELETE CASCADE ON UPDATE NO ACTION);"
},
dropTableQuery: [
{
arguments: ['myTable'],
expectation: "DROP TABLE IF EXISTS \"myTable\";"
},
{
arguments: ['mySchema.myTable'],
expectation: "DROP TABLE IF EXISTS \"mySchema\".\"myTable\";"
},
{
arguments: ['myTable', {cascade: true}],
expectation: "DROP TABLE IF EXISTS \"myTable\" CASCADE;"
},
{
arguments: ['mySchema.myTable', {cascade: true}],
expectation: "DROP TABLE IF EXISTS \"mySchema\".\"myTable\" CASCADE;"
},
// Variants when quoteIdentifiers is false
{
arguments: ['myTable', {title: 'VARCHAR(255)', name: 'VARCHAR(255)'}],
expectation: "CREATE TABLE IF NOT EXISTS myTable (title VARCHAR(255), name VARCHAR(255));",
context: {options: {quoteIdentifiers: false}}
},
{
arguments: ['mySchema.myTable', {title: 'VARCHAR(255)', name: 'VARCHAR(255)'}],
expectation: "CREATE TABLE IF NOT EXISTS mySchema.myTable (title VARCHAR(255), name VARCHAR(255));",
context: {options: {quoteIdentifiers: false}}
},
{
arguments: ['myTable', {title: 'ENUM("A", "B", "C")', name: 'VARCHAR(255)'}],
expectation: "DROP TYPE IF EXISTS enum_myTable_title; CREATE TYPE enum_myTable_title AS ENUM(\"A\", \"B\", \"C\"); CREATE TABLE IF NOT EXISTS myTable (title enum_myTable_title, name VARCHAR(255));",
context: {options: {quoteIdentifiers: false}}
},
{
arguments: ['myTable', {title: 'VARCHAR(255)', name: 'VARCHAR(255)', id: 'INTEGER PRIMARY KEY'}],
expectation: "CREATE TABLE IF NOT EXISTS myTable (title VARCHAR(255), name VARCHAR(255), id INTEGER , PRIMARY KEY (id));",
context: {options: {quoteIdentifiers: false}}
},
{
arguments: ['myTable', {title: 'VARCHAR(255)', name: 'VARCHAR(255)', otherId: 'INTEGER REFERENCES otherTable (id) ON DELETE CASCADE ON UPDATE NO ACTION'}],
expectation: "CREATE TABLE IF NOT EXISTS myTable (title VARCHAR(255), name VARCHAR(255), otherId INTEGER REFERENCES otherTable (id) ON DELETE CASCADE ON UPDATE NO ACTION);",
context: {options: {quoteIdentifiers: false}}
}
],
// Variants when quoteIdentifiers is false
{
arguments: ['myTable'],
expectation: "DROP TABLE IF EXISTS myTable;",
context: {options: {quoteIdentifiers: false}}
},
{
arguments: ['mySchema.myTable'],
expectation: "DROP TABLE IF EXISTS mySchema.myTable;",
context: {options: {quoteIdentifiers: false}}
},
{
arguments: ['myTable', {cascade: true}],
expectation: "DROP TABLE IF EXISTS myTable CASCADE;",
context: {options: {quoteIdentifiers: false}}
},
{
arguments: ['mySchema.myTable', {cascade: true}],
expectation: "DROP TABLE IF EXISTS mySchema.myTable CASCADE;",
context: {options: {quoteIdentifiers: false}}
}
],
dropTableQuery: [
{
arguments: ['myTable'],
expectation: "DROP TABLE IF EXISTS \"myTable\";"
},
{
arguments: ['mySchema.myTable'],
expectation: "DROP TABLE IF EXISTS \"mySchema\".\"myTable\";"
},
{
arguments: ['myTable', {cascade: true}],
expectation: "DROP TABLE IF EXISTS \"myTable\" CASCADE;"
},
{
arguments: ['mySchema.myTable', {cascade: true}],
expectation: "DROP TABLE IF EXISTS \"mySchema\".\"myTable\" CASCADE;"
},
selectQuery: [
{
arguments: ['myTable'],
expectation: "SELECT * FROM \"myTable\";"
}, {
arguments: ['myTable', {attributes: ['id', 'name']}],
expectation: "SELECT \"id\", \"name\" FROM \"myTable\";"
}, {
arguments: ['myTable', {where: {id: 2}}],
expectation: "SELECT * FROM \"myTable\" WHERE \"myTable\".\"id\"=2;"
}, {
arguments: ['myTable', {where: {name: 'foo'}}],
expectation: "SELECT * FROM \"myTable\" WHERE \"myTable\".\"name\"='foo';"
}, {
arguments: ['myTable', {where: {name: "foo';DROP TABLE myTable;"}}],
expectation: "SELECT * FROM \"myTable\" WHERE \"myTable\".\"name\"='foo'';DROP TABLE myTable;';"
}, {
arguments: ['myTable', {where: 2}],
expectation: "SELECT * FROM \"myTable\" WHERE \"myTable\".\"id\"=2;"
}, {
arguments: ['foo', { attributes: [['count(*)', 'count']] }],
expectation: 'SELECT count(*) as \"count\" FROM \"foo\";'
}, {
arguments: ['myTable', {where: "foo='bar'"}],
expectation: "SELECT * FROM \"myTable\" WHERE foo='bar';"
}, {
arguments: ['myTable', {order: "id DESC"}],
expectation: "SELECT * FROM \"myTable\" ORDER BY \"id\" DESC;"
}, {
arguments: ['myTable', {group: "name"}],
expectation: "SELECT * FROM \"myTable\" GROUP BY \"name\";"
}, {
arguments: ['myTable', {group: ["name"]}],
expectation: "SELECT * FROM \"myTable\" GROUP BY \"name\";"
}, {
arguments: ['myTable', {group: ["name","title"]}],
expectation: "SELECT * FROM \"myTable\" GROUP BY \"name\", \"title\";"
}, {
arguments: ['myTable', {limit: 10}],
expectation: "SELECT * FROM \"myTable\" LIMIT 10;"
}, {
arguments: ['myTable', {limit: 10, offset: 2}],
expectation: "SELECT * FROM \"myTable\" LIMIT 10 OFFSET 2;"
}, {
title: 'uses offset even if no limit was passed',
arguments: ['myTable', {offset: 2}],
expectation: "SELECT * FROM \"myTable\" OFFSET 2;"
}, {
arguments: ['mySchema.myTable'],
expectation: "SELECT * FROM \"mySchema\".\"myTable\";"
}, {
arguments: ['mySchema.myTable', {where: {name: "foo';DROP TABLE mySchema.myTable;"}}],
expectation: "SELECT * FROM \"mySchema\".\"myTable\" WHERE \"mySchema\".\"myTable\".\"name\"='foo'';DROP TABLE mySchema.myTable;';"
},
// Variants when quoteIdentifiers is false
{
arguments: ['myTable'],
expectation: "DROP TABLE IF EXISTS myTable;",
context: {options: {quoteIdentifiers: false}}
},
{
arguments: ['mySchema.myTable'],
expectation: "DROP TABLE IF EXISTS mySchema.myTable;",
context: {options: {quoteIdentifiers: false}}
},
{
arguments: ['myTable', {cascade: true}],
expectation: "DROP TABLE IF EXISTS myTable CASCADE;",
context: {options: {quoteIdentifiers: false}}
},
{
arguments: ['mySchema.myTable', {cascade: true}],
expectation: "DROP TABLE IF EXISTS mySchema.myTable CASCADE;",
context: {options: {quoteIdentifiers: false}}
}
],
// Variants when quoteIdentifiers is false
{
arguments: ['myTable'],
expectation: "SELECT * FROM myTable;",
context: {options: {quoteIdentifiers: false}}
}, {
arguments: ['myTable', {attributes: ['id', 'name']}],
expectation: "SELECT id, name FROM myTable;",
context: {options: {quoteIdentifiers: false}}
}, {
arguments: ['myTable', {where: {id: 2}}],
expectation: "SELECT * FROM myTable WHERE myTable.id=2;",
context: {options: {quoteIdentifiers: false}}
}, {
arguments: ['myTable', {where: {name: 'foo'}}],
expectation: "SELECT * FROM myTable WHERE myTable.name='foo';",
context: {options: {quoteIdentifiers: false}}
}, {
arguments: ['myTable', {where: {name: "foo';DROP TABLE myTable;"}}],
expectation: "SELECT * FROM myTable WHERE myTable.name='foo'';DROP TABLE myTable;';",
context: {options: {quoteIdentifiers: false}}
}, {
arguments: ['myTable', {where: 2}],
expectation: "SELECT * FROM myTable WHERE myTable.id=2;",
context: {options: {quoteIdentifiers: false}}
}, {
arguments: ['foo', { attributes: [['count(*)', 'count']] }],
expectation: 'SELECT count(*) as count FROM foo;',
context: {options: {quoteIdentifiers: false}}
}, {
arguments: ['myTable', {where: "foo='bar'"}],
expectation: "SELECT * FROM myTable WHERE foo='bar';",
context: {options: {quoteIdentifiers: false}}
}, {
arguments: ['myTable', {order: "id DESC"}],
expectation: "SELECT * FROM myTable ORDER BY id DESC;",
context: {options: {quoteIdentifiers: false}}
}, {
arguments: ['myTable', {group: "name"}],
expectation: "SELECT * FROM myTable GROUP BY name;",
context: {options: {quoteIdentifiers: false}}
}, {
arguments: ['myTable', {group: ["name"]}],
expectation: "SELECT * FROM myTable GROUP BY name;",
context: {options: {quoteIdentifiers: false}}
}, {
arguments: ['myTable', {group: ["name","title"]}],
expectation: "SELECT * FROM myTable GROUP BY name, title;",
context: {options: {quoteIdentifiers: false}}
}, {
arguments: ['myTable', {limit: 10}],
expectation: "SELECT * FROM myTable LIMIT 10;",
context: {options: {quoteIdentifiers: false}}
}, {
arguments: ['myTable', {limit: 10, offset: 2}],
expectation: "SELECT * FROM myTable LIMIT 10 OFFSET 2;",
context: {options: {quoteIdentifiers: false}}
}, {
title: 'uses offset even if no limit was passed',
arguments: ['myTable', {offset: 2}],
expectation: "SELECT * FROM myTable OFFSET 2;",
context: {options: {quoteIdentifiers: false}}
}, {
arguments: ['mySchema.myTable'],
expectation: "SELECT * FROM mySchema.myTable;",
context: {options: {quoteIdentifiers: false}}
}, {
arguments: ['mySchema.myTable', {where: {name: "foo';DROP TABLE mySchema.myTable;"}}],
expectation: "SELECT * FROM mySchema.myTable WHERE mySchema.myTable.name='foo'';DROP TABLE mySchema.myTable;';",
context: {options: {quoteIdentifiers: false}}
}
],
selectQuery: [
{
arguments: ['myTable'],
expectation: "SELECT * FROM \"myTable\";"
}, {
arguments: ['myTable', {attributes: ['id', 'name']}],
expectation: "SELECT \"id\", \"name\" FROM \"myTable\";"
}, {
arguments: ['myTable', {where: {id: 2}}],
expectation: "SELECT * FROM \"myTable\" WHERE \"myTable\".\"id\"=2;"
}, {
arguments: ['myTable', {where: {name: 'foo'}}],
expectation: "SELECT * FROM \"myTable\" WHERE \"myTable\".\"name\"='foo';"
}, {
arguments: ['myTable', {where: {name: "foo';DROP TABLE myTable;"}}],
expectation: "SELECT * FROM \"myTable\" WHERE \"myTable\".\"name\"='foo'';DROP TABLE myTable;';"
}, {
arguments: ['myTable', {where: 2}],
expectation: "SELECT * FROM \"myTable\" WHERE \"myTable\".\"id\"=2;"
}, {
arguments: ['foo', { attributes: [['count(*)', 'count']] }],
expectation: 'SELECT count(*) as \"count\" FROM \"foo\";'
}, {
arguments: ['myTable', {where: "foo='bar'"}],
expectation: "SELECT * FROM \"myTable\" WHERE foo='bar';"
}, {
arguments: ['myTable', {order: "id DESC"}],
expectation: "SELECT * FROM \"myTable\" ORDER BY \"id\" DESC;"
}, {
arguments: ['myTable', {group: "name"}],
expectation: "SELECT * FROM \"myTable\" GROUP BY \"name\";"
}, {
arguments: ['myTable', {group: ["name"]}],
expectation: "SELECT * FROM \"myTable\" GROUP BY \"name\";"
}, {
arguments: ['myTable', {group: ["name","title"]}],
expectation: "SELECT * FROM \"myTable\" GROUP BY \"name\", \"title\";"
}, {
arguments: ['myTable', {limit: 10}],
expectation: "SELECT * FROM \"myTable\" LIMIT 10;"
}, {
arguments: ['myTable', {limit: 10, offset: 2}],
expectation: "SELECT * FROM \"myTable\" LIMIT 10 OFFSET 2;"
}, {
title: 'uses offset even if no limit was passed',
arguments: ['myTable', {offset: 2}],
expectation: "SELECT * FROM \"myTable\" OFFSET 2;"
}, {
arguments: ['mySchema.myTable'],
expectation: "SELECT * FROM \"mySchema\".\"myTable\";"
}, {
arguments: ['mySchema.myTable', {where: {name: "foo';DROP TABLE mySchema.myTable;"}}],
expectation: "SELECT * FROM \"mySchema\".\"myTable\" WHERE \"mySchema\".\"myTable\".\"name\"='foo'';DROP TABLE mySchema.myTable;';"
},
insertQuery: [
{
arguments: ['myTable', {name: 'foo'}],
expectation: "INSERT INTO \"myTable\" (\"name\") VALUES ('foo') RETURNING *;"
}, {
arguments: ['myTable', {name: "foo';DROP TABLE myTable;"}],
expectation: "INSERT INTO \"myTable\" (\"name\") VALUES ('foo'';DROP TABLE myTable;') RETURNING *;"
}, {
arguments: ['myTable', {name: 'foo', birthday: new Date(Date.UTC(2011, 2, 27, 10, 1, 55))}],
expectation: "INSERT INTO \"myTable\" (\"name\",\"birthday\") VALUES ('foo','2011-03-27 10:01:55.000 +00:00') RETURNING *;"
}, {
arguments: ['myTable', {name: 'foo', foo: 1}],
expectation: "INSERT INTO \"myTable\" (\"name\",\"foo\") VALUES ('foo',1) RETURNING *;"
}, {
arguments: ['myTable', {name: 'foo', nullValue: null}],
expectation: "INSERT INTO \"myTable\" (\"name\",\"nullValue\") VALUES ('foo',NULL) RETURNING *;"
}, {
arguments: ['myTable', {name: 'foo', nullValue: null}],
expectation: "INSERT INTO \"myTable\" (\"name\",\"nullValue\") VALUES ('foo',NULL) RETURNING *;",
context: {options: {omitNull: false}}
}, {
arguments: ['myTable', {name: 'foo', nullValue: null}],
expectation: "INSERT INTO \"myTable\" (\"name\") VALUES ('foo') RETURNING *;",
context: {options: {omitNull: true}}
}, {
arguments: ['myTable', {name: 'foo', nullValue: undefined}],
expectation: "INSERT INTO \"myTable\" (\"name\") VALUES ('foo') RETURNING *;",
context: {options: {omitNull: true}}
}, {
arguments: ['mySchema.myTable', {name: 'foo'}],
expectation: "INSERT INTO \"mySchema\".\"myTable\" (\"name\") VALUES ('foo') RETURNING *;"
}, {
arguments: ['mySchema.myTable', {name: JSON.stringify({info: 'Look ma a " quote'})}],
expectation: "INSERT INTO \"mySchema\".\"myTable\" (\"name\") VALUES ('{\"info\":\"Look ma a \\\" quote\"}') RETURNING *;"
}, {
arguments: ['mySchema.myTable', {name: "foo';DROP TABLE mySchema.myTable;"}],
expectation: "INSERT INTO \"mySchema\".\"myTable\" (\"name\") VALUES ('foo'';DROP TABLE mySchema.myTable;') RETURNING *;"
},
// Variants when quoteIdentifiers is false
{
arguments: ['myTable'],
expectation: "SELECT * FROM myTable;",
context: {options: {quoteIdentifiers: false}}
}, {
arguments: ['myTable', {attributes: ['id', 'name']}],
expectation: "SELECT id, name FROM myTable;",
context: {options: {quoteIdentifiers: false}}
}, {
arguments: ['myTable', {where: {id: 2}}],
expectation: "SELECT * FROM myTable WHERE myTable.id=2;",
context: {options: {quoteIdentifiers: false}}
}, {
arguments: ['myTable', {where: {name: 'foo'}}],
expectation: "SELECT * FROM myTable WHERE myTable.name='foo';",
context: {options: {quoteIdentifiers: false}}
}, {
arguments: ['myTable', {where: {name: "foo';DROP TABLE myTable;"}}],
expectation: "SELECT * FROM myTable WHERE myTable.name='foo'';DROP TABLE myTable;';",
context: {options: {quoteIdentifiers: false}}
}, {
arguments: ['myTable', {where: 2}],
expectation: "SELECT * FROM myTable WHERE myTable.id=2;",
context: {options: {quoteIdentifiers: false}}
}, {
arguments: ['foo', { attributes: [['count(*)', 'count']] }],
expectation: 'SELECT count(*) as count FROM foo;',
context: {options: {quoteIdentifiers: false}}
}, {
arguments: ['myTable', {where: "foo='bar'"}],
expectation: "SELECT * FROM myTable WHERE foo='bar';",
context: {options: {quoteIdentifiers: false}}
}, {
arguments: ['myTable', {order: "id DESC"}],
expectation: "SELECT * FROM myTable ORDER BY id DESC;",
context: {options: {quoteIdentifiers: false}}
}, {
arguments: ['myTable', {group: "name"}],
expectation: "SELECT * FROM myTable GROUP BY name;",
context: {options: {quoteIdentifiers: false}}
}, {
arguments: ['myTable', {group: ["name"]}],
expectation: "SELECT * FROM myTable GROUP BY name;",
context: {options: {quoteIdentifiers: false}}
}, {
arguments: ['myTable', {group: ["name","title"]}],
expectation: "SELECT * FROM myTable GROUP BY name, title;",
context: {options: {quoteIdentifiers: false}}
}, {
arguments: ['myTable', {limit: 10}],
expectation: "SELECT * FROM myTable LIMIT 10;",
context: {options: {quoteIdentifiers: false}}
}, {
arguments: ['myTable', {limit: 10, offset: 2}],
expectation: "SELECT * FROM myTable LIMIT 10 OFFSET 2;",
context: {options: {quoteIdentifiers: false}}
}, {
title: 'uses offset even if no limit was passed',
arguments: ['myTable', {offset: 2}],
expectation: "SELECT * FROM myTable OFFSET 2;",
context: {options: {quoteIdentifiers: false}}
}, {
arguments: ['mySchema.myTable'],
expectation: "SELECT * FROM mySchema.myTable;",
context: {options: {quoteIdentifiers: false}}
}, {
arguments: ['mySchema.myTable', {where: {name: "foo';DROP TABLE mySchema.myTable;"}}],
expectation: "SELECT * FROM mySchema.myTable WHERE mySchema.myTable.name='foo'';DROP TABLE mySchema.myTable;';",
context: {options: {quoteIdentifiers: false}}
}
],
// Variants when quoteIdentifiers is false
{
arguments: ['myTable', {name: 'foo'}],
expectation: "INSERT INTO myTable (name) VALUES ('foo') RETURNING *;",
context: {options: {quoteIdentifiers: false}}
}, {
arguments: ['myTable', {name: "foo';DROP TABLE myTable;"}],
expectation: "INSERT INTO myTable (name) VALUES ('foo'';DROP TABLE myTable;') RETURNING *;",
context: {options: {quoteIdentifiers: false}}
}, {
arguments: ['myTable', {name: 'foo', birthday: new Date(Date.UTC(2011, 2, 27, 10, 1, 55))}],
expectation: "INSERT INTO myTable (name,birthday) VALUES ('foo','2011-03-27 10:01:55.000 +00:00') RETURNING *;",
context: {options: {quoteIdentifiers: false}}
}, {
arguments: ['myTable', {name: 'foo', foo: 1}],
expectation: "INSERT INTO myTable (name,foo) VALUES ('foo',1) RETURNING *;",
context: {options: {quoteIdentifiers: false}}
}, {
arguments: ['myTable', {name: 'foo', nullValue: null}],
expectation: "INSERT INTO myTable (name,nullValue) VALUES ('foo',NULL) RETURNING *;",
context: {options: {quoteIdentifiers: false}}
}, {
arguments: ['myTable', {name: 'foo', nullValue: null}],
expectation: "INSERT INTO myTable (name,nullValue) VALUES ('foo',NULL) RETURNING *;",
context: {options: {omitNull: false, quoteIdentifiers: false}}
}, {
arguments: ['myTable', {name: 'foo', nullValue: null}],
expectation: "INSERT INTO myTable (name) VALUES ('foo') RETURNING *;",
context: {options: {omitNull: true, quoteIdentifiers: false}}
}, {
arguments: ['myTable', {name: 'foo', nullValue: undefined}],
expectation: "INSERT INTO myTable (name) VALUES ('foo') RETURNING *;",
context: {options: {omitNull: true, quoteIdentifiers: false}}
}, {
arguments: ['mySchema.myTable', {name: 'foo'}],
expectation: "INSERT INTO mySchema.myTable (name) VALUES ('foo') RETURNING *;",
context: {options: {quoteIdentifiers: false}}
}, {
arguments: ['mySchema.myTable', {name: JSON.stringify({info: 'Look ma a " quote'})}],
expectation: "INSERT INTO mySchema.myTable (name) VALUES ('{\"info\":\"Look ma a \\\" quote\"}') RETURNING *;",
context: {options: {quoteIdentifiers: false}}
}, {
arguments: ['mySchema.myTable', {name: "foo';DROP TABLE mySchema.myTable;"}],
expectation: "INSERT INTO mySchema.myTable (name) VALUES ('foo'';DROP TABLE mySchema.myTable;') RETURNING *;",
context: {options: {quoteIdentifiers: false}}
}
insertQuery: [
{
arguments: ['myTable', {name: 'foo'}],
expectation: "INSERT INTO \"myTable\" (\"name\") VALUES ('foo') RETURNING *;"
}, {
arguments: ['myTable', {name: "foo';DROP TABLE myTable;"}],
expectation: "INSERT INTO \"myTable\" (\"name\") VALUES ('foo'';DROP TABLE myTable;') RETURNING *;"
}, {
arguments: ['myTable', {name: 'foo', birthday: moment("2011-03-27 10:01:55 +0000", "YYYY-MM-DD HH:mm:ss Z").toDate()}],
expectation: "INSERT INTO \"myTable\" (\"name\",\"birthday\") VALUES ('foo','2011-03-27 10:01:55.000 +00:00') RETURNING *;"
}, {
arguments: ['myTable', {name: 'foo', foo: 1}],
expectation: "INSERT INTO \"myTable\" (\"name\",\"foo\") VALUES ('foo',1) RETURNING *;"
}, {
arguments: ['myTable', {name: 'foo', nullValue: null}],
expectation: "INSERT INTO \"myTable\" (\"name\",\"nullValue\") VALUES ('foo',NULL) RETURNING *;"
}, {
arguments: ['myTable', {name: 'foo', nullValue: null}],
expectation: "INSERT INTO \"myTable\" (\"name\",\"nullValue\") VALUES ('foo',NULL) RETURNING *;",
context: {options: {omitNull: false}}
}, {
arguments: ['myTable', {name: 'foo', nullValue: null}],
expectation: "INSERT INTO \"myTable\" (\"name\") VALUES ('foo') RETURNING *;",
context: {options: {omitNull: true}}
}, {
arguments: ['myTable', {name: 'foo', nullValue: undefined}],
expectation: "INSERT INTO \"myTable\" (\"name\") VALUES ('foo') RETURNING *;",
context: {options: {omitNull: true}}
}, {
arguments: ['mySchema.myTable', {name: 'foo'}],
expectation: "INSERT INTO \"mySchema\".\"myTable\" (\"name\") VALUES ('foo') RETURNING *;"
}, {
arguments: ['mySchema.myTable', {name: JSON.stringify({info: 'Look ma a " quote'})}],
expectation: "INSERT INTO \"mySchema\".\"myTable\" (\"name\") VALUES ('{\"info\":\"Look ma a \\\" quote\"}') RETURNING *;"
}, {
arguments: ['mySchema.myTable', {name: "foo';DROP TABLE mySchema.myTable;"}],
expectation: "INSERT INTO \"mySchema\".\"myTable\" (\"name\") VALUES ('foo'';DROP TABLE mySchema.myTable;') RETURNING *;"
},
],
// Variants when quoteIdentifiers is false
{
arguments: ['myTable', {name: 'foo'}],
expectation: "INSERT INTO myTable (name) VALUES ('foo') RETURNING *;",
context: {options: {quoteIdentifiers: false}}
}, {
arguments: ['myTable', {name: "foo';DROP TABLE myTable;"}],
expectation: "INSERT INTO myTable (name) VALUES ('foo'';DROP TABLE myTable;') RETURNING *;",
context: {options: {quoteIdentifiers: false}}
}, {
arguments: ['myTable', {name: 'foo', birthday: moment("2011-03-27 10:01:55 +0000", "YYYY-MM-DD HH:mm:ss Z").toDate()}],
expectation: "INSERT INTO myTable (name,birthday) VALUES ('foo','2011-03-27 10:01:55.000 +00:00') RETURNING *;",
context: {options: {quoteIdentifiers: false}}
}, {
arguments: ['myTable', {name: 'foo', foo: 1}],
expectation: "INSERT INTO myTable (name,foo) VALUES ('foo',1) RETURNING *;",
context: {options: {quoteIdentifiers: false}}
}, {
arguments: ['myTable', {name: 'foo', nullValue: null}],
expectation: "INSERT INTO myTable (name,nullValue) VALUES ('foo',NULL) RETURNING *;",
context: {options: {quoteIdentifiers: false}}
}, {
arguments: ['myTable', {name: 'foo', nullValue: null}],
expectation: "INSERT INTO myTable (name,nullValue) VALUES ('foo',NULL) RETURNING *;",
context: {options: {omitNull: false, quoteIdentifiers: false}}
}, {
arguments: ['myTable', {name: 'foo', nullValue: null}],
expectation: "INSERT INTO myTable (name) VALUES ('foo') RETURNING *;",
context: {options: {omitNull: true, quoteIdentifiers: false}}
}, {
arguments: ['myTable', {name: 'foo', nullValue: undefined}],
expectation: "INSERT INTO myTable (name) VALUES ('foo') RETURNING *;",
context: {options: {omitNull: true, quoteIdentifiers: false}}
}, {
arguments: ['mySchema.myTable', {name: 'foo'}],
expectation: "INSERT INTO mySchema.myTable (name) VALUES ('foo') RETURNING *;",
context: {options: {quoteIdentifiers: false}}
}, {
arguments: ['mySchema.myTable', {name: JSON.stringify({info: 'Look ma a " quote'})}],
expectation: "INSERT INTO mySchema.myTable (name) VALUES ('{\"info\":\"Look ma a \\\" quote\"}') RETURNING *;",
context: {options: {quoteIdentifiers: false}}
}, {
arguments: ['mySchema.myTable', {name: "foo';DROP TABLE mySchema.myTable;"}],
expectation: "INSERT INTO mySchema.myTable (name) VALUES ('foo'';DROP TABLE mySchema.myTable;') RETURNING *;",
context: {options: {quoteIdentifiers: false}}
}
bulkInsertQuery: [
{
arguments: ['myTable', [{name: 'foo'}, {name: 'bar'}]],
expectation: "INSERT INTO \"myTable\" (\"name\") VALUES ('foo'),('bar') RETURNING *;"
}, {
arguments: ['myTable', [{name: "foo';DROP TABLE myTable;"}, {name: 'bar'}]],
expectation: "INSERT INTO \"myTable\" (\"name\") VALUES ('foo'';DROP TABLE myTable;'),('bar') RETURNING *;"
}, {
arguments: ['myTable', [{name: 'foo', birthday: new Date(Date.UTC(2011, 2, 27, 10, 1, 55))}, {name: 'bar', birthday: new Date(Date.UTC(2012, 2, 27, 10, 1, 55))}]],
expectation: "INSERT INTO \"myTable\" (\"name\",\"birthday\") VALUES ('foo','2011-03-27 10:01:55.000 +00:00'),('bar','2012-03-27 10:01:55.000 +00:00') RETURNING *;"
}, {
arguments: ['myTable', [{name: 'foo', foo: 1}, {name: 'bar', foo: 2}]],
expectation: "INSERT INTO \"myTable\" (\"name\",\"foo\") VALUES ('foo',1),('bar',2) RETURNING *;"
}, {
arguments: ['myTable', [{name: 'foo', nullValue: null}, {name: 'bar', nullValue: null}]],
expectation: "INSERT INTO \"myTable\" (\"name\",\"nullValue\") VALUES ('foo',NULL),('bar',NULL) RETURNING *;"
}, {
arguments: ['myTable', [{name: 'foo', nullValue: null}, {name: 'bar', nullValue: null}]],
expectation: "INSERT INTO \"myTable\" (\"name\",\"nullValue\") VALUES ('foo',NULL),('bar',NULL) RETURNING *;",
context: {options: {omitNull: false}}
}, {
arguments: ['myTable', [{name: 'foo', nullValue: null}, {name: 'bar', nullValue: null}]],
expectation: "INSERT INTO \"myTable\" (\"name\",\"nullValue\") VALUES ('foo',NULL),('bar',NULL) RETURNING *;",
context: {options: {omitNull: true}} // Note: We don't honour this because it makes little sense when some rows may have nulls and others not
}, {
arguments: ['myTable', [{name: 'foo', nullValue: undefined}, {name: 'bar', nullValue: undefined}]],
expectation: "INSERT INTO \"myTable\" (\"name\",\"nullValue\") VALUES ('foo',NULL),('bar',NULL) RETURNING *;",
context: {options: {omitNull: true}} // Note: As above
}, {
arguments: ['mySchema.myTable', [{name: 'foo'}, {name: 'bar'}]],
expectation: "INSERT INTO \"mySchema\".\"myTable\" (\"name\") VALUES ('foo'),('bar') RETURNING *;"
}, {
arguments: ['mySchema.myTable', [{name: JSON.stringify({info: 'Look ma a " quote'})}, {name: JSON.stringify({info: 'Look ma another " quote'})}]],
expectation: "INSERT INTO \"mySchema\".\"myTable\" (\"name\") VALUES ('{\"info\":\"Look ma a \\\" quote\"}'),('{\"info\":\"Look ma another \\\" quote\"}') RETURNING *;"
}, {
arguments: ['mySchema.myTable', [{name: "foo';DROP TABLE mySchema.myTable;"}, {name: 'bar'}]],
expectation: "INSERT INTO \"mySchema\".\"myTable\" (\"name\") VALUES ('foo'';DROP TABLE mySchema.myTable;'),('bar') RETURNING *;"
},
],
// Variants when quoteIdentifiers is false
{
arguments: ['myTable', [{name: 'foo'}, {name: 'bar'}]],
expectation: "INSERT INTO myTable (name) VALUES ('foo'),('bar') RETURNING *;",
context: {options: {quoteIdentifiers: false}}
}, {
arguments: ['myTable', [{name: "foo';DROP TABLE myTable;"}, {name: 'bar'}]],
expectation: "INSERT INTO myTable (name) VALUES ('foo'';DROP TABLE myTable;'),('bar') RETURNING *;",
context: {options: {quoteIdentifiers: false}}
}, {
arguments: ['myTable', [{name: 'foo', birthday: new Date(Date.UTC(2011, 2, 27, 10, 1, 55))}, {name: 'bar', birthday: new Date(Date.UTC(2012, 2, 27, 10, 1, 55))}]],
expectation: "INSERT INTO myTable (name,birthday) VALUES ('foo','2011-03-27 10:01:55.000 +00:00'),('bar','2012-03-27 10:01:55.000 +00:00') RETURNING *;",
context: {options: {quoteIdentifiers: false}}
}, {
arguments: ['myTable', [{name: 'foo', foo: 1}, {name: 'bar', foo: 2}]],
expectation: "INSERT INTO myTable (name,foo) VALUES ('foo',1),('bar',2) RETURNING *;",
context: {options: {quoteIdentifiers: false}}
}, {
arguments: ['myTable', [{name: 'foo', nullValue: null}, {name: 'bar', nullValue: null}]],
expectation: "INSERT INTO myTable (name,nullValue) VALUES ('foo',NULL),('bar',NULL) RETURNING *;",
context: {options: {quoteIdentifiers: false}}
}, {
arguments: ['myTable', [{name: 'foo', nullValue: null}, {name: 'bar', nullValue: null}]],
expectation: "INSERT INTO myTable (name,nullValue) VALUES ('foo',NULL),('bar',NULL) RETURNING *;",
context: {options: {quoteIdentifiers: false, omitNull: false}},
}, {
arguments: ['myTable', [{name: 'foo', nullValue: null}, {name: 'bar', nullValue: null}]],
expectation: "INSERT INTO myTable (name,nullValue) VALUES ('foo',NULL),('bar',NULL) RETURNING *;",
context: {options: {omitNull: true, quoteIdentifiers: false}} // Note: We don't honour this because it makes little sense when some rows may have nulls and others not
}, {
arguments: ['myTable', [{name: 'foo', nullValue: undefined}, {name: 'bar', nullValue: undefined}]],
expectation: "INSERT INTO myTable (name,nullValue) VALUES ('foo',NULL),('bar',NULL) RETURNING *;",
context: {options: {omitNull: true, quoteIdentifiers: false}} // Note: As above
}, {
arguments: ['mySchema.myTable', [{name: 'foo'}, {name: 'bar'}]],
expectation: "INSERT INTO mySchema.myTable (name) VALUES ('foo'),('bar') RETURNING *;",
context: {options: {quoteIdentifiers: false}}
}, {
arguments: ['mySchema.myTable', [{name: JSON.stringify({info: 'Look ma a " quote'})}, {name: JSON.stringify({info: 'Look ma another " quote'})}]],
expectation: "INSERT INTO mySchema.myTable (name) VALUES ('{\"info\":\"Look ma a \\\" quote\"}'),('{\"info\":\"Look ma another \\\" quote\"}') RETURNING *;",
context: {options: {quoteIdentifiers: false}}
}, {
arguments: ['mySchema.myTable', [{name: "foo';DROP TABLE mySchema.myTable;"}, {name: 'bar'}]],
expectation: "INSERT INTO mySchema.myTable (name) VALUES ('foo'';DROP TABLE mySchema.myTable;'),('bar') RETURNING *;",
context: {options: {quoteIdentifiers: false}}
}
],
bulkInsertQuery: [
{
arguments: ['myTable', [{name: 'foo'}, {name: 'bar'}]],
expectation: "INSERT INTO \"myTable\" (\"name\") VALUES ('foo'),('bar') RETURNING *;"
}, {
arguments: ['myTable', [{name: "foo';DROP TABLE myTable;"}, {name: 'bar'}]],
expectation: "INSERT INTO \"myTable\" (\"name\") VALUES ('foo'';DROP TABLE myTable;'),('bar') RETURNING *;"
}, {
arguments: ['myTable', [{name: 'foo', birthday: moment("2011-03-27 10:01:55 +0000", "YYYY-MM-DD HH:mm:ss Z").toDate()}, {name: 'bar', birthday: moment("2012-03-27 10:01:55 +0000", "YYYY-MM-DD HH:mm:ss Z").toDate()}]],
expectation: "INSERT INTO \"myTable\" (\"name\",\"birthday\") VALUES ('foo','2011-03-27 10:01:55.000 +00:00'),('bar','2012-03-27 10:01:55.000 +00:00') RETURNING *;"
}, {
arguments: ['myTable', [{name: 'foo', foo: 1}, {name: 'bar', foo: 2}]],
expectation: "INSERT INTO \"myTable\" (\"name\",\"foo\") VALUES ('foo',1),('bar',2) RETURNING *;"
}, {
arguments: ['myTable', [{name: 'foo', nullValue: null}, {name: 'bar', nullValue: null}]],
expectation: "INSERT INTO \"myTable\" (\"name\",\"nullValue\") VALUES ('foo',NULL),('bar',NULL) RETURNING *;"
}, {
arguments: ['myTable', [{name: 'foo', nullValue: null}, {name: 'bar', nullValue: null}]],
expectation: "INSERT INTO \"myTable\" (\"name\",\"nullValue\") VALUES ('foo',NULL),('bar',NULL) RETURNING *;",
context: {options: {omitNull: false}}
}, {
arguments: ['myTable', [{name: 'foo', nullValue: null}, {name: 'bar', nullValue: null}]],
expectation: "INSERT INTO \"myTable\" (\"name\",\"nullValue\") VALUES ('foo',NULL),('bar',NULL) RETURNING *;",
context: {options: {omitNull: true}} // Note: We don't honour this because it makes little sense when some rows may have nulls and others not
}, {
arguments: ['myTable', [{name: 'foo', nullValue: undefined}, {name: 'bar', nullValue: undefined}]],
expectation: "INSERT INTO \"myTable\" (\"name\",\"nullValue\") VALUES ('foo',NULL),('bar',NULL) RETURNING *;",
context: {options: {omitNull: true}} // Note: As above
}, {
arguments: ['mySchema.myTable', [{name: 'foo'}, {name: 'bar'}]],
expectation: "INSERT INTO \"mySchema\".\"myTable\" (\"name\") VALUES ('foo'),('bar') RETURNING *;"
}, {
arguments: ['mySchema.myTable', [{name: JSON.stringify({info: 'Look ma a " quote'})}, {name: JSON.stringify({info: 'Look ma another " quote'})}]],
expectation: "INSERT INTO \"mySchema\".\"myTable\" (\"name\") VALUES ('{\"info\":\"Look ma a \\\" quote\"}'),('{\"info\":\"Look ma another \\\" quote\"}') RETURNING *;"
}, {
arguments: ['mySchema.myTable', [{name: "foo';DROP TABLE mySchema.myTable;"}, {name: 'bar'}]],
expectation: "INSERT INTO \"mySchema\".\"myTable\" (\"name\") VALUES ('foo'';DROP TABLE mySchema.myTable;'),('bar') RETURNING *;"
},
updateQuery: [
{
arguments: ['myTable', {name: 'foo', birthday: new Date(Date.UTC(2011, 2, 27, 10, 1, 55))}, {id: 2}],
expectation: "UPDATE \"myTable\" SET \"name\"='foo',\"birthday\"='2011-03-27 10:01:55.000 +00:00' WHERE \"id\"=2 RETURNING *"
}, {
arguments: ['myTable', {name: 'foo', birthday: new Date(Date.UTC(2011, 2, 27, 10, 1, 55))}, 2],
expectation: "UPDATE \"myTable\" SET \"name\"='foo',\"birthday\"='2011-03-27 10:01:55.000 +00:00' WHERE \"id\"=2 RETURNING *"
}, {
arguments: ['myTable', {bar: 2}, {name: 'foo'}],
expectation: "UPDATE \"myTable\" SET \"bar\"=2 WHERE \"name\"='foo' RETURNING *"
}, {
arguments: ['myTable', {name: "foo';DROP TABLE myTable;"}, {name: 'foo'}],
expectation: "UPDATE \"myTable\" SET \"name\"='foo'';DROP TABLE myTable;' WHERE \"name\"='foo' RETURNING *"
}, {
arguments: ['myTable', {bar: 2, nullValue: null}, {name: 'foo'}],
expectation: "UPDATE \"myTable\" SET \"bar\"=2,\"nullValue\"=NULL WHERE \"name\"='foo' RETURNING *"
}, {
arguments: ['myTable', {bar: 2, nullValue: null}, {name: 'foo'}],
expectation: "UPDATE \"myTable\" SET \"bar\"=2,\"nullValue\"=NULL WHERE \"name\"='foo' RETURNING *",
context: {options: {omitNull: false}}
}, {
arguments: ['myTable', {bar: 2, nullValue: null}, {name: 'foo'}],
expectation: "UPDATE \"myTable\" SET \"bar\"=2 WHERE \"name\"='foo' RETURNING *",
context: {options: {omitNull: true}}
}, {
arguments: ['myTable', {bar: 2, nullValue: undefined}, {name: 'foo'}],
expectation: "UPDATE \"myTable\" SET \"bar\"=2 WHERE \"name\"='foo' RETURNING *",
context: {options: {omitNull: true}}
}, {
arguments: ['mySchema.myTable', {name: 'foo', birthday: new Date(Date.UTC(2011, 2, 27, 10, 1, 55))}, {id: 2}],
expectation: "UPDATE \"mySchema\".\"myTable\" SET \"name\"='foo',\"birthday\"='2011-03-27 10:01:55.000 +00:00' WHERE \"id\"=2 RETURNING *"
}, {
arguments: ['mySchema.myTable', {name: "foo';DROP TABLE mySchema.myTable;"}, {name: 'foo'}],
expectation: "UPDATE \"mySchema\".\"myTable\" SET \"name\"='foo'';DROP TABLE mySchema.myTable;' WHERE \"name\"='foo' RETURNING *"
},
// Variants when quoteIdentifiers is false
{
arguments: ['myTable', [{name: 'foo'}, {name: 'bar'}]],
expectation: "INSERT INTO myTable (name) VALUES ('foo'),('bar') RETURNING *;",
context: {options: {quoteIdentifiers: false}}
}, {
arguments: ['myTable', [{name: "foo';DROP TABLE myTable;"}, {name: 'bar'}]],
expectation: "INSERT INTO myTable (name) VALUES ('foo'';DROP TABLE myTable;'),('bar') RETURNING *;",
context: {options: {quoteIdentifiers: false}}
}, {
arguments: ['myTable', [{name: 'foo', birthday: moment("2011-03-27 10:01:55 +0000", "YYYY-MM-DD HH:mm:ss Z").toDate()}, {name: 'bar', birthday: moment("2012-03-27 10:01:55 +0000", "YYYY-MM-DD HH:mm:ss Z").toDate()}]],
expectation: "INSERT INTO myTable (name,birthday) VALUES ('foo','2011-03-27 10:01:55.000 +00:00'),('bar','2012-03-27 10:01:55.000 +00:00') RETURNING *;",
context: {options: {quoteIdentifiers: false}}
}, {
arguments: ['myTable', [{name: 'foo', foo: 1}, {name: 'bar', foo: 2}]],
expectation: "INSERT INTO myTable (name,foo) VALUES ('foo',1),('bar',2) RETURNING *;",
context: {options: {quoteIdentifiers: false}}
}, {
arguments: ['myTable', [{name: 'foo', nullValue: null}, {name: 'bar', nullValue: null}]],
expectation: "INSERT INTO myTable (name,nullValue) VALUES ('foo',NULL),('bar',NULL) RETURNING *;",
context: {options: {quoteIdentifiers: false}}
}, {
arguments: ['myTable', [{name: 'foo', nullValue: null}, {name: 'bar', nullValue: null}]],
expectation: "INSERT INTO myTable (name,nullValue) VALUES ('foo',NULL),('bar',NULL) RETURNING *;",
context: {options: {quoteIdentifiers: false, omitNull: false}},
}, {
arguments: ['myTable', [{name: 'foo', nullValue: null}, {name: 'bar', nullValue: null}]],
expectation: "INSERT INTO myTable (name,nullValue) VALUES ('foo',NULL),('bar',NULL) RETURNING *;",
context: {options: {omitNull: true, quoteIdentifiers: false}} // Note: We don't honour this because it makes little sense when some rows may have nulls and others not
}, {
arguments: ['myTable', [{name: 'foo', nullValue: undefined}, {name: 'bar', nullValue: undefined}]],
expectation: "INSERT INTO myTable (name,nullValue) VALUES ('foo',NULL),('bar',NULL) RETURNING *;",
context: {options: {omitNull: true, quoteIdentifiers: false}} // Note: As above
}, {
arguments: ['mySchema.myTable', [{name: 'foo'}, {name: 'bar'}]],
expectation: "INSERT INTO mySchema.myTable (name) VALUES ('foo'),('bar') RETURNING *;",
context: {options: {quoteIdentifiers: false}}
}, {
arguments: ['mySchema.myTable', [{name: JSON.stringify({info: 'Look ma a " quote'})}, {name: JSON.stringify({info: 'Look ma another " quote'})}]],
expectation: "INSERT INTO mySchema.myTable (name) VALUES ('{\"info\":\"Look ma a \\\" quote\"}'),('{\"info\":\"Look ma another \\\" quote\"}') RETURNING *;",
context: {options: {quoteIdentifiers: false}}
}, {
arguments: ['mySchema.myTable', [{name: "foo';DROP TABLE mySchema.myTable;"}, {name: 'bar'}]],
expectation: "INSERT INTO mySchema.myTable (name) VALUES ('foo'';DROP TABLE mySchema.myTable;'),('bar') RETURNING *;",
context: {options: {quoteIdentifiers: false}}
}
],
// Variants when quoteIdentifiers is false
{
arguments: ['myTable', {name: 'foo', birthday: new Date(Date.UTC(2011, 2, 27, 10, 1, 55))}, {id: 2}],
expectation: "UPDATE myTable SET name='foo',birthday='2011-03-27 10:01:55.000 +00:00' WHERE id=2 RETURNING *",
context: {options: {quoteIdentifiers: false}}
}, {
arguments: ['myTable', {name: 'foo', birthday: new Date(Date.UTC(2011, 2, 27, 10, 1, 55))}, 2],
expectation: "UPDATE myTable SET name='foo',birthday='2011-03-27 10:01:55.000 +00:00' WHERE id=2 RETURNING *",
context: {options: {quoteIdentifiers: false}}
}, {
arguments: ['myTable', {bar: 2}, {name: 'foo'}],
expectation: "UPDATE myTable SET bar=2 WHERE name='foo' RETURNING *",
context: {options: {quoteIdentifiers: false}}
}, {
arguments: ['myTable', {name: "foo';DROP TABLE myTable;"}, {name: 'foo'}],
expectation: "UPDATE myTable SET name='foo'';DROP TABLE myTable;' WHERE name='foo' RETURNING *",
context: {options: {quoteIdentifiers: false}}
}, {
arguments: ['myTable', {bar: 2, nullValue: null}, {name: 'foo'}],
expectation: "UPDATE myTable SET bar=2,nullValue=NULL WHERE name='foo' RETURNING *",
context: {options: {quoteIdentifiers: false}}
}, {
arguments: ['myTable', {bar: 2, nullValue: null}, {name: 'foo'}],
expectation: "UPDATE myTable SET bar=2,nullValue=NULL WHERE name='foo' RETURNING *",
context: {options: {omitNull: false, quoteIdentifiers: false}},
}, {
arguments: ['myTable', {bar: 2, nullValue: null}, {name: 'foo'}],
expectation: "UPDATE myTable SET bar=2 WHERE name='foo' RETURNING *",
context: {options: {omitNull: true, quoteIdentifiers: false}},
}, {
arguments: ['myTable', {bar: 2, nullValue: undefined}, {name: 'foo'}],
expectation: "UPDATE myTable SET bar=2 WHERE name='foo' RETURNING *",
context: {options: {omitNull: true, quoteIdentifiers: false}},
}, {
arguments: ['mySchema.myTable', {name: 'foo', birthday: new Date(Date.UTC(2011, 2, 27, 10, 1, 55))}, {id: 2}],
expectation: "UPDATE mySchema.myTable SET name='foo',birthday='2011-03-27 10:01:55.000 +00:00' WHERE id=2 RETURNING *",
context: {options: {quoteIdentifiers: false}}
}, {
arguments: ['mySchema.myTable', {name: "foo';DROP TABLE mySchema.myTable;"}, {name: 'foo'}],
expectation: "UPDATE mySchema.myTable SET name='foo'';DROP TABLE mySchema.myTable;' WHERE name='foo' RETURNING *",
context: {options: {quoteIdentifiers: false}}
}
],
updateQuery: [
{
arguments: ['myTable', {name: 'foo', birthday: moment("2011-03-27 10:01:55 +0000", "YYYY-MM-DD HH:mm:ss Z").toDate()}, {id: 2}],
expectation: "UPDATE \"myTable\" SET \"name\"='foo',\"birthday\"='2011-03-27 10:01:55.000 +00:00' WHERE \"id\"=2 RETURNING *"
}, {
arguments: ['myTable', {name: 'foo', birthday: moment("2011-03-27 10:01:55 +0000", "YYYY-MM-DD HH:mm:ss Z").toDate()}, 2],
expectation: "UPDATE \"myTable\" SET \"name\"='foo',\"birthday\"='2011-03-27 10:01:55.000 +00:00' WHERE \"id\"=2 RETURNING *"
}, {
arguments: ['myTable', {bar: 2}, {name: 'foo'}],
expectation: "UPDATE \"myTable\" SET \"bar\"=2 WHERE \"name\"='foo' RETURNING *"
}, {
arguments: ['myTable', {name: "foo';DROP TABLE myTable;"}, {name: 'foo'}],
expectation: "UPDATE \"myTable\" SET \"name\"='foo'';DROP TABLE myTable;' WHERE \"name\"='foo' RETURNING *"
}, {
arguments: ['myTable', {bar: 2, nullValue: null}, {name: 'foo'}],
expectation: "UPDATE \"myTable\" SET \"bar\"=2,\"nullValue\"=NULL WHERE \"name\"='foo' RETURNING *"
}, {
arguments: ['myTable', {bar: 2, nullValue: null}, {name: 'foo'}],
expectation: "UPDATE \"myTable\" SET \"bar\"=2,\"nullValue\"=NULL WHERE \"name\"='foo' RETURNING *",
context: {options: {omitNull: false}}
}, {
arguments: ['myTable', {bar: 2, nullValue: null}, {name: 'foo'}],
expectation: "UPDATE \"myTable\" SET \"bar\"=2 WHERE \"name\"='foo' RETURNING *",
context: {options: {omitNull: true}}
}, {
arguments: ['myTable', {bar: 2, nullValue: undefined}, {name: 'foo'}],
expectation: "UPDATE \"myTable\" SET \"bar\"=2 WHERE \"name\"='foo' RETURNING *",
context: {options: {omitNull: true}}
}, {
arguments: ['mySchema.myTable', {name: 'foo', birthday: moment("2011-03-27 10:01:55 +0000", "YYYY-MM-DD HH:mm:ss Z").toDate()}, {id: 2}],
expectation: "UPDATE \"mySchema\".\"myTable\" SET \"name\"='foo',\"birthday\"='2011-03-27 10:01:55.000 +00:00' WHERE \"id\"=2 RETURNING *"
}, {
arguments: ['mySchema.myTable', {name: "foo';DROP TABLE mySchema.myTable;"}, {name: 'foo'}],
expectation: "UPDATE \"mySchema\".\"myTable\" SET \"name\"='foo'';DROP TABLE mySchema.myTable;' WHERE \"name\"='foo' RETURNING *"
},
deleteQuery: [
{
arguments: ['myTable', {name: 'foo'}],
expectation: "DELETE FROM \"myTable\" WHERE \"id\" IN (SELECT \"id\" FROM \"myTable\" WHERE \"name\"='foo' LIMIT 1)"
}, {
arguments: ['myTable', 1],
expectation: "DELETE FROM \"myTable\" WHERE \"id\" IN (SELECT \"id\" FROM \"myTable\" WHERE \"id\"=1 LIMIT 1)"
}, {
arguments: ['myTable', undefined, {truncate: true}],
expectation: "TRUNCATE \"myTable\""
}, {
arguments: ['myTable', 1, {limit: 10, truncate: true}],
expectation: "TRUNCATE \"myTable\""
}, {
arguments: ['myTable', 1, {limit: 10}],
expectation: "DELETE FROM \"myTable\" WHERE \"id\" IN (SELECT \"id\" FROM \"myTable\" WHERE \"id\"=1 LIMIT 10)"
}, {
arguments: ['myTable', {name: "foo';DROP TABLE myTable;"}, {limit: 10}],
expectation: "DELETE FROM \"myTable\" WHERE \"id\" IN (SELECT \"id\" FROM \"myTable\" WHERE \"name\"='foo'';DROP TABLE myTable;' LIMIT 10)"
}, {
arguments: ['mySchema.myTable', {name: 'foo'}],
expectation: "DELETE FROM \"mySchema\".\"myTable\" WHERE \"id\" IN (SELECT \"id\" FROM \"mySchema\".\"myTable\" WHERE \"name\"='foo' LIMIT 1)"
}, {
arguments: ['mySchema.myTable', {name: "foo';DROP TABLE mySchema.myTable;"}, {limit: 10}],
expectation: "DELETE FROM \"mySchema\".\"myTable\" WHERE \"id\" IN (SELECT \"id\" FROM \"mySchema\".\"myTable\" WHERE \"name\"='foo'';DROP TABLE mySchema.myTable;' LIMIT 10)"
}, {
arguments: ['myTable', {name: 'foo'}, {limit: null}],
expectation: "DELETE FROM \"myTable\" WHERE \"id\" IN (SELECT \"id\" FROM \"myTable\" WHERE \"name\"='foo')"
},
// Variants when quoteIdentifiers is false
{
arguments: ['myTable', {name: 'foo', birthday: moment("2011-03-27 10:01:55 +0000", "YYYY-MM-DD HH:mm:ss Z").toDate()}, {id: 2}],
expectation: "UPDATE myTable SET name='foo',birthday='2011-03-27 10:01:55.000 +00:00' WHERE id=2 RETURNING *",
context: {options: {quoteIdentifiers: false}}
}, {
arguments: ['myTable', {name: 'foo', birthday: moment("2011-03-27 10:01:55 +0000", "YYYY-MM-DD HH:mm:ss Z").toDate()}, 2],
expectation: "UPDATE myTable SET name='foo',birthday='2011-03-27 10:01:55.000 +00:00' WHERE id=2 RETURNING *",
context: {options: {quoteIdentifiers: false}}
}, {
arguments: ['myTable', {bar: 2}, {name: 'foo'}],
expectation: "UPDATE myTable SET bar=2 WHERE name='foo' RETURNING *",
context: {options: {quoteIdentifiers: false}}
}, {
arguments: ['myTable', {name: "foo';DROP TABLE myTable;"}, {name: 'foo'}],
expectation: "UPDATE myTable SET name='foo'';DROP TABLE myTable;' WHERE name='foo' RETURNING *",
context: {options: {quoteIdentifiers: false}}
}, {
arguments: ['myTable', {bar: 2, nullValue: null}, {name: 'foo'}],
expectation: "UPDATE myTable SET bar=2,nullValue=NULL WHERE name='foo' RETURNING *",
context: {options: {quoteIdentifiers: false}}
}, {
arguments: ['myTable', {bar: 2, nullValue: null}, {name: 'foo'}],
expectation: "UPDATE myTable SET bar=2,nullValue=NULL WHERE name='foo' RETURNING *",
context: {options: {omitNull: false, quoteIdentifiers: false}},
}, {
arguments: ['myTable', {bar: 2, nullValue: null}, {name: 'foo'}],
expectation: "UPDATE myTable SET bar=2 WHERE name='foo' RETURNING *",
context: {options: {omitNull: true, quoteIdentifiers: false}},
}, {
arguments: ['myTable', {bar: 2, nullValue: undefined}, {name: 'foo'}],
expectation: "UPDATE myTable SET bar=2 WHERE name='foo' RETURNING *",
context: {options: {omitNull: true, quoteIdentifiers: false}},
}, {
arguments: ['mySchema.myTable', {name: 'foo', birthday: moment("2011-03-27 10:01:55 +0000", "YYYY-MM-DD HH:mm:ss Z").toDate()}, {id: 2}],
expectation: "UPDATE mySchema.myTable SET name='foo',birthday='2011-03-27 10:01:55.000 +00:00' WHERE id=2 RETURNING *",
context: {options: {quoteIdentifiers: false}}
}, {
arguments: ['mySchema.myTable', {name: "foo';DROP TABLE mySchema.myTable;"}, {name: 'foo'}],
expectation: "UPDATE mySchema.myTable SET name='foo'';DROP TABLE mySchema.myTable;' WHERE name='foo' RETURNING *",
context: {options: {quoteIdentifiers: false}}
}
],
// Variants when quoteIdentifiers is false
{
arguments: ['myTable', {name: 'foo'}],
expectation: "DELETE FROM myTable WHERE id IN (SELECT id FROM myTable WHERE name='foo' LIMIT 1)",
context: {options: {quoteIdentifiers: false}}
}, {
arguments: ['myTable', 1],
expectation: "DELETE FROM myTable WHERE id IN (SELECT id FROM myTable WHERE id=1 LIMIT 1)",
context: {options: {quoteIdentifiers: false}}
}, {
arguments: ['myTable', 1, {limit: 10}],
expectation: "DELETE FROM myTable WHERE id IN (SELECT id FROM myTable WHERE id=1 LIMIT 10)",
context: {options: {quoteIdentifiers: false}}
}, {
arguments: ['myTable', {name: "foo';DROP TABLE myTable;"}, {limit: 10}],
expectation: "DELETE FROM myTable WHERE id IN (SELECT id FROM myTable WHERE name='foo'';DROP TABLE myTable;' LIMIT 10)",
context: {options: {quoteIdentifiers: false}}
}, {
arguments: ['mySchema.myTable', {name: 'foo'}],
expectation: "DELETE FROM mySchema.myTable WHERE id IN (SELECT id FROM mySchema.myTable WHERE name='foo' LIMIT 1)",
context: {options: {quoteIdentifiers: false}}
}, {
arguments: ['mySchema.myTable', {name: "foo';DROP TABLE mySchema.myTable;"}, {limit: 10}],
expectation: "DELETE FROM mySchema.myTable WHERE id IN (SELECT id FROM mySchema.myTable WHERE name='foo'';DROP TABLE mySchema.myTable;' LIMIT 10)",
context: {options: {quoteIdentifiers: false}}
}, {
arguments: ['myTable', {name: 'foo'}, {limit: null}],
expectation: "DELETE FROM myTable WHERE id IN (SELECT id FROM myTable WHERE name='foo')",
context: {options: {quoteIdentifiers: false}}
}
],
deleteQuery: [
{
arguments: ['myTable', {name: 'foo'}],
expectation: "DELETE FROM \"myTable\" WHERE \"id\" IN (SELECT \"id\" FROM \"myTable\" WHERE \"name\"='foo' LIMIT 1)"
}, {
arguments: ['myTable', 1],
expectation: "DELETE FROM \"myTable\" WHERE \"id\" IN (SELECT \"id\" FROM \"myTable\" WHERE \"id\"=1 LIMIT 1)"
}, {
arguments: ['myTable', undefined, {truncate: true}],
expectation: "TRUNCATE \"myTable\""
}, {
arguments: ['myTable', 1, {limit: 10, truncate: true}],
expectation: "TRUNCATE \"myTable\""
}, {
arguments: ['myTable', 1, {limit: 10}],
expectation: "DELETE FROM \"myTable\" WHERE \"id\" IN (SELECT \"id\" FROM \"myTable\" WHERE \"id\"=1 LIMIT 10)"
}, {
arguments: ['myTable', {name: "foo';DROP TABLE myTable;"}, {limit: 10}],
expectation: "DELETE FROM \"myTable\" WHERE \"id\" IN (SELECT \"id\" FROM \"myTable\" WHERE \"name\"='foo'';DROP TABLE myTable;' LIMIT 10)"
}, {
arguments: ['mySchema.myTable', {name: 'foo'}],
expectation: "DELETE FROM \"mySchema\".\"myTable\" WHERE \"id\" IN (SELECT \"id\" FROM \"mySchema\".\"myTable\" WHERE \"name\"='foo' LIMIT 1)"
}, {
arguments: ['mySchema.myTable', {name: "foo';DROP TABLE mySchema.myTable;"}, {limit: 10}],
expectation: "DELETE FROM \"mySchema\".\"myTable\" WHERE \"id\" IN (SELECT \"id\" FROM \"mySchema\".\"myTable\" WHERE \"name\"='foo'';DROP TABLE mySchema.myTable;' LIMIT 10)"
}, {
arguments: ['myTable', {name: 'foo'}, {limit: null}],
expectation: "DELETE FROM \"myTable\" WHERE \"id\" IN (SELECT \"id\" FROM \"myTable\" WHERE \"name\"='foo')"
},
addIndexQuery: [
{
arguments: ['User', ['username', 'isAdmin']],
expectation: 'CREATE INDEX \"user_username_is_admin\" ON \"User\" (\"username\", \"isAdmin\")'
}, {
arguments: [
'User', [
{ attribute: 'username', length: 10, order: 'ASC'},
'isAdmin'
]
],
expectation: "CREATE INDEX \"user_username_is_admin\" ON \"User\" (\"username\"(10) ASC, \"isAdmin\")"
}, {
arguments: [
'User', ['username', 'isAdmin'], { indicesType: 'FULLTEXT', indexName: 'bar'}
],
expectation: "CREATE FULLTEXT INDEX \"bar\" ON \"User\" (\"username\", \"isAdmin\")"
}, {
arguments: ['mySchema.User', ['username', 'isAdmin']],
expectation: 'CREATE INDEX \"user_username_is_admin\" ON \"mySchema\".\"User\" (\"username\", \"isAdmin\")'
},
// Variants when quoteIdentifiers is false
{
arguments: ['myTable', {name: 'foo'}],
expectation: "DELETE FROM myTable WHERE id IN (SELECT id FROM myTable WHERE name='foo' LIMIT 1)",
context: {options: {quoteIdentifiers: false}}
}, {
arguments: ['myTable', 1],
expectation: "DELETE FROM myTable WHERE id IN (SELECT id FROM myTable WHERE id=1 LIMIT 1)",
context: {options: {quoteIdentifiers: false}}
}, {
arguments: ['myTable', 1, {limit: 10}],
expectation: "DELETE FROM myTable WHERE id IN (SELECT id FROM myTable WHERE id=1 LIMIT 10)",
context: {options: {quoteIdentifiers: false}}
}, {
arguments: ['myTable', {name: "foo';DROP TABLE myTable;"}, {limit: 10}],
expectation: "DELETE FROM myTable WHERE id IN (SELECT id FROM myTable WHERE name='foo'';DROP TABLE myTable;' LIMIT 10)",
context: {options: {quoteIdentifiers: false}}
}, {
arguments: ['mySchema.myTable', {name: 'foo'}],
expectation: "DELETE FROM mySchema.myTable WHERE id IN (SELECT id FROM mySchema.myTable WHERE name='foo' LIMIT 1)",
context: {options: {quoteIdentifiers: false}}
}, {
arguments: ['mySchema.myTable', {name: "foo';DROP TABLE mySchema.myTable;"}, {limit: 10}],
expectation: "DELETE FROM mySchema.myTable WHERE id IN (SELECT id FROM mySchema.myTable WHERE name='foo'';DROP TABLE mySchema.myTable;' LIMIT 10)",
context: {options: {quoteIdentifiers: false}}
}, {
arguments: ['myTable', {name: 'foo'}, {limit: null}],
expectation: "DELETE FROM myTable WHERE id IN (SELECT id FROM myTable WHERE name='foo')",
context: {options: {quoteIdentifiers: false}}
}
],
// Variants when quoteIdentifiers is false
{
arguments: ['User', ['username', 'isAdmin']],
expectation: 'CREATE INDEX user_username_is_admin ON User (username, isAdmin)',
context: {options: {quoteIdentifiers: false}}
}, {
arguments: [
'User', [
{ attribute: 'username', length: 10, order: 'ASC'},
'isAdmin'
]
],
expectation: "CREATE INDEX user_username_is_admin ON User (username(10) ASC, isAdmin)",
context: {options: {quoteIdentifiers: false}}
}, {
arguments: [
'User', ['username', 'isAdmin'], { indicesType: 'FULLTEXT', indexName: 'bar'}
],
expectation: "CREATE FULLTEXT INDEX bar ON User (username, isAdmin)",
context: {options: {quoteIdentifiers: false}}
}, {
arguments: ['mySchema.User', ['username', 'isAdmin']],
expectation: 'CREATE INDEX user_username_is_admin ON mySchema.User (username, isAdmin)',
context: {options: {quoteIdentifiers: false}}
}
],
addIndexQuery: [
{
arguments: ['User', ['username', 'isAdmin']],
expectation: 'CREATE INDEX \"user_username_is_admin\" ON \"User\" (\"username\", \"isAdmin\")'
}, {
arguments: [
'User', [
{ attribute: 'username', length: 10, order: 'ASC'},
'isAdmin'
]
],
expectation: "CREATE INDEX \"user_username_is_admin\" ON \"User\" (\"username\"(10) ASC, \"isAdmin\")"
}, {
arguments: [
'User', ['username', 'isAdmin'], { indicesType: 'FULLTEXT', indexName: 'bar'}
],
expectation: "CREATE FULLTEXT INDEX \"bar\" ON \"User\" (\"username\", \"isAdmin\")"
}, {
arguments: ['mySchema.User', ['username', 'isAdmin']],
expectation: 'CREATE INDEX \"user_username_is_admin\" ON \"mySchema\".\"User\" (\"username\", \"isAdmin\")'
},
// FIXME: not implemented
//showIndexQuery: [
// {
// arguments: ['User'],
// expectation: 'SHOW INDEX FROM \"User\"'
// }, {
// arguments: ['User', { database: 'sequelize' }],
// expectation: "SHOW INDEX FROM \"User\" FROM \"sequelize\""
// }
//],
// Variants when quoteIdentifiers is false
{
arguments: ['User', ['username', 'isAdmin']],
expectation: 'CREATE INDEX user_username_is_admin ON User (username, isAdmin)',
context: {options: {quoteIdentifiers: false}}
}, {
arguments: [
'User', [
{ attribute: 'username', length: 10, order: 'ASC'},
'isAdmin'
]
],
expectation: "CREATE INDEX user_username_is_admin ON User (username(10) ASC, isAdmin)",
context: {options: {quoteIdentifiers: false}}
}, {
arguments: [
'User', ['username', 'isAdmin'], { indicesType: 'FULLTEXT', indexName: 'bar'}
],
expectation: "CREATE FULLTEXT INDEX bar ON User (username, isAdmin)",
context: {options: {quoteIdentifiers: false}}
}, {
arguments: ['mySchema.User', ['username', 'isAdmin']],
expectation: 'CREATE INDEX user_username_is_admin ON mySchema.User (username, isAdmin)',
context: {options: {quoteIdentifiers: false}}
}
],
removeIndexQuery: [
{
arguments: ['User', 'user_foo_bar'],
expectation: "DROP INDEX IF EXISTS \"user_foo_bar\""
}, {
arguments: ['User', ['foo', 'bar']],
expectation: "DROP INDEX IF EXISTS \"user_foo_bar\""
}, {
arguments: ['User', 'mySchema.user_foo_bar'],
expectation: "DROP INDEX IF EXISTS \"mySchema\".\"user_foo_bar\""
},
// FIXME: not implemented
//showIndexQuery: [
// {
// arguments: ['User'],
// expectation: 'SHOW INDEX FROM \"User\"'
// }, {
// arguments: ['User', { database: 'sequelize' }],
// expectation: "SHOW INDEX FROM \"User\" FROM \"sequelize\""
// }
//],
// Variants when quoteIdentifiers is false
{
arguments: ['User', 'user_foo_bar'],
expectation: "DROP INDEX IF EXISTS user_foo_bar",
context: {options: {quoteIdentifiers: false}}
}, {
arguments: ['User', ['foo', 'bar']],
expectation: "DROP INDEX IF EXISTS user_foo_bar",
context: {options: {quoteIdentifiers: false}}
}, {
arguments: ['User', 'mySchema.user_foo_bar'],
expectation: "DROP INDEX IF EXISTS mySchema.user_foo_bar",
context: {options: {quoteIdentifiers: false}}
}
],
removeIndexQuery: [
{
arguments: ['User', 'user_foo_bar'],
expectation: "DROP INDEX IF EXISTS \"user_foo_bar\""
}, {
arguments: ['User', ['foo', 'bar']],
expectation: "DROP INDEX IF EXISTS \"user_foo_bar\""
}, {
arguments: ['User', 'mySchema.user_foo_bar'],
expectation: "DROP INDEX IF EXISTS \"mySchema\".\"user_foo_bar\""
},
hashToWhereConditions: [
{
arguments: [{ id: [1,2,3] }],
expectation: "\"id\" IN (1,2,3)"
},
{
arguments: [{ id: [] }],
expectation: "\"id\" IN (NULL)"
},
// Variants when quoteIdentifiers is false
{
arguments: ['User', 'user_foo_bar'],
expectation: "DROP INDEX IF EXISTS user_foo_bar",
context: {options: {quoteIdentifiers: false}}
}, {
arguments: ['User', ['foo', 'bar']],
expectation: "DROP INDEX IF EXISTS user_foo_bar",
context: {options: {quoteIdentifiers: false}}
}, {
arguments: ['User', 'mySchema.user_foo_bar'],
expectation: "DROP INDEX IF EXISTS mySchema.user_foo_bar",
context: {options: {quoteIdentifiers: false}}
}
],
// Variants when quoteIdentifiers is false
{
arguments: [{ id: [1,2,3] }],
expectation: "id IN (1,2,3)",
context: {options: {quoteIdentifiers: false}}
},
{
arguments: [{ id: [] }],
expectation: "id IN (NULL)",
context: {options: {quoteIdentifiers: false}}
},
]
}
hashToWhereConditions: [
{
arguments: [{ id: [1,2,3] }],
expectation: "\"id\" IN (1,2,3)"
},
{
arguments: [{ id: [] }],
expectation: "\"id\" IN (NULL)"
},
Sequelize.Utils._.each(suites, function(tests, suiteTitle) {
describe(suiteTitle, function() {
tests.forEach(function(test) {
var title = test.title || 'Postgres correctly returns ' + test.expectation + ' for ' + util.inspect(test.arguments)
it(title, function() {
// Options would normally be set by the query interface that instantiates the query-generator, but here we specify it explicitly
var context = test.context || {options: {}};
QueryGenerator.options = context.options
var conditions = QueryGenerator[suiteTitle].apply(QueryGenerator, test.arguments)
// Variants when quoteIdentifiers is false
{
arguments: [{ id: [1,2,3] }],
expectation: "id IN (1,2,3)",
context: {options: {quoteIdentifiers: false}}
},
{
arguments: [{ id: [] }],
expectation: "id IN (NULL)",
context: {options: {quoteIdentifiers: false}}
},
]
}
expect(conditions).toEqual(test.expectation)
Helpers.Sequelize.Utils._.each(suites, function(tests, suiteTitle) {
describe(suiteTitle, function() {
tests.forEach(function(test) {
var title = test.title || 'Postgres correctly returns ' + test.expectation + ' for ' + util.inspect(test.arguments)
it(title, function(done) {
// Options would normally be set by the query interface that instantiates the query-generator, but here we specify it explicitly
var context = test.context || {options: {}};
QueryGenerator.options = context.options
var conditions = QueryGenerator[suiteTitle].apply(QueryGenerator, test.arguments)
expect(conditions).toEqual(test.expectation)
done()
})
})
})
})
})
})
}
\ No newline at end of file
if(typeof require === 'function') {
const buster = require("buster")
, Helpers = require('./buster-helpers')
, config = require(__dirname + "/config/config")
, dialect = Helpers.getTestDialect()
, moment = require('moment')
}
......@@ -16,6 +17,7 @@ var qq = function(str) {
}
buster.spec.expose()
buster.timeout = 1000
describe(Helpers.getTestDialectTeaser("Sequelize"), function() {
before(function(done) {
......@@ -26,6 +28,23 @@ describe(Helpers.getTestDialectTeaser("Sequelize"), function() {
})
})
describe('constructor', function() {
it('should pass the global options correctly', function(done) {
var sequelize = Helpers.createSequelizeInstance({ logging: false, define: { underscored:true } })
, DAO = sequelize.define('dao', {name: Helpers.Sequelize.STRING})
expect(DAO.options.underscored).toBeTruthy()
done()
})
it('should correctly set the host and the port', function(done) {
var sequelize = Helpers.createSequelizeInstance({ host: '127.0.0.1', port: 1234 })
expect(sequelize.config.port).toEqual(1234)
expect(sequelize.config.host).toEqual('127.0.0.1')
done()
})
})
describe('isDefined', function() {
it("returns false if the dao wasn't defined before", function() {
expect(this.sequelize.isDefined('Project')).toBeFalse()
......@@ -177,6 +196,113 @@ describe(Helpers.getTestDialectTeaser("Sequelize"), function() {
})
describe('define', function() {
it("adds a new dao to the dao manager", function(done) {
expect(this.sequelize.daoFactoryManager.all.length).toEqual(0)
this.sequelize.define('foo', { title: Helpers.Sequelize.STRING })
expect(this.sequelize.daoFactoryManager.all.length).toEqual(1)
done()
})
it("overwrites global options", function(done) {
var sequelize = Helpers.createSequelizeInstance({ define: { collate: 'utf8_general_ci' } })
var DAO = sequelize.define('foo', {bar: Helpers.Sequelize.STRING}, {collate: 'utf8_bin'})
expect(DAO.options.collate).toEqual('utf8_bin')
done()
})
it("inherits global collate option", function(done) {
var sequelize = Helpers.createSequelizeInstance({ define: { collate: 'utf8_general_ci' } })
var DAO = sequelize.define('foo', {bar: Helpers.Sequelize.STRING})
expect(DAO.options.collate).toEqual('utf8_general_ci')
done()
})
it("inherits global classMethods and instanceMethods", function(done) {
var sequelize = Helpers.createSequelizeInstance({
define: {
classMethods : { globalClassMethod : function() {} },
instanceMethods : { globalInstanceMethod : function() {} }
}
})
var DAO = sequelize.define('foo', {bar: Helpers.Sequelize.STRING}, {
classMethods : { localClassMethod : function() {} }
})
expect(typeof DAO.options.classMethods.globalClassMethod).toEqual('function')
expect(typeof DAO.options.classMethods.localClassMethod).toEqual('function')
expect(typeof DAO.options.instanceMethods.globalInstanceMethod).toEqual('function')
done()
})
it("uses the passed tableName", function(done) {
var self = this
, Photo = this.sequelize.define('Foto', { name: Helpers.Sequelize.STRING }, { tableName: 'photos' })
Photo.sync({ force: true }).success(function() {
self.sequelize.getQueryInterface().showAllTables().success(function(tableNames) {
expect(tableNames).toContain('photos')
done()
})
})
})
})
describe('sync', function() {
it("synchronizes all daos", function(done) {
var Project = this.sequelize.define('project' + config.rand(), { title: Helpers.Sequelize.STRING })
var Task = this.sequelize.define('task' + config.rand(), { title: Helpers.Sequelize.STRING })
this.sequelize.sync().success(function() {
Project.create({title: 'bla'}).success(function() {
Task.create({title: 'bla'}).success(function(task){
expect(task).toBeDefined()
expect(task.title).toEqual('bla')
done()
})
})
})
})
it('works with correct database credentials', function(done) {
var User = this.sequelize.define('User', { username: Helpers.Sequelize.STRING })
User.sync().success(function() {
expect(true).toBeTrue()
done()
})
})
it("fails with incorrect database credentials", function(done) {
var sequelize2 = Helpers.getSequelizeInstance('foo', 'bar', null, { logging: false })
, User2 = sequelize2.define('User', { name: Helpers.Sequelize.STRING, bio: Helpers.Sequelize.TEXT })
User2.sync().error(function(err) {
expect(err.message).toMatch(/.*Access\ denied.*/)
done()
})
})
})
describe('drop should work', function() {
it('correctly succeeds', function(done) {
var User = this.sequelize.define('Users', {username: Helpers.Sequelize.STRING })
User.sync({ force: true }).success(function() {
User.drop().success(function() {
expect(true).toBeTrue()
done()
})
})
})
})
describe('import', function() {
it("imports a dao definition from a file", function(done) {
var Project = this.sequelize.import(__dirname + "/assets/project")
expect(Project).toBeDefined()
done()
})
})
describe('define', function() {
[
{ type: Helpers.Sequelize.ENUM, values: ['scheduled', 'active', 'finished']},
Helpers.Sequelize.ENUM('scheduled', 'active', 'finished')
......@@ -241,6 +367,5 @@ describe(Helpers.getTestDialectTeaser("Sequelize"), function() {
})
})
})
})
/* jshint camelcase: false */
if(typeof require === 'function') {
const buster = require("buster")
, Helpers = require('../buster-helpers')
, dialect = Helpers.getTestDialect()
, dbFile = __dirname + '/test.sqlite'
, storages = [dbFile]
, DataTypes = require(__dirname + "/../../lib/data-types")
}
buster.spec.expose()
buster.testRunner.timeout = 1000
if (dialect === 'sqlite') {
describe('[SQLITE] DAOFactory', function() {
before(function(done) {
var self = this
Helpers.initTests({
dialect: 'sqlite',
beforeComplete: function(sequelize, DataTypes) {
self.sequelize = sequelize
self.User = sequelize.define('User', {
age: DataTypes.INTEGER,
name: DataTypes.STRING,
bio: DataTypes.TEXT
})
},
onComplete: function() {
self.User.sync({ force: true }).success(done)
}
})
})
storages.forEach(function(storage) {
describe('with storage "' + storage + '"', function() {
after(function(done) {
if (storage == dbFile) {
require("fs").unlink(__dirname + '/test.sqlite', done)
}
})
describe('create', function() {
it('creates a table entry', function(done) {
var self = this
this.User.create({ age: 21, name: 'John Wayne', bio: 'noot noot' }).success(function(user) {
expect(user.age).toEqual(21)
expect(user.name).toEqual('John Wayne')
expect(user.bio).toEqual('noot noot')
self.User.all().success(function(users) {
var usernames = users.map(function(user) {
return user.name
})
expect(usernames).toEqual(['John Wayne'])
done()
})
})
})
it('should allow the creation of an object with options as attribute', function(done) {
var Person = this.sequelize.define('Person', {
name: DataTypes.STRING,
options: DataTypes.TEXT
})
Person.sync({ force: true }).success(function() {
var options = JSON.stringify({ foo: 'bar', bar: 'foo' })
Person.create({
name: 'John Doe',
options: options
}).success(function(people) {
expect(people.options).toEqual(options)
done()
})
})
})
it('should allow the creation of an object with a boolean (true) as attribute', function(done) {
var Person = this.sequelize.define('Person', {
name: DataTypes.STRING,
has_swag: DataTypes.BOOLEAN
})
Person.sync({ force: true }).success(function() {
Person.create({
name: 'John Doe',
has_swag: true
}).success(function(people) {
expect(people.has_swag).toBeTruthy();
done()
})
})
})
it('should allow the creation of an object with a boolean (false) as attribute', function(done) {
var Person = this.sequelize.define('Person', {
name: DataTypes.STRING,
has_swag: DataTypes.BOOLEAN
})
Person.sync({ force: true }).success(function() {
Person.create({
name: 'John Doe',
has_swag: false
}).success(function(people) {
expect(people.has_swag).toBeFalsy();
done()
})
})
})
})
describe('.find', function() {
before(function(done) {
this.User.create({name: 'user', bio: 'footbar'}).success(done)
})
it("finds normal lookups", function(done) {
this.User.find({ where: { name:'user' } }).success(function(user) {
expect(user.name).toEqual('user')
done()
})
})
it("should make aliased attributes available", function(done) {
this.User.find({ where: { name:'user' }, attributes: ['id', ['name', 'username']] }).success(function(user) {
expect(user.username).toEqual('user')
done()
})
})
})
describe('.all', function() {
before(function(done) {
this.User.bulkCreate([
{name: 'user', bio: 'foobar'},
{name: 'user', bio: 'foobar'}
]).success(done)
})
it("should return all users", function(done) {
this.User.all().on('success', function(users) {
expect(users.length).toEqual(2)
done()
})
})
})
describe('.min', function() {
it("should return the min value", function(done) {
var self = this
, users = []
for (var i = 2; i < 5; i++) {
users[users.length] = {age: i}
}
this.User.bulkCreate(users).success(function() {
self.User.min('age').on('success', function(min) {
expect(min).toEqual(2)
done()
})
})
})
})
describe('.max', function() {
it("should return the max value", function(done) {
var self = this
, users = []
for (var i = 2; i <= 5; i++) {
users[users.length] = {age: i}
}
this.User.bulkCreate(users).success(function() {
self.User.max('age').on('success', function(min) {
expect(min).toEqual(5);
done()
})
})
})
})
})
})
})
}
......@@ -33,19 +33,14 @@ if (dialect === 'sqlite') {
this.User
.create({ username: 'user', createdAt: new Date(2011, 04, 04) })
.success(function(oldUser) {
self.User
.create({ username: 'new user' })
.success(function(newUser) {
self.User.findAll({
where: ['createdAt > ?', new Date(2012, 01, 01)]
}).success(function(users) {
expect(users.length).toEqual(1)
done()
})
self.User.create({ username: 'new user' }).success(function(newUser) {
self.User.findAll({
where: ['createdAt > ?', new Date(2012, 01, 01)]
}).success(function(users) {
expect(users.length).toEqual(1)
done()
})
})
.error(function(err) {
console.log(err)
})
})
})
})
......
var Sequelize = require("../../index")
, sequelize = new Sequelize(null, null, null, { dialect: 'sqlite' })
, Helpers = new (require("../config/helpers"))(sequelize)
, QueryGenerator = require("../../lib/dialects/sqlite/query-generator")
, util = require("util");
if(typeof require === 'function') {
const buster = require("buster")
, Helpers = require('../buster-helpers')
, dialect = Helpers.getTestDialect()
, QueryGenerator = require("../../lib/dialects/sqlite/query-generator")
, util = require("util");
}
describe('QueryGenerator', function() {
beforeEach(function() { Helpers.sync() })
afterEach(function() { Helpers.drop() })
buster.spec.expose()
buster.testRunner.timeout = 1000
var suites = {
if (dialect === 'sqlite') {
describe('[SQLITE] QueryGenerator', function() {
before(function(done) {
var self = this
attributesToSQL: [
{
arguments: [{id: 'INTEGER'}],
expectation: {id: 'INTEGER'}
},
{
arguments: [{id: 'INTEGER', foo: 'VARCHAR(255)'}],
expectation: {id: 'INTEGER', foo: 'VARCHAR(255)'}
},
{
arguments: [{id: {type: 'INTEGER'}}],
expectation: {id: 'INTEGER'}
},
{
arguments: [{id: {type: 'INTEGER', allowNull: false}}],
expectation: {id: 'INTEGER NOT NULL'}
},
{
arguments: [{id: {type: 'INTEGER', allowNull: true}}],
expectation: {id: 'INTEGER'}
},
{
arguments: [{id: {type: 'INTEGER', primaryKey: true, autoIncrement: true}}],
expectation: {id: 'INTEGER PRIMARY KEY AUTOINCREMENT'}
},
{
arguments: [{id: {type: 'INTEGER', defaultValue: 0}}],
expectation: {id: 'INTEGER DEFAULT 0'}
},
{
arguments: [{id: {type: 'INTEGER', unique: true}}],
expectation: {id: 'INTEGER UNIQUE'}
},
{
arguments: [{id: {type: 'INTEGER', references: 'Bar'}}],
expectation: {id: 'INTEGER REFERENCES `Bar` (`id`)'}
},
{
arguments: [{id: {type: 'INTEGER', references: 'Bar', referencesKey: 'pk'}}],
expectation: {id: 'INTEGER REFERENCES `Bar` (`pk`)'}
},
{
arguments: [{id: {type: 'INTEGER', references: 'Bar', onDelete: 'CASCADE'}}],
expectation: {id: 'INTEGER REFERENCES `Bar` (`id`) ON DELETE CASCADE'}
},
{
arguments: [{id: {type: 'INTEGER', references: 'Bar', onUpdate: 'RESTRICT'}}],
expectation: {id: 'INTEGER REFERENCES `Bar` (`id`) ON UPDATE RESTRICT'}
},
{
arguments: [{id: {type: 'INTEGER', allowNull: false, defaultValue: 1, references: 'Bar', onDelete: 'CASCADE', onUpdate: 'RESTRICT'}}],
expectation: {id: 'INTEGER NOT NULL DEFAULT 1 REFERENCES `Bar` (`id`) ON DELETE CASCADE ON UPDATE RESTRICT'}
},
],
Helpers.initTests({
dialect: 'sqlite',
beforeComplete: function(sequelize, DataTypes) {
self.sequelize = sequelize
createTableQuery: [
{
arguments: ['myTable', {title: 'VARCHAR(255)', name: 'VARCHAR(255)'}],
expectation: "CREATE TABLE IF NOT EXISTS `myTable` (`title` VARCHAR(255), `name` VARCHAR(255));"
},
{
arguments: ['myTable', {title: 'ENUM("A", "B", "C")', name: 'VARCHAR(255)'}],
expectation: "CREATE TABLE IF NOT EXISTS `myTable` (`title` ENUM(\"A\", \"B\", \"C\"), `name` VARCHAR(255));"
},
{
arguments: ['myTable', {title: 'VARCHAR(255)', name: 'VARCHAR(255)', id: 'INTEGER PRIMARY KEY'}],
expectation: "CREATE TABLE IF NOT EXISTS `myTable` (`title` VARCHAR(255), `name` VARCHAR(255), `id` INTEGER PRIMARY KEY);"
},
{
arguments: ['myTable', {title: 'VARCHAR(255)', name: 'VARCHAR(255)', otherId: 'INTEGER REFERENCES `otherTable` (`id`) ON DELETE CASCADE ON UPDATE NO ACTION'}],
expectation: "CREATE TABLE IF NOT EXISTS `myTable` (`title` VARCHAR(255), `name` VARCHAR(255), `otherId` INTEGER REFERENCES `otherTable` (`id`) ON DELETE CASCADE ON UPDATE NO ACTION);"
}
],
self.User = sequelize.define('User', {
username: DataTypes.STRING
})
},
onComplete: function() {
self.User.sync({ force: true }).success(done)
}
})
})
var suites = {
attributesToSQL: [
{
arguments: [{id: 'INTEGER'}],
expectation: {id: 'INTEGER'}
},
{
arguments: [{id: 'INTEGER', foo: 'VARCHAR(255)'}],
expectation: {id: 'INTEGER', foo: 'VARCHAR(255)'}
},
{
arguments: [{id: {type: 'INTEGER'}}],
expectation: {id: 'INTEGER'}
},
{
arguments: [{id: {type: 'INTEGER', allowNull: false}}],
expectation: {id: 'INTEGER NOT NULL'}
},
{
arguments: [{id: {type: 'INTEGER', allowNull: true}}],
expectation: {id: 'INTEGER'}
},
{
arguments: [{id: {type: 'INTEGER', primaryKey: true, autoIncrement: true}}],
expectation: {id: 'INTEGER PRIMARY KEY AUTOINCREMENT'}
},
{
arguments: [{id: {type: 'INTEGER', defaultValue: 0}}],
expectation: {id: 'INTEGER DEFAULT 0'}
},
{
arguments: [{id: {type: 'INTEGER', unique: true}}],
expectation: {id: 'INTEGER UNIQUE'}
},
{
arguments: [{id: {type: 'INTEGER', references: 'Bar'}}],
expectation: {id: 'INTEGER REFERENCES `Bar` (`id`)'}
},
{
arguments: [{id: {type: 'INTEGER', references: 'Bar', referencesKey: 'pk'}}],
expectation: {id: 'INTEGER REFERENCES `Bar` (`pk`)'}
},
{
arguments: [{id: {type: 'INTEGER', references: 'Bar', onDelete: 'CASCADE'}}],
expectation: {id: 'INTEGER REFERENCES `Bar` (`id`) ON DELETE CASCADE'}
},
{
arguments: [{id: {type: 'INTEGER', references: 'Bar', onUpdate: 'RESTRICT'}}],
expectation: {id: 'INTEGER REFERENCES `Bar` (`id`) ON UPDATE RESTRICT'}
},
{
arguments: [{id: {type: 'INTEGER', allowNull: false, defaultValue: 1, references: 'Bar', onDelete: 'CASCADE', onUpdate: 'RESTRICT'}}],
expectation: {id: 'INTEGER NOT NULL DEFAULT 1 REFERENCES `Bar` (`id`) ON DELETE CASCADE ON UPDATE RESTRICT'}
},
],
createTableQuery: [
{
arguments: ['myTable', {title: 'VARCHAR(255)', name: 'VARCHAR(255)'}],
expectation: "CREATE TABLE IF NOT EXISTS `myTable` (`title` VARCHAR(255), `name` VARCHAR(255));"
},
{
arguments: ['myTable', {title: 'ENUM("A", "B", "C")', name: 'VARCHAR(255)'}],
expectation: "CREATE TABLE IF NOT EXISTS `myTable` (`title` ENUM(\"A\", \"B\", \"C\"), `name` VARCHAR(255));"
},
{
arguments: ['myTable', {title: 'VARCHAR(255)', name: 'VARCHAR(255)', id: 'INTEGER PRIMARY KEY'}],
expectation: "CREATE TABLE IF NOT EXISTS `myTable` (`title` VARCHAR(255), `name` VARCHAR(255), `id` INTEGER PRIMARY KEY);"
},
{
arguments: ['myTable', {title: 'VARCHAR(255)', name: 'VARCHAR(255)', otherId: 'INTEGER REFERENCES `otherTable` (`id`) ON DELETE CASCADE ON UPDATE NO ACTION'}],
expectation: "CREATE TABLE IF NOT EXISTS `myTable` (`title` VARCHAR(255), `name` VARCHAR(255), `otherId` INTEGER REFERENCES `otherTable` (`id`) ON DELETE CASCADE ON UPDATE NO ACTION);"
}
],
insertQuery: [
{
arguments: ['myTable', { name: 'foo' }],
expectation: "INSERT INTO `myTable` (`name`) VALUES ('foo');"
}, {
arguments: ['myTable', { name: "'bar'" }],
expectation: "INSERT INTO `myTable` (`name`) VALUES ('''bar''');"
}, {
arguments: ['myTable', { name: "bar", value: null }],
expectation: "INSERT INTO `myTable` (`name`,`value`) VALUES ('bar',NULL);"
}, {
arguments: ['myTable', { name: "bar", value: undefined }],
expectation: "INSERT INTO `myTable` (`name`,`value`) VALUES ('bar',NULL);"
}, {
arguments: ['myTable', { name: "foo", value: true }],
expectation: "INSERT INTO `myTable` (`name`,`value`) VALUES ('foo',1);"
}, {
arguments: ['myTable', { name: "foo", value: false }],
expectation: "INSERT INTO `myTable` (`name`,`value`) VALUES ('foo',0);"
}, {
arguments: ['myTable', {name: 'foo', foo: 1, nullValue: null}],
expectation: "INSERT INTO `myTable` (`name`,`foo`,`nullValue`) VALUES ('foo',1,NULL);"
}, {
arguments: ['myTable', {name: 'foo', foo: 1, nullValue: null}],
expectation: "INSERT INTO `myTable` (`name`,`foo`,`nullValue`) VALUES ('foo',1,NULL);",
context: {options: {omitNull: false}}
}, {
arguments: ['myTable', {name: 'foo', foo: 1, nullValue: null}],
expectation: "INSERT INTO `myTable` (`name`,`foo`) VALUES ('foo',1);",
context: {options: {omitNull: true}}
}, {
arguments: ['myTable', {name: 'foo', foo: 1, nullValue: undefined}],
expectation: "INSERT INTO `myTable` (`name`,`foo`) VALUES ('foo',1);",
context: {options: {omitNull: true}}
}
],
insertQuery: [
{
arguments: ['myTable', { name: 'foo' }],
expectation: "INSERT INTO `myTable` (`name`) VALUES ('foo');"
}, {
arguments: ['myTable', { name: "'bar'" }],
expectation: "INSERT INTO `myTable` (`name`) VALUES ('''bar''');"
}, {
arguments: ['myTable', { name: "bar", value: null }],
expectation: "INSERT INTO `myTable` (`name`,`value`) VALUES ('bar',NULL);"
}, {
arguments: ['myTable', { name: "bar", value: undefined }],
expectation: "INSERT INTO `myTable` (`name`,`value`) VALUES ('bar',NULL);"
}, {
arguments: ['myTable', { name: "foo", value: true }],
expectation: "INSERT INTO `myTable` (`name`,`value`) VALUES ('foo',1);"
}, {
arguments: ['myTable', { name: "foo", value: false }],
expectation: "INSERT INTO `myTable` (`name`,`value`) VALUES ('foo',0);"
}, {
arguments: ['myTable', {name: 'foo', foo: 1, nullValue: null}],
expectation: "INSERT INTO `myTable` (`name`,`foo`,`nullValue`) VALUES ('foo',1,NULL);"
}, {
arguments: ['myTable', {name: 'foo', foo: 1, nullValue: null}],
expectation: "INSERT INTO `myTable` (`name`,`foo`,`nullValue`) VALUES ('foo',1,NULL);",
context: {options: {omitNull: false}}
}, {
arguments: ['myTable', {name: 'foo', foo: 1, nullValue: null}],
expectation: "INSERT INTO `myTable` (`name`,`foo`) VALUES ('foo',1);",
context: {options: {omitNull: true}}
}, {
arguments: ['myTable', {name: 'foo', foo: 1, nullValue: undefined}],
expectation: "INSERT INTO `myTable` (`name`,`foo`) VALUES ('foo',1);",
context: {options: {omitNull: true}}
}
],
bulkInsertQuery: [
{
arguments: ['myTable', [{name: 'foo'}, {name: 'bar'}]],
expectation: "INSERT INTO `myTable` (`name`) VALUES ('foo'),('bar');"
}, {
arguments: ['myTable', [{name: "'bar'"}, {name: 'foo'}]],
expectation: "INSERT INTO `myTable` (`name`) VALUES ('''bar'''),('foo');"
}, {
arguments: ['myTable', [{name: "bar", value: null}, {name: 'foo', value: 1}]],
expectation: "INSERT INTO `myTable` (`name`,`value`) VALUES ('bar',NULL),('foo',1);"
}, {
arguments: ['myTable', [{name: "bar", value: undefined}, {name: 'bar', value: 2}]],
expectation: "INSERT INTO `myTable` (`name`,`value`) VALUES ('bar',NULL),('bar',2);"
}, {
arguments: ['myTable', [{name: "foo", value: true}, {name: 'bar', value: false}]],
expectation: "INSERT INTO `myTable` (`name`,`value`) VALUES ('foo',1),('bar',0);"
}, {
arguments: ['myTable', [{name: "foo", value: false}, {name: 'bar', value: false}]],
expectation: "INSERT INTO `myTable` (`name`,`value`) VALUES ('foo',0),('bar',0);"
}, {
arguments: ['myTable', [{name: 'foo', foo: 1, nullValue: null}, {name: 'bar', foo: 2, nullValue: null}]],
expectation: "INSERT INTO `myTable` (`name`,`foo`,`nullValue`) VALUES ('foo',1,NULL),('bar',2,NULL);"
}, {
arguments: ['myTable', [{name: 'foo', foo: 1, nullValue: null}, {name: 'bar', foo: 2, nullValue: null}]],
expectation: "INSERT INTO `myTable` (`name`,`foo`,`nullValue`) VALUES ('foo',1,NULL),('bar',2,NULL);",
context: {options: {omitNull: false}}
}, {
arguments: ['myTable', [{name: 'foo', foo: 1, nullValue: null}, {name: 'bar', foo: 2, nullValue: null}]],
expectation: "INSERT INTO `myTable` (`name`,`foo`,`nullValue`) VALUES ('foo',1,NULL),('bar',2,NULL);",
context: {options: {omitNull: true}} // Note: We don't honour this because it makes little sense when some rows may have nulls and others not
}, {
arguments: ['myTable', [{name: 'foo', foo: 1, nullValue: null}, {name: 'bar', foo: 2, nullValue: null}]],
expectation: "INSERT INTO `myTable` (`name`,`foo`,`nullValue`) VALUES ('foo',1,NULL),('bar',2,NULL);",
context: {options: {omitNull: true}} // Note: As above
}
],
bulkInsertQuery: [
{
arguments: ['myTable', [{name: 'foo'}, {name: 'bar'}]],
expectation: "INSERT INTO `myTable` (`name`) VALUES ('foo'),('bar');"
}, {
arguments: ['myTable', [{name: "'bar'"}, {name: 'foo'}]],
expectation: "INSERT INTO `myTable` (`name`) VALUES ('''bar'''),('foo');"
}, {
arguments: ['myTable', [{name: "bar", value: null}, {name: 'foo', value: 1}]],
expectation: "INSERT INTO `myTable` (`name`,`value`) VALUES ('bar',NULL),('foo',1);"
}, {
arguments: ['myTable', [{name: "bar", value: undefined}, {name: 'bar', value: 2}]],
expectation: "INSERT INTO `myTable` (`name`,`value`) VALUES ('bar',NULL),('bar',2);"
}, {
arguments: ['myTable', [{name: "foo", value: true}, {name: 'bar', value: false}]],
expectation: "INSERT INTO `myTable` (`name`,`value`) VALUES ('foo',1),('bar',0);"
}, {
arguments: ['myTable', [{name: "foo", value: false}, {name: 'bar', value: false}]],
expectation: "INSERT INTO `myTable` (`name`,`value`) VALUES ('foo',0),('bar',0);"
}, {
arguments: ['myTable', [{name: 'foo', foo: 1, nullValue: null}, {name: 'bar', foo: 2, nullValue: null}]],
expectation: "INSERT INTO `myTable` (`name`,`foo`,`nullValue`) VALUES ('foo',1,NULL),('bar',2,NULL);"
}, {
arguments: ['myTable', [{name: 'foo', foo: 1, nullValue: null}, {name: 'bar', foo: 2, nullValue: null}]],
expectation: "INSERT INTO `myTable` (`name`,`foo`,`nullValue`) VALUES ('foo',1,NULL),('bar',2,NULL);",
context: {options: {omitNull: false}}
}, {
arguments: ['myTable', [{name: 'foo', foo: 1, nullValue: null}, {name: 'bar', foo: 2, nullValue: null}]],
expectation: "INSERT INTO `myTable` (`name`,`foo`,`nullValue`) VALUES ('foo',1,NULL),('bar',2,NULL);",
context: {options: {omitNull: true}} // Note: We don't honour this because it makes little sense when some rows may have nulls and others not
}, {
arguments: ['myTable', [{name: 'foo', foo: 1, nullValue: null}, {name: 'bar', foo: 2, nullValue: null}]],
expectation: "INSERT INTO `myTable` (`name`,`foo`,`nullValue`) VALUES ('foo',1,NULL),('bar',2,NULL);",
context: {options: {omitNull: true}} // Note: As above
}
],
updateQuery: [
{
arguments: ['myTable', { name: 'foo' }, { id: 2 }],
expectation: "UPDATE `myTable` SET `name`='foo' WHERE `id`=2"
}, {
arguments: ['myTable', { name: "'bar'" }, { id: 2 }],
expectation: "UPDATE `myTable` SET `name`='''bar''' WHERE `id`=2"
}, {
arguments: ['myTable', { name: 'bar', value: null }, { id: 2 }],
expectation: "UPDATE `myTable` SET `name`='bar',`value`=NULL WHERE `id`=2"
}, {
arguments: ['myTable', { name: 'bar', value: undefined }, { id: 2 }],
expectation: "UPDATE `myTable` SET `name`='bar',`value`=NULL WHERE `id`=2"
}, {
arguments: ['myTable', { flag: true }, { id: 2 }],
expectation: "UPDATE `myTable` SET `flag`=1 WHERE `id`=2"
}, {
arguments: ['myTable', { flag: false }, { id: 2 }],
expectation: "UPDATE `myTable` SET `flag`=0 WHERE `id`=2"
}, {
arguments: ['myTable', {bar: 2, nullValue: null}, {name: 'foo'}],
expectation: "UPDATE `myTable` SET `bar`=2,`nullValue`=NULL WHERE `name`='foo'"
}, {
arguments: ['myTable', {bar: 2, nullValue: null}, {name: 'foo'}],
expectation: "UPDATE `myTable` SET `bar`=2,`nullValue`=NULL WHERE `name`='foo'",
context: {options: {omitNull: false}}
}, {
arguments: ['myTable', {bar: 2, nullValue: null}, {name: 'foo'}],
expectation: "UPDATE `myTable` SET `bar`=2 WHERE `name`='foo'",
context: {options: {omitNull: true}}
}
],
updateQuery: [
{
arguments: ['myTable', { name: 'foo' }, { id: 2 }],
expectation: "UPDATE `myTable` SET `name`='foo' WHERE `id`=2"
}, {
arguments: ['myTable', { name: "'bar'" }, { id: 2 }],
expectation: "UPDATE `myTable` SET `name`='''bar''' WHERE `id`=2"
}, {
arguments: ['myTable', { name: 'bar', value: null }, { id: 2 }],
expectation: "UPDATE `myTable` SET `name`='bar',`value`=NULL WHERE `id`=2"
}, {
arguments: ['myTable', { name: 'bar', value: undefined }, { id: 2 }],
expectation: "UPDATE `myTable` SET `name`='bar',`value`=NULL WHERE `id`=2"
}, {
arguments: ['myTable', { flag: true }, { id: 2 }],
expectation: "UPDATE `myTable` SET `flag`=1 WHERE `id`=2"
}, {
arguments: ['myTable', { flag: false }, { id: 2 }],
expectation: "UPDATE `myTable` SET `flag`=0 WHERE `id`=2"
}, {
arguments: ['myTable', {bar: 2, nullValue: null}, {name: 'foo'}],
expectation: "UPDATE `myTable` SET `bar`=2,`nullValue`=NULL WHERE `name`='foo'"
}, {
arguments: ['myTable', {bar: 2, nullValue: null}, {name: 'foo'}],
expectation: "UPDATE `myTable` SET `bar`=2,`nullValue`=NULL WHERE `name`='foo'",
context: {options: {omitNull: false}}
}, {
arguments: ['myTable', {bar: 2, nullValue: null}, {name: 'foo'}],
expectation: "UPDATE `myTable` SET `bar`=2 WHERE `name`='foo'",
context: {options: {omitNull: true}}
}
],
deleteQuery: [
{
arguments: ['myTable', {name: 'foo'}],
expectation: "DELETE FROM `myTable` WHERE `name`='foo'"
}, {
arguments: ['myTable', 1],
expectation: "DELETE FROM `myTable` WHERE `id`=1"
}, {
arguments: ['myTable', 1, {truncate: true}],
expectation: "DELETE FROM `myTable` WHERE `id`=1"
}, {
arguments: ['myTable', 1, {limit: 10}],
expectation: "DELETE FROM `myTable` WHERE `id`=1"
}, {
arguments: ['myTable', {name: "foo';DROP TABLE myTable;"}, {limit: 10}],
expectation: "DELETE FROM `myTable` WHERE `name`='foo'';DROP TABLE myTable;'"
}, {
arguments: ['myTable', {name: 'foo'}, {limit: null}],
expectation: "DELETE FROM `myTable` WHERE `name`='foo'"
}
]
}
deleteQuery: [
{
arguments: ['myTable', {name: 'foo'}],
expectation: "DELETE FROM `myTable` WHERE `name`='foo'"
}, {
arguments: ['myTable', 1],
expectation: "DELETE FROM `myTable` WHERE `id`=1"
}, {
arguments: ['myTable', 1, {truncate: true}],
expectation: "DELETE FROM `myTable` WHERE `id`=1"
}, {
arguments: ['myTable', 1, {limit: 10}],
expectation: "DELETE FROM `myTable` WHERE `id`=1"
}, {
arguments: ['myTable', {name: "foo';DROP TABLE myTable;"}, {limit: 10}],
expectation: "DELETE FROM `myTable` WHERE `name`='foo'';DROP TABLE myTable;'"
}, {
arguments: ['myTable', {name: 'foo'}, {limit: null}],
expectation: "DELETE FROM `myTable` WHERE `name`='foo'"
}
]
};
Sequelize.Utils._.each(suites, function(tests, suiteTitle) {
describe(suiteTitle, function() {
tests.forEach(function(test) {
var title = test.title || 'SQLite correctly returns ' + test.expectation + ' for ' + util.inspect(test.arguments)
it(title, function() {
// Options would normally be set by the query interface that instantiates the query-generator, but here we specify it explicitly
var context = test.context || {options: {}};
QueryGenerator.options = context.options
var conditions = QueryGenerator[suiteTitle].apply(QueryGenerator, test.arguments)
expect(conditions).toEqual(test.expectation)
Helpers.Sequelize.Utils._.each(suites, function(tests, suiteTitle) {
describe(suiteTitle, function() {
tests.forEach(function(test) {
var title = test.title || 'SQLite correctly returns ' + test.expectation + ' for ' + util.inspect(test.arguments)
it(title, function(done) {
// Options would normally be set by the query interface that instantiates the query-generator, but here we specify it explicitly
var context = test.context || {options: {}};
QueryGenerator.options = context.options
var conditions = QueryGenerator[suiteTitle].apply(QueryGenerator, test.arguments)
expect(conditions).toEqual(test.expectation)
done()
})
})
})
})
})
});
}
var Utils = require('../lib/utils')
var buster = require("buster")
, Utils = require('../lib/utils')
, Helpers = require('./buster-helpers')
describe('Utils', function() {
buster.spec.expose()
buster.testRunner.timeout = 1000
describe(Helpers.getTestDialectTeaser("Utils"), function() {
describe('removeCommentsFromFunctionString', function() {
it("removes line comments at the start of a line", function() {
it("removes line comments at the start of a line", function(done) {
var functionWithLineComments = function() {
// noot noot
}
var result = Utils.removeCommentsFromFunctionString(functionWithLineComments.toString())
expect(result).toNotMatch(/.*noot.*/)
expect(result).not.toMatch(/.*noot.*/)
done()
})
it("removes lines comments in the middle of a line", function() {
it("removes lines comments in the middle of a line", function(done) {
var functionWithLineComments = function() {
alert(1) // noot noot
}
var result = Utils.removeCommentsFromFunctionString(functionWithLineComments.toString())
expect(result).toNotMatch(/.*noot.*/)
expect(result).not.toMatch(/.*noot.*/)
done()
})
it("removes range comments", function() {
it("removes range comments", function(done) {
var s = function() {
alert(1) /*
noot noot
......@@ -31,97 +38,117 @@ describe('Utils', function() {
}.toString()
var result = Utils.removeCommentsFromFunctionString(s)
expect(result).toNotMatch(/.*noot.*/)
expect(result).toNotMatch(/.*foo.*/)
expect(result).not.toMatch(/.*noot.*/)
expect(result).not.toMatch(/.*foo.*/)
expect(result).toMatch(/.*alert\(2\).*/)
done()
})
})
describe('argsArePrimaryKeys', function() {
it("doesn't detect primary keys if primareyKeys and values have different lengths", function() {
it("doesn't detect primary keys if primareyKeys and values have different lengths", function(done) {
expect(Utils.argsArePrimaryKeys([1,2,3], [1])).toBeFalsy()
done()
})
it("doesn't detect primary keys if primary keys are hashes or arrays", function() {
it("doesn't detect primary keys if primary keys are hashes or arrays", function(done) {
expect(Utils.argsArePrimaryKeys([[]], [1])).toBeFalsy()
done()
})
it('detects primary keys if length is correct and data types are matching', function() {
it('detects primary keys if length is correct and data types are matching', function(done) {
expect(Utils.argsArePrimaryKeys([1,2,3], ["INTEGER", "INTEGER", "INTEGER"])).toBeTruthy()
done()
})
it("detects primary keys if primary keys are dates and lengths are matching", function() {
it("detects primary keys if primary keys are dates and lengths are matching", function(done) {
expect(Utils.argsArePrimaryKeys([new Date()], ['foo'])).toBeTruthy()
done()
})
})
describe('underscore', function() {
describe('underscoredIf', function() {
it('is defined', function() {
it('is defined', function(done) {
expect(Utils._.underscoredIf).toBeDefined()
done()
})
it('underscores if second param is true', function() {
it('underscores if second param is true', function(done) {
expect(Utils._.underscoredIf('fooBar', true)).toEqual('foo_bar')
done()
})
it("doesn't underscore if second param is false", function() {
it("doesn't underscore if second param is false", function(done) {
expect(Utils._.underscoredIf('fooBar', false)).toEqual('fooBar')
done()
})
})
describe('camelizeIf', function() {
it('is defined', function() {
it('is defined', function(done) {
expect(Utils._.camelizeIf).toBeDefined()
done()
})
it('camelizes if second param is true', function() {
it('camelizes if second param is true', function(done) {
expect(Utils._.camelizeIf('foo_bar', true)).toEqual('fooBar')
done()
})
it("doesn't camelize if second param is false", function() {
it("doesn't camelize if second param is false", function(done) {
expect(Utils._.underscoredIf('fooBar', true)).toEqual('foo_bar')
done()
})
})
})
describe('isHash', function() {
it('doesn\'t match arrays', function() {
expect(Utils.isHash([])).toBeFalsy();
});
it('doesn\'t match null', function() {
expect(Utils.isHash(null)).toBeFalsy();
});
it('matches plain objects', function() {
var values = {
'name': {
'first': 'Foo',
'last': 'Bar'
}
};
expect(Utils.isHash(values)).toBeTruthy();
});
it('matches plain objects with length property/key', function() {
it('doesn\'t match arrays', function(done) {
expect(Utils.isHash([])).toBeFalsy()
done()
})
it('doesn\'t match null', function(done) {
expect(Utils.isHash(null)).toBeFalsy()
done()
})
it('matches plain objects', function(done) {
var values = {
'name': {
'first': 'Foo',
'last': 'Bar'
},
'length': 1
};
expect(Utils.isHash(values)).toBeTruthy();
});
});
'name': {
'first': 'Foo',
'last': 'Bar'
}
}
expect(Utils.isHash(values)).toBeTruthy()
done()
})
it('matches plain objects with length property/key', function(done) {
var values = {
'name': {
'first': 'Foo',
'last': 'Bar'
},
'length': 1
}
expect(Utils.isHash(values)).toBeTruthy()
done()
})
})
describe('format', function() {
it('should format where clause correctly when the value is truthy', function() {
var where = ['foo = ?', 1];
expect(Utils.format(where)).toEqual('foo = 1');
});
it('should format where clause correctly when the value is falsy', function() {
var where = ['foo = ?', 0];
expect(Utils.format(where)).toEqual('foo = 0');
});
});
it('should format where clause correctly when the value is truthy', function(done) {
var where = ['foo = ?', 1]
expect(Utils.format(where)).toEqual('foo = 1')
done()
})
it('should format where clause correctly when the value is falsy', function(done) {
var where = ['foo = ?', 0]
expect(Utils.format(where)).toEqual('foo = 0')
done()
})
})
})
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!