juggling = require('loopback-datasource-juggler') Schema = juggling.Schema Text = Schema.Text DBNAME = 'myapp_test' DBUSER = 'strongloop' DBPASS = 'password' DBENGINE = 'mysql' dataSource = new Schema __dirname + '/..', database: '', username: DBUSER, password: DBPASS dataSource.log = (q) -> console.log q query = (sql, cb) -> dataSource.adapter.query sql, cb User = dataSource.define 'User', email: { type: String, null: false, index: true } name: String bio: Text password: String birthDate: Date pendingPeriod: Number createdByAdmin: Boolean , indexes: index1: columns: 'email, createdByAdmin' withBlankDatabase = (cb) -> db = dataSource.settings.database = DBNAME query 'DROP DATABASE IF EXISTS ' + db, (err) -> query 'CREATE DATABASE ' + db, (err) -> query 'USE '+ db, cb getFields = (model, cb) -> query 'SHOW FIELDS FROM ' + model, (err, res) -> if err cb err else fields = {} res.forEach (field) -> fields[field.Field] = field cb err, fields getIndexes = (model, cb) -> query 'SHOW INDEXES FROM ' + model, (err, res) -> if err console.log err cb err else indexes = {} # Note: this will only show the first key of compound keys res.forEach (index) -> indexes[index.Key_name] = index if parseInt(index.Seq_in_index, 10) == 1 cb err, indexes it = (name, testCases) -> module.exports[name] = testCases it 'should run migration', (test) -> withBlankDatabase (err) -> dataSource.automigrate -> getFields 'User', (err, fields) -> test.deepEqual fields, id: Field: 'id' Type: 'int(11)' Null: 'NO' Key: 'PRI' Default: null Extra: 'auto_increment' email: Field: 'email' Type: 'varchar(255)' Null: 'NO' Key: 'MUL' Default: null Extra: '' name: Field: 'name' Type: 'varchar(255)' Null: 'YES' Key: '' Default: null Extra: '' bio: Field: 'bio' Type: 'text' Null: 'YES' Key: '' Default: null Extra: '' password: Field: 'password' Type: 'varchar(255)' Null: 'YES' Key: '' Default: null Extra: '' birthDate: Field: 'birthDate' Type: 'datetime' Null: 'YES' Key: '' Default: null Extra: '' pendingPeriod: Field: 'pendingPeriod' Type: 'int(11)' Null: 'YES' Key: '' Default: null Extra: '' createdByAdmin: Field: 'createdByAdmin' Type: 'tinyint(1)' Null: 'YES' Key: '' Default: null Extra: '' # Once gain, getIdexes truncates multi-key indexes to the first member. Hence index1 is correct. getIndexes 'User', (err, fields) -> test.deepEqual fields, PRIMARY: Table: 'User' Non_unique: 0 Key_name: 'PRIMARY' Seq_in_index: 1 Column_name: 'id' Collation: 'A' Cardinality: 0 Sub_part: null Packed: null Null: '' Index_type: 'BTREE' Comment: '' Index_comment: '' email: Table: 'User' Non_unique: 1 Key_name: 'email' Seq_in_index: 1 Column_name: 'email' Collation: 'A' Cardinality: 0 Sub_part: null Packed: null Null: '' Index_type: 'BTREE' Comment: '' Index_comment: '' index1: Table: 'User' Non_unique: 1 Key_name: 'index1' Seq_in_index: 1 Column_name: 'email' Collation: 'A' Cardinality: 0 Sub_part: null Packed: null Null: '' Index_type: 'BTREE' Comment: '' Index_comment: '' test.done() it 'should autoupgrade', (test) -> userExists = (cb) -> query 'SELECT * FROM User', (err, res) -> cb(not err and res[0].email == 'test@example.com') User.create email: 'test@example.com', (err, user) -> test.ok not err userExists (yep) -> test.ok yep User.defineProperty 'email', type: String User.defineProperty 'name', type: String, limit: 50 User.defineProperty 'newProperty', type: Number User.defineProperty 'pendingPeriod', false dataSource.autoupdate (err) -> getFields 'User', (err, fields) -> # change nullable for email test.equal fields.email.Null, 'YES', 'Email is not null' # change type of name test.equal fields.name.Type, 'varchar(50)', 'Name is not varchar(50)' # add new column test.ok fields.newProperty, 'New column was not added' if fields.newProperty test.equal fields.newProperty.Type, 'int(11)', 'New column type is not int(11)' # drop column test.ok not fields.pendingPeriod, 'drop column' # user still exists userExists (yep) -> test.ok yep test.done() it 'should check actuality of dataSource', (test) -> # drop column User.dataSource.isActual (err, ok) -> test.ok ok, 'dataSource is actual' User.defineProperty 'email', false User.dataSource.isActual (err, ok) -> test.ok not ok, 'dataSource is not actual' test.done() it 'should add single-column index', (test) -> User.defineProperty 'email', type: String, index: { kind: 'FULLTEXT', type: 'HASH'} User.dataSource.autoupdate (err) -> return console.log(err) if err getIndexes 'User', (err, ixs) -> test.ok ixs.email && ixs.email.Column_name == 'email' console.log(ixs) test.equal ixs.email.Index_type, 'BTREE', 'default index type' test.done() it 'should change type of single-column index', (test) -> User.defineProperty 'email', type: String, index: { type: 'BTREE' } User.dataSource.isActual (err, ok) -> test.ok ok, 'dataSource is actual' User.dataSource.autoupdate (err) -> return console.log(err) if err getIndexes 'User', (err, ixs) -> test.ok ixs.email && ixs.email.Column_name == 'email' test.equal ixs.email.Index_type, 'BTREE' test.done() it 'should remove single-column index', (test) -> User.defineProperty 'email', type: String, index: false User.dataSource.autoupdate (err) -> return console.log(err) if err getIndexes 'User', (err, ixs) -> test.ok !ixs.email test.done() it 'should update multi-column index when order of columns changed', (test) -> User.dataSource.adapter._models.User.settings.indexes.index1.columns = 'createdByAdmin, email' User.dataSource.isActual (err, ok) -> test.ok not ok, 'dataSource is not actual' User.dataSource.autoupdate (err) -> return console.log(err) if err getIndexes 'User', (err, ixs) -> test.equals ixs.index1.Column_name, 'createdByAdmin' test.done() it 'test', (test) -> User.defineProperty 'email', type: String, index: true User.dataSource.autoupdate (err) -> User.dataSource.autoupdate (err) -> User.dataSource.autoupdate (err) -> test.done() it 'should disconnect when done', (test) -> dataSource.disconnect() test.done()