Update eslint infrastructure

This commit is contained in:
Loay 2016-08-10 14:41:03 -04:00
parent 4368b6e1e1
commit 9c9b61e7dc
21 changed files with 561 additions and 605 deletions

13
.eslintrc Normal file
View File

@ -0,0 +1,13 @@
{
"extends": "loopback",
"rules": {
"max-len": ["error", 120, 4, {
"ignoreComments": true,
"ignoreUrls": true,
"ignorePattern": "^\\s*var\\s.=\\s*(require\\s*\\()|(/)"
}],
"camelcase": 0,
"one-var": "off",
"no-unused-expressions": "off"
}
}

View File

@ -3,6 +3,7 @@
// This file is licensed under the MIT License. // This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict';
var DataSource = require('loopback-datasource-juggler').DataSource; var DataSource = require('loopback-datasource-juggler').DataSource;
var config = require('rc')('loopback', {dev: {mysql: {}}}).dev.mysql; var config = require('rc')('loopback', {dev: {mysql: {}}}).dev.mysql;
@ -15,7 +16,7 @@ function show(err, models) {
} else { } else {
console.log(models); console.log(models);
if (models) { if (models) {
models.forEach(function (m) { models.forEach(function(m) {
console.dir(m); console.dir(m);
}); });
} }
@ -33,13 +34,8 @@ ds.discoverForeignKeys('inventory', show);
ds.discoverExportedForeignKeys('location', show); ds.discoverExportedForeignKeys('location', show);
ds.discoverAndBuildModels('weapon', {owner: 'strongloop', visited: {}, associations: true}, function (err, models) { ds.discoverAndBuildModels('weapon', {owner: 'strongloop', visited: {}, associations: true}, function(err, models) {
for (var m in models) { for (var m in models) {
models[m].all(show); models[m].all(show);
} }
}); });

View File

@ -3,6 +3,7 @@
// This file is licensed under the MIT License. // This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict';
var SG = require('strong-globalize'); var SG = require('strong-globalize');
SG.SetRootDir(__dirname); SG.SetRootDir(__dirname);

View File

@ -3,6 +3,7 @@
// This file is licensed under the MIT License. // This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict';
var g = require('strong-globalize')(); var g = require('strong-globalize')();
module.exports = mixinDiscovery; module.exports = mixinDiscovery;
@ -88,7 +89,6 @@ function mixinDiscovery(MySQL, mysql) {
function queryViews(options) { function queryViews(options) {
var sqlViews = null; var sqlViews = null;
if (options.views) { if (options.views) {
var schema = options.owner || options.schema; var schema = options.owner || options.schema;
if (options.all && !schema) { if (options.all && !schema) {
@ -183,7 +183,7 @@ function mixinDiscovery(MySQL, mysql) {
schema: options.owner || options.schema, schema: options.owner || options.schema,
table: table, table: table,
options: options, options: options,
cb: cb cb: cb,
}; };
} }
@ -404,7 +404,7 @@ function mixinDiscovery(MySQL, mysql) {
this.execute(sql, cb); this.execute(sql, cb);
}; };
MySQL.prototype.buildPropertyType = function (columnDefinition) { MySQL.prototype.buildPropertyType = function(columnDefinition) {
var mysqlType = columnDefinition.dataType; var mysqlType = columnDefinition.dataType;
var dataLength = columnDefinition.dataLength; var dataLength = columnDefinition.dataLength;
@ -452,7 +452,7 @@ function mixinDiscovery(MySQL, mysql) {
default: default:
return 'String'; return 'String';
} }
} };
MySQL.prototype.getDefaultSchema = function() { MySQL.prototype.getDefaultSchema = function() {
if (this.dataSource && this.dataSource.settings && if (this.dataSource && this.dataSource.settings &&

View File

@ -3,6 +3,7 @@
// This file is licensed under the MIT License. // This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict';
var g = require('strong-globalize')(); var g = require('strong-globalize')();
var EnumFactory = function() { var EnumFactory = function() {
@ -11,7 +12,7 @@ var EnumFactory = function() {
if (typeof arg === 'number' && arg % 1 == 0) { if (typeof arg === 'number' && arg % 1 == 0) {
return Enum._values[arg]; return Enum._values[arg];
} else if (Enum[arg]) { } else if (Enum[arg]) {
return Enum[arg] return Enum[arg];
} else if (Enum._values.indexOf(arg) !== -1) { } else if (Enum._values.indexOf(arg) !== -1) {
return arg; return arg;
} else if (arg === null) { } else if (arg === null) {
@ -30,7 +31,7 @@ var EnumFactory = function() {
configurable: false, configurable: false,
enumerable: true, enumerable: true,
value: arg, value: arg,
writable: false writable: false,
}); });
dxList.push(arg); dxList.push(arg);
} }
@ -38,18 +39,18 @@ var EnumFactory = function() {
configurable: false, configurable: false,
enumerable: false, enumerable: false,
value: dxList, value: dxList,
writable: false writable: false,
}); });
Object.defineProperty(Enum, '_string', { Object.defineProperty(Enum, '_string', {
configurable: false, configurable: false,
enumerable: false, enumerable: false,
value: stringified(Enum), value: stringified(Enum),
writable: false writable: false,
}); });
Object.freeze(Enum); Object.freeze(Enum);
return Enum; return Enum;
} else { } else {
throw g.f("No arguments - could not create {{Enum}}."); throw g.f('No arguments - could not create {{Enum}}.');
} }
}; };
@ -64,10 +65,3 @@ function stringified(anEnum) {
} }
exports.EnumFactory = EnumFactory; exports.EnumFactory = EnumFactory;

View File

@ -3,6 +3,7 @@
// This file is licensed under the MIT License. // This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict';
var g = require('strong-globalize')(); var g = require('strong-globalize')();
var async = require('async'); var async = require('async');
module.exports = mixinMigration; module.exports = mixinMigration;
@ -49,7 +50,6 @@ function mixinMigration(MySQL, mysql) {
}); });
}); });
}, cb); }, cb);
}; };
/*! /*!
@ -130,7 +130,7 @@ function mixinMigration(MySQL, mysql) {
if (!ai[name]) { if (!ai[name]) {
ai[name] = { ai[name] = {
info: i, info: i,
columns: [] columns: [],
}; };
} }
ai[name].columns[i.Seq_in_index - 1] = i.Column_name; ai[name].columns[i.Seq_in_index - 1] = i.Column_name;
@ -216,7 +216,7 @@ function mixinMigration(MySQL, mysql) {
' (' + pName + ') ' + type); ' (' + pName + ') ' + type);
} else { } else {
if (typeof i === 'object' && i.unique && i.unique === true) { if (typeof i === 'object' && i.unique && i.unique === true) {
kind = "UNIQUE"; kind = 'UNIQUE';
} }
sql.push('ADD ' + kind + ' INDEX ' + pName + ' ' + type + sql.push('ADD ' + kind + ' INDEX ' + pName + ' ' + type +
' (' + pName + ') '); ' (' + pName + ') ');
@ -350,7 +350,7 @@ function mixinMigration(MySQL, mysql) {
return (kind + ' INDEX ' + columnName + ' (' + columnName + ') ' + type); return (kind + ' INDEX ' + columnName + ' (' + columnName + ') ' + type);
} else { } else {
if (typeof i === 'object' && i.unique && i.unique === true) { if (typeof i === 'object' && i.unique && i.unique === true) {
kind = "UNIQUE"; kind = 'UNIQUE';
} }
return (kind + ' INDEX ' + columnName + ' ' + type + ' (' + columnName + ') '); return (kind + ' INDEX ' + columnName + ' ' + type + ' (' + columnName + ') ');
} }
@ -496,10 +496,10 @@ function mixinMigration(MySQL, mysql) {
function stringOptions(p, columnType) { function stringOptions(p, columnType) {
if (p.charset) { if (p.charset) {
columnType += " CHARACTER SET " + p.charset; columnType += ' CHARACTER SET ' + p.charset;
} }
if (p.collation) { if (p.collation) {
columnType += " COLLATE " + p.collation; columnType += ' COLLATE ' + p.collation;
} }
return columnType; return columnType;
} }

View File

@ -3,6 +3,7 @@
// This file is licensed under the MIT License. // This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict';
var g = require('strong-globalize')(); var g = require('strong-globalize')();
/*! /*!
@ -33,12 +34,12 @@ exports.initialize = function initializeDataSource(dataSource, callback) {
dataSource.EnumFactory = EnumFactory; // factory for Enums. Note that currently Enums can not be registered. dataSource.EnumFactory = EnumFactory; // factory for Enums. Note that currently Enums can not be registered.
if(callback) { if (callback) {
if(dataSource.settings.lazyConnect) { if (dataSource.settings.lazyConnect) {
process.nextTick(function() { process.nextTick(function() {
callback(); callback();
}); });
} else{ } else {
dataSource.connector.connect(callback); dataSource.connector.connect(callback);
} }
} }
@ -90,7 +91,7 @@ MySQL.prototype.connect = function(callback) {
if (!err) { if (!err) {
if (self.debug) { if (self.debug) {
debug('MySQL connection is established: ' + self.settings || {}); debug('MySQL connection is established: ' + self.settings || {});
} }
connection.release(); connection.release();
} else { } else {
if (self.debug || !callback) { if (self.debug || !callback) {
@ -100,9 +101,9 @@ MySQL.prototype.connect = function(callback) {
callback && callback(err, conn); callback && callback(err, conn);
}); });
} }
} };
function generateOptions (settings) { function generateOptions(settings) {
var s = settings || {}; var s = settings || {};
if (s.collation) { if (s.collation) {
// Charset should be first 'chunk' of collation. // Charset should be first 'chunk' of collation.
@ -133,7 +134,7 @@ function generateOptions (settings) {
socketPath: s.socketPath, socketPath: s.socketPath,
charset: s.collation.toUpperCase(), // Correct by docs despite seeming odd. charset: s.collation.toUpperCase(), // Correct by docs despite seeming odd.
supportBigNumbers: s.supportBigNumbers, supportBigNumbers: s.supportBigNumbers,
connectionLimit: s.connectionLimit connectionLimit: s.connectionLimit,
}; };
// Don't configure the DB if the pool can be used for multiple DBs // Don't configure the DB if the pool can be used for multiple DBs
@ -240,44 +241,44 @@ MySQL.prototype.executeSQL = function(sql, params, options, callback) {
}; };
MySQL.prototype._modifyOrCreate = function(model, data, options, fields, cb) { MySQL.prototype._modifyOrCreate = function(model, data, options, fields, cb) {
var sql = new ParameterizedSQL('INSERT INTO ' + this.tableEscaped(model)); var sql = new ParameterizedSQL('INSERT INTO ' + this.tableEscaped(model));
var columnValues = fields.columnValues; var columnValues = fields.columnValues;
var fieldNames = fields.names; var fieldNames = fields.names;
if (fieldNames.length) { if (fieldNames.length) {
sql.merge('(' + fieldNames.join(',') + ')', ''); sql.merge('(' + fieldNames.join(',') + ')', '');
var values = ParameterizedSQL.join(columnValues, ','); var values = ParameterizedSQL.join(columnValues, ',');
values.sql = 'VALUES(' + values.sql + ')'; values.sql = 'VALUES(' + values.sql + ')';
sql.merge(values); sql.merge(values);
} else { } else {
sql.merge(this.buildInsertDefaultValues(model, data, options)); sql.merge(this.buildInsertDefaultValues(model, data, options));
} }
sql.merge('ON DUPLICATE KEY UPDATE'); sql.merge('ON DUPLICATE KEY UPDATE');
var setValues = []; var setValues = [];
for (var i = 0, n = fields.names.length; i < n; i++) { for (var i = 0, n = fields.names.length; i < n; i++) {
if (!fields.properties[i].id) { if (!fields.properties[i].id) {
setValues.push(new ParameterizedSQL(fields.names[i] + '=' + setValues.push(new ParameterizedSQL(fields.names[i] + '=' +
columnValues[i].sql, columnValues[i].params)); columnValues[i].sql, columnValues[i].params));
}
} }
}
sql.merge(ParameterizedSQL.join(setValues, ',')); sql.merge(ParameterizedSQL.join(setValues, ','));
this.execute(sql.sql, sql.params, options, function(err, info) { this.execute(sql.sql, sql.params, options, function(err, info) {
if (!err && info && info.insertId) { if (!err && info && info.insertId) {
data.id = info.insertId; data.id = info.insertId;
} }
var meta = {}; var meta = {};
if (info) { if (info) {
// When using the INSERT ... ON DUPLICATE KEY UPDATE statement, // When using the INSERT ... ON DUPLICATE KEY UPDATE statement,
// the returned value is as follows: // the returned value is as follows:
// 1 for each successful INSERT. // 1 for each successful INSERT.
// 2 for each successful UPDATE. // 2 for each successful UPDATE.
meta.isNewInstance = (info.affectedRows === 1); meta.isNewInstance = (info.affectedRows === 1);
} }
cb(err, data, meta); cb(err, data, meta);
}); });
}; };
/** /**
* Replace if the model instance exists with the same id or create a new instance * Replace if the model instance exists with the same id or create a new instance
@ -363,7 +364,7 @@ MySQL.prototype.toColumnValue = function(prop, val) {
if (prop.type.name === 'GeoPoint') { if (prop.type.name === 'GeoPoint') {
return new ParameterizedSQL({ return new ParameterizedSQL({
sql: 'Point(?,?)', sql: 'Point(?,?)',
params: [val.lat, val.lng] params: [val.lat, val.lng],
}); });
} }
if (prop.type === Object) { if (prop.type === Object) {
@ -416,7 +417,7 @@ MySQL.prototype.fromColumnValue = function(prop, val) {
case 'Point': case 'Point':
val = { val = {
lat: val.x, lat: val.x,
lng: val.y lng: val.y,
}; };
break; break;
case 'List': case 'List':
@ -465,7 +466,7 @@ MySQL.prototype._buildLimit = function(model, limit, offset) {
return ''; return '';
} }
return 'LIMIT ' + (offset ? (offset + ',' + limit) : limit); return 'LIMIT ' + (offset ? (offset + ',' + limit) : limit);
} };
MySQL.prototype.applyPagination = function(model, stmt, filter) { MySQL.prototype.applyPagination = function(model, stmt, filter) {
var limitClause = this._buildLimit(model, filter.limit, var limitClause = this._buildLimit(model, filter.limit,

View File

@ -3,6 +3,7 @@
// This file is licensed under the MIT License. // This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict';
var debug = require('debug')('loopback:connector:mysql:transaction'); var debug = require('debug')('loopback:connector:mysql:transaction');
module.exports = mixinTransaction; module.exports = mixinTransaction;
@ -11,7 +12,6 @@ module.exports = mixinTransaction;
* @param {Object} mysql mysql driver * @param {Object} mysql mysql driver
*/ */
function mixinTransaction(MySQL, mysql) { function mixinTransaction(MySQL, mysql) {
/** /**
* Begin a new transaction * Begin a new transaction
* @param isolationLevel * @param isolationLevel
@ -20,8 +20,8 @@ function mixinTransaction(MySQL, mysql) {
MySQL.prototype.beginTransaction = function(isolationLevel, cb) { MySQL.prototype.beginTransaction = function(isolationLevel, cb) {
debug('Begin a transaction with isolation level: %s', isolationLevel); debug('Begin a transaction with isolation level: %s', isolationLevel);
this.client.getConnection(function(err, connection) { this.client.getConnection(function(err, connection) {
if(err) return cb(err); if (err) return cb(err);
if(isolationLevel) { if (isolationLevel) {
connection.query( connection.query(
'SET SESSION TRANSACTION ISOLATION LEVEL ' + isolationLevel, 'SET SESSION TRANSACTION ISOLATION LEVEL ' + isolationLevel,
function(err) { function(err) {
@ -65,4 +65,4 @@ function mixinTransaction(MySQL, mysql) {
cb(err); cb(err);
}); });
}; };
} }

View File

@ -5,8 +5,10 @@
"main": "index.js", "main": "index.js",
"scripts": { "scripts": {
"pretest": "node pretest.js", "pretest": "node pretest.js",
"test": "mocha" "lint": "eslint .",
}, "test": "mocha --timeout 10000 test/*.js",
"posttest": "npm run lint"
},
"dependencies": { "dependencies": {
"async": "^0.9.0", "async": "^0.9.0",
"debug": "^2.1.1", "debug": "^2.1.1",
@ -16,6 +18,8 @@
}, },
"devDependencies": { "devDependencies": {
"bluebird": "~2.9.10", "bluebird": "~2.9.10",
"eslint": "^2.13.1",
"eslint-config-loopback": "^4.0.0",
"loopback-datasource-juggler": "^2.28.0", "loopback-datasource-juggler": "^2.28.0",
"mocha": "^2.1.0", "mocha": "^2.1.0",
"rc": "^1.0.0", "rc": "^1.0.0",

View File

@ -1,3 +1,4 @@
'use strict';
// TODO: used for testing support for parallel testing on ci.strongloop.com which // TODO: used for testing support for parallel testing on ci.strongloop.com which
// provides MYSQL_* env vars instead of TEST_MYSQL_* env vars. // provides MYSQL_* env vars instead of TEST_MYSQL_* env vars.
process.env.TEST_MYSQL_USER = process.env.TEST_MYSQL_USER || process.env.MYSQL_USER; process.env.TEST_MYSQL_USER = process.env.TEST_MYSQL_USER || process.env.MYSQL_USER;

View File

@ -3,6 +3,7 @@
// This file is licensed under the MIT License. // This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict';
require('./init.js'); require('./init.js');
var assert = require('assert'); var assert = require('assert');
var should = require('should'); var should = require('should');
@ -12,9 +13,8 @@ var url = require('url');
var db, DummyModel, odb, config; var db, DummyModel, odb, config;
describe('connections', function () { describe('connections', function() {
before(function() {
before(function () {
require('./init.js'); require('./init.js');
config = global.getConfig(); config = global.getConfig();
@ -23,12 +23,12 @@ describe('connections', function () {
db = odb; db = odb;
}); });
it('should pass with valid settings', function (done) { it('should pass with valid settings', function(done) {
var db = new DataSource(mysqlConnector, config); var db = new DataSource(mysqlConnector, config);
db.ping(done); db.ping(done);
}); });
it('ignores all other settings when url is present', function (done) { it('ignores all other settings when url is present', function(done) {
var formatedUrl = generateURL(config); var formatedUrl = generateURL(config);
var dbConfig = { var dbConfig = {
url: formatedUrl, url: formatedUrl,
@ -43,36 +43,32 @@ describe('connections', function () {
db.ping(done); db.ping(done);
}); });
it('should use utf8 charset', function (done) { it('should use utf8 charset', function(done) {
var test_set = /utf8/; var test_set = /utf8/;
var test_collo = /utf8_general_ci/; var test_collo = /utf8_general_ci/;
var test_set_str = 'utf8'; var test_set_str = 'utf8';
var test_set_collo = 'utf8_general_ci'; var test_set_collo = 'utf8_general_ci';
charsetTest(test_set, test_collo, test_set_str, test_set_collo, done); charsetTest(test_set, test_collo, test_set_str, test_set_collo, done);
}); });
it('should disconnect first db', function (done) { it('should disconnect first db', function(done) {
db.disconnect(function () { db.disconnect(function() {
odb = getDataSource(); odb = getDataSource();
done(); done();
}); });
}); });
it('should use latin1 charset', function (done) { it('should use latin1 charset', function(done) {
var test_set = /latin1/; var test_set = /latin1/;
var test_collo = /latin1_general_ci/; var test_collo = /latin1_general_ci/;
var test_set_str = 'latin1'; var test_set_str = 'latin1';
var test_set_collo = 'latin1_general_ci'; var test_set_collo = 'latin1_general_ci';
charsetTest(test_set, test_collo, test_set_str, test_set_collo, done); charsetTest(test_set, test_collo, test_set_str, test_set_collo, done);
}); });
it('should drop db and disconnect all', function (done) { it('should drop db and disconnect all', function(done) {
db.connector.execute('DROP DATABASE IF EXISTS ' + db.settings.database, function (err) { db.connector.execute('DROP DATABASE IF EXISTS ' + db.settings.database, function(err) {
db.disconnect(function () { db.disconnect(function() {
done(); done();
}); });
}); });
@ -113,21 +109,19 @@ describe('connections', function () {
}); });
function charsetTest(test_set, test_collo, test_set_str, test_set_collo, done) { function charsetTest(test_set, test_collo, test_set_str, test_set_collo, done) {
query('DROP DATABASE IF EXISTS ' + odb.settings.database, function(err) {
query('DROP DATABASE IF EXISTS ' + odb.settings.database, function (err) {
assert.ok(!err); assert.ok(!err);
odb.disconnect(function () { odb.disconnect(function() {
db = getDataSource({collation: test_set_collo, createDatabase: true}); db = getDataSource({collation: test_set_collo, createDatabase: true});
DummyModel = db.define('DummyModel', {string: String}); DummyModel = db.define('DummyModel', {string: String});
db.automigrate(function () { db.automigrate(function() {
var q = 'SELECT DEFAULT_COLLATION_NAME' + var q = 'SELECT DEFAULT_COLLATION_NAME' +
' FROM information_schema.SCHEMATA WHERE SCHEMA_NAME = ' + ' FROM information_schema.SCHEMATA WHERE SCHEMA_NAME = ' +
db.driver.escape(db.settings.database) + ' LIMIT 1'; db.driver.escape(db.settings.database) + ' LIMIT 1';
db.connector.execute(q, function (err, r) { db.connector.execute(q, function(err, r) {
assert.ok(!err); assert.ok(!err);
should(r[0].DEFAULT_COLLATION_NAME).match(test_collo); should(r[0].DEFAULT_COLLATION_NAME).match(test_collo);
db.connector.execute('SHOW VARIABLES LIKE "character_set%"', function (err, r) { db.connector.execute('SHOW VARIABLES LIKE "character_set%"', function(err, r) {
assert.ok(!err); assert.ok(!err);
var hit_all = 0; var hit_all = 0;
for (var result in r) { for (var result in r) {
@ -138,7 +132,7 @@ function charsetTest(test_set, test_collo, test_set_str, test_set_collo, done) {
} }
assert.equal(hit_all, 4); assert.equal(hit_all, 4);
}); });
db.connector.execute('SHOW VARIABLES LIKE "collation%"', function (err, r) { db.connector.execute('SHOW VARIABLES LIKE "collation%"', function(err, r) {
assert.ok(!err); assert.ok(!err);
var hit_all = 0; var hit_all = 0;
for (var result in r) { for (var result in r) {
@ -152,7 +146,6 @@ function charsetTest(test_set, test_collo, test_set_str, test_set_collo, done) {
}); });
}); });
}); });
} }
function matchResult(result, variable_name, match) { function matchResult(result, variable_name, match) {
@ -163,7 +156,7 @@ function matchResult(result, variable_name, match) {
return 0; return 0;
} }
var query = function (sql, cb) { var query = function(sql, cb) {
odb.connector.execute(sql, cb); odb.connector.execute(sql, cb);
}; };
@ -173,7 +166,7 @@ function generateURL(config) {
auth: config.username || '', auth: config.username || '',
hostname: config.host, hostname: config.host,
pathname: config.database, pathname: config.database,
slashes: true slashes: true,
}; };
if (config.password) { if (config.password) {
urlObj.auth += ':' + config.password; urlObj.auth += ':' + config.password;
@ -181,8 +174,3 @@ function generateURL(config) {
var formatedUrl = url.format(urlObj); var formatedUrl = url.format(urlObj);
return formatedUrl; return formatedUrl;
} }

View File

@ -3,23 +3,23 @@
// This file is licensed under the MIT License. // This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict';
require('./init.js'); require('./init.js');
var assert = require('assert'); var assert = require('assert');
var db, EnumModel, ANIMAL_ENUM; var db, EnumModel, ANIMAL_ENUM;
var mysqlVersion; var mysqlVersion;
describe('MySQL specific datatypes', function () { describe('MySQL specific datatypes', function() {
before(setup); before(setup);
it('should run migration', function (done) { it('should run migration', function(done) {
db.automigrate(function () { db.automigrate(function() {
done(); done();
}); });
}); });
it('An enum should parse itself', function (done) { it('An enum should parse itself', function(done) {
assert.equal(ANIMAL_ENUM.CAT, ANIMAL_ENUM('cat')); assert.equal(ANIMAL_ENUM.CAT, ANIMAL_ENUM('cat'));
assert.equal(ANIMAL_ENUM.CAT, ANIMAL_ENUM('CAT')); assert.equal(ANIMAL_ENUM.CAT, ANIMAL_ENUM('CAT'));
assert.equal(ANIMAL_ENUM.CAT, ANIMAL_ENUM(2)); assert.equal(ANIMAL_ENUM.CAT, ANIMAL_ENUM(2));
@ -30,11 +30,11 @@ describe('MySQL specific datatypes', function () {
done(); done();
}); });
it('should create a model instance with Enums', function (done) { it('should create a model instance with Enums', function(done) {
var em = EnumModel.create({animal: ANIMAL_ENUM.CAT, condition: 'sleepy', mood: 'happy'}, function (err, obj) { var em = EnumModel.create({animal: ANIMAL_ENUM.CAT, condition: 'sleepy', mood: 'happy'}, function(err, obj) {
assert.ok(!err); assert.ok(!err);
assert.equal(obj.condition, 'sleepy'); assert.equal(obj.condition, 'sleepy');
EnumModel.findOne({where: {animal: ANIMAL_ENUM.CAT}}, function (err, found) { EnumModel.findOne({where: {animal: ANIMAL_ENUM.CAT}}, function(err, found) {
assert.ok(!err); assert.ok(!err);
assert.equal(found.mood, 'happy'); assert.equal(found.mood, 'happy');
assert.equal(found.animal, ANIMAL_ENUM.CAT); assert.equal(found.animal, ANIMAL_ENUM.CAT);
@ -43,15 +43,15 @@ describe('MySQL specific datatypes', function () {
}); });
}); });
it('should fail spectacularly with invalid enum values', function (done) { it('should fail spectacularly with invalid enum values', function(done) {
// TODO: with a default install of MySQL 5.7, these queries actually do fail and raise errors... // TODO: with a default install of MySQL 5.7, these queries actually do fail and raise errors...
if (/^5\.7/.test(mysqlVersion)) { if (/^5\.7/.test(mysqlVersion)) {
assert.ok(mysqlVersion, 'skipping decimal/number test on mysql 5.7'); assert.ok(mysqlVersion, 'skipping decimal/number test on mysql 5.7');
return done(); return done();
} }
var em = EnumModel.create({animal: 'horse', condition: 'sleepy', mood: 'happy'}, function (err, obj) { var em = EnumModel.create({animal: 'horse', condition: 'sleepy', mood: 'happy'}, function(err, obj) {
assert.ok(!err); assert.ok(!err);
EnumModel.findById(obj.id, function (err, found) { EnumModel.findById(obj.id, function(err, found) {
assert.ok(!err); assert.ok(!err);
assert.equal(found.animal, ''); // MySQL fun. assert.equal(found.animal, ''); // MySQL fun.
assert.equal(found.animal, 0); assert.equal(found.animal, 0);
@ -60,14 +60,14 @@ describe('MySQL specific datatypes', function () {
}); });
}); });
it('should create a model instance with object/json types', function (done) { it('should create a model instance with object/json types', function(done) {
var note = {a: 1, b: '2'}; var note = {a: 1, b: '2'};
var extras = {c: 3, d: '4'}; var extras = {c: 3, d: '4'};
var em = EnumModel.create({animal: ANIMAL_ENUM.DOG, condition: 'sleepy', var em = EnumModel.create({animal: ANIMAL_ENUM.DOG, condition: 'sleepy',
mood: 'happy', note: note, extras: extras}, function (err, obj) { mood: 'happy', note: note, extras: extras}, function(err, obj) {
assert.ok(!err); assert.ok(!err);
assert.equal(obj.condition, 'sleepy'); assert.equal(obj.condition, 'sleepy');
EnumModel.findOne({where: {animal: ANIMAL_ENUM.DOG}}, function (err, found) { EnumModel.findOne({where: {animal: ANIMAL_ENUM.DOG}}, function(err, found) {
assert.ok(!err); assert.ok(!err);
assert.equal(found.mood, 'happy'); assert.equal(found.mood, 'happy');
assert.equal(found.animal, ANIMAL_ENUM.DOG); assert.equal(found.animal, ANIMAL_ENUM.DOG);
@ -78,15 +78,13 @@ describe('MySQL specific datatypes', function () {
}); });
}); });
it('should disconnect when done', function (done) { it('should disconnect when done', function(done) {
db.disconnect(); db.disconnect();
done() done();
}); });
}); });
function setup(done) { function setup(done) {
require('./init.js'); require('./init.js');
db = getSchema(); db = getSchema();
@ -94,11 +92,11 @@ function setup(done) {
ANIMAL_ENUM = db.EnumFactory('dog', 'cat', 'mouse'); ANIMAL_ENUM = db.EnumFactory('dog', 'cat', 'mouse');
EnumModel = db.define('EnumModel', { EnumModel = db.define('EnumModel', {
animal: { type: ANIMAL_ENUM, null: false }, animal: {type: ANIMAL_ENUM, null: false},
condition: { type: db.EnumFactory('hungry', 'sleepy', 'thirsty') }, condition: {type: db.EnumFactory('hungry', 'sleepy', 'thirsty')},
mood: { type: db.EnumFactory('angry', 'happy', 'sad') }, mood: {type: db.EnumFactory('angry', 'happy', 'sad')},
note: Object, note: Object,
extras: 'JSON' extras: 'JSON',
}); });
query('SELECT VERSION()', function(err, res) { query('SELECT VERSION()', function(err, res) {
@ -107,15 +105,15 @@ function setup(done) {
}); });
} }
var query = function (sql, cb) { var query = function(sql, cb) {
db.adapter.execute(sql, cb); db.adapter.execute(sql, cb);
}; };
var blankDatabase = function (db, cb) { var blankDatabase = function(db, cb) {
var dbn = db.settings.database; var dbn = db.settings.database;
var cs = db.settings.charset; var cs = db.settings.charset;
var co = db.settings.collation; var co = db.settings.collation;
query('DROP DATABASE IF EXISTS ' + dbn, function (err) { query('DROP DATABASE IF EXISTS ' + dbn, function(err) {
var q = 'CREATE DATABASE ' + dbn; var q = 'CREATE DATABASE ' + dbn;
if (cs) { if (cs) {
q += ' CHARACTER SET ' + cs; q += ' CHARACTER SET ' + cs;
@ -123,46 +121,40 @@ var blankDatabase = function (db, cb) {
if (co) { if (co) {
q += ' COLLATE ' + co; q += ' COLLATE ' + co;
} }
query(q, function (err) { query(q, function(err) {
query('USE ' + dbn, cb); query('USE ' + dbn, cb);
}); });
}); });
}; };
getFields = function (model, cb) { var getFields = function(model, cb) {
query('SHOW FIELDS FROM ' + model, function (err, res) { query('SHOW FIELDS FROM ' + model, function(err, res) {
if (err) { if (err) {
cb(err); cb(err);
} else { } else {
var fields = {}; var fields = {};
res.forEach(function (field) { res.forEach(function(field) {
fields[field.Field] = field; fields[field.Field] = field;
}); });
cb(err, fields); cb(err, fields);
} }
}); });
} };
getIndexes = function (model, cb) { var getIndexes = function(model, cb) {
query('SHOW INDEXES FROM ' + model, function (err, res) { query('SHOW INDEXES FROM ' + model, function(err, res) {
if (err) { if (err) {
console.log(err); console.log(err);
cb(err); cb(err);
} else { } else {
var indexes = {}; var indexes = {};
// Note: this will only show the first key of compound keys // Note: this will only show the first key of compound keys
res.forEach(function (index) { res.forEach(function(index) {
if (parseInt(index.Seq_in_index, 10) == 1) { if (parseInt(index.Seq_in_index, 10) == 1) {
indexes[index.Key_name] = index indexes[index.Key_name] = index;
} }
}); });
cb(err, indexes); cb(err, indexes);
} }
}); });
}; };

View File

@ -3,13 +3,12 @@
// This file is licensed under the MIT License. // This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
describe('mysql imported features', function () { 'use strict';
describe('mysql imported features', function() {
before(function () { before(function() {
require('./init.js'); require('./init.js');
}); });
require('loopback-datasource-juggler/test/common.batch.js'); require('loopback-datasource-juggler/test/common.batch.js');
require('loopback-datasource-juggler/test/include.test.js'); require('loopback-datasource-juggler/test/include.test.js');
}); });

View File

@ -3,6 +3,7 @@
// This file is licensed under the MIT License. // This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict';
// TODO: used for testing support for parallel testing on ci.strongloop.com which // TODO: used for testing support for parallel testing on ci.strongloop.com which
// provides MYSQL_* env vars instead of TEST_MYSQL_* env vars. // provides MYSQL_* env vars instead of TEST_MYSQL_* env vars.
process.env.TEST_MYSQL_USER = process.env.TEST_MYSQL_USER || process.env.MYSQL_USER; process.env.TEST_MYSQL_USER = process.env.TEST_MYSQL_USER || process.env.MYSQL_USER;
@ -15,16 +16,15 @@ module.exports = require('should');
var DataSource = require('loopback-datasource-juggler').DataSource; var DataSource = require('loopback-datasource-juggler').DataSource;
var config = require('rc')('loopback', {test: {mysql: {}}}).test.mysql; var config = require('rc')('loopback', {test: {mysql: {}}}).test.mysql;
console.log(config) console.log(config);
global.getConfig = function (options) { global.getConfig = function(options) {
var dbConf = { var dbConf = {
host: process.env.TEST_MYSQL_HOST || config.host || 'localhost', host: process.env.TEST_MYSQL_HOST || config.host || 'localhost',
port: process.env.TEST_MYSQL_PORT || config.port || 3306, port: process.env.TEST_MYSQL_PORT || config.port || 3306,
database: 'myapp_test', database: 'myapp_test',
username: process.env.TEST_MYSQL_USER || config.username, username: process.env.TEST_MYSQL_USER || config.username,
password: process.env.TEST_MYSQL_PASSWORD || config.password, password: process.env.TEST_MYSQL_PASSWORD || config.password,
createDatabase: true createDatabase: true,
}; };
if (options) { if (options) {
@ -35,7 +35,7 @@ global.getConfig = function (options) {
return dbConf; return dbConf;
}; };
global.getDataSource = global.getSchema = function (options) { global.getDataSource = global.getSchema = function(options) {
var db = new DataSource(require('../'), getConfig(options)); var db = new DataSource(require('../'), getConfig(options));
return db; return db;
}; };

View File

@ -3,6 +3,7 @@
// This file is licensed under the MIT License. // This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict';
var should = require('./init.js'); var should = require('./init.js');
var assert = require('assert'); var assert = require('assert');
var Schema = require('loopback-datasource-juggler').Schema; var Schema = require('loopback-datasource-juggler').Schema;
@ -10,18 +11,17 @@ var Schema = require('loopback-datasource-juggler').Schema;
var db, UserData, StringData, NumberData, DateData; var db, UserData, StringData, NumberData, DateData;
var mysqlVersion; var mysqlVersion;
describe('migrations', function () { describe('migrations', function() {
before(setup); before(setup);
it('should run migration', function (done) { it('should run migration', function(done) {
db.automigrate(function () { db.automigrate(function() {
done(); done();
}); });
}); });
it('UserData should have correct columns', function (done) { it('UserData should have correct columns', function(done) {
getFields('UserData', function (err, fields) { getFields('UserData', function(err, fields) {
fields.should.be.eql({ fields.should.be.eql({
id: { id: {
Field: 'id', Field: 'id',
@ -29,58 +29,58 @@ describe('migrations', function () {
Null: 'NO', Null: 'NO',
Key: 'PRI', Key: 'PRI',
Default: null, Default: null,
Extra: 'auto_increment' }, Extra: 'auto_increment'},
email: { email: {
Field: 'email', Field: 'email',
Type: 'varchar(512)', Type: 'varchar(512)',
Null: 'NO', Null: 'NO',
Key: 'MUL', Key: 'MUL',
Default: null, Default: null,
Extra: '' }, Extra: ''},
name: { name: {
Field: 'name', Field: 'name',
Type: 'varchar(512)', Type: 'varchar(512)',
Null: 'YES', Null: 'YES',
Key: '', Key: '',
Default: null, Default: null,
Extra: '' }, Extra: ''},
bio: { bio: {
Field: 'bio', Field: 'bio',
Type: 'text', Type: 'text',
Null: 'YES', Null: 'YES',
Key: '', Key: '',
Default: null, Default: null,
Extra: '' }, Extra: ''},
birthDate: { birthDate: {
Field: 'birthDate', Field: 'birthDate',
Type: 'datetime', Type: 'datetime',
Null: 'YES', Null: 'YES',
Key: '', Key: '',
Default: null, Default: null,
Extra: '' }, Extra: ''},
pendingPeriod: { pendingPeriod: {
Field: 'pendingPeriod', Field: 'pendingPeriod',
Type: 'int(11)', Type: 'int(11)',
Null: 'YES', Null: 'YES',
Key: '', Key: '',
Default: null, Default: null,
Extra: '' }, Extra: ''},
createdByAdmin: { createdByAdmin: {
Field: 'createdByAdmin', Field: 'createdByAdmin',
Type: 'tinyint(1)', Type: 'tinyint(1)',
Null: 'YES', Null: 'YES',
Key: '', Key: '',
Default: null, Default: null,
Extra: '' } Extra: ''},
}); });
done(); done();
}); });
}); });
it('UserData should have correct indexes', function (done) { it('UserData should have correct indexes', function(done) {
// Note: getIndexes truncates multi-key indexes to the first member. // Note: getIndexes truncates multi-key indexes to the first member.
// Hence index1 is correct. // Hence index1 is correct.
getIndexes('UserData', function (err, fields) { getIndexes('UserData', function(err, fields) {
fields.should.match({ fields.should.match({
PRIMARY: { PRIMARY: {
Table: /UserData/i, Table: /UserData/i,
@ -97,7 +97,7 @@ describe('migrations', function () {
Packed: null, Packed: null,
Null: '', Null: '',
Index_type: 'BTREE', Index_type: 'BTREE',
Comment: '' }, Comment: ''},
email: { email: {
Table: /UserData/i, Table: /UserData/i,
Non_unique: 1, Non_unique: 1,
@ -113,7 +113,7 @@ describe('migrations', function () {
Packed: null, Packed: null,
Null: '', Null: '',
Index_type: 'BTREE', Index_type: 'BTREE',
Comment: '' }, Comment: ''},
index0: { index0: {
Table: /UserData/i, Table: /UserData/i,
Non_unique: 1, Non_unique: 1,
@ -129,141 +129,141 @@ describe('migrations', function () {
Packed: null, Packed: null,
Null: '', Null: '',
Index_type: 'BTREE', Index_type: 'BTREE',
Comment: '' } Comment: ''},
}); });
done(); done();
}); });
}); });
it('StringData should have correct columns', function (done) { it('StringData should have correct columns', function(done) {
getFields('StringData', function (err, fields) { getFields('StringData', function(err, fields) {
fields.should.be.eql({ fields.should.be.eql({
idString: { Field: "idString", idString: {Field: 'idString',
Type: 'varchar(255)', Type: 'varchar(255)',
Null: 'NO', Null: 'NO',
Key: 'PRI', Key: 'PRI',
Default: null, Default: null,
Extra: ''}, Extra: ''},
smallString: { Field: 'smallString', smallString: {Field: 'smallString',
Type: 'char(127)', Type: 'char(127)',
Null: 'NO', Null: 'NO',
Key: 'MUL', Key: 'MUL',
Default: null, Default: null,
Extra: '' }, Extra: ''},
mediumString: { Field: 'mediumString', mediumString: {Field: 'mediumString',
Type: 'varchar(255)', Type: 'varchar(255)',
Null: 'NO', Null: 'NO',
Key: '', Key: '',
Default: null, Default: null,
Extra: '' }, Extra: ''},
tinyText: { Field: 'tinyText', tinyText: {Field: 'tinyText',
Type: 'tinytext', Type: 'tinytext',
Null: 'YES', Null: 'YES',
Key: '', Key: '',
Default: null, Default: null,
Extra: '' }, Extra: ''},
giantJSON: { Field: 'giantJSON', giantJSON: {Field: 'giantJSON',
Type: 'longtext', Type: 'longtext',
Null: 'YES', Null: 'YES',
Key: '', Key: '',
Default: null, Default: null,
Extra: '' }, Extra: ''},
text: { Field: 'text', text: {Field: 'text',
Type: 'varchar(1024)', Type: 'varchar(1024)',
Null: 'YES', Null: 'YES',
Key: '', Key: '',
Default: null, Default: null,
Extra: '' } Extra: ''},
}); });
done(); done();
}); });
}); });
it('NumberData should have correct columns', function (done) { it('NumberData should have correct columns', function(done) {
getFields('NumberData', function (err, fields) { getFields('NumberData', function(err, fields) {
fields.should.be.eql({ fields.should.be.eql({
id: { Field: 'id', id: {Field: 'id',
Type: 'int(11)', Type: 'int(11)',
Null: 'NO', Null: 'NO',
Key: 'PRI', Key: 'PRI',
Default: null, Default: null,
Extra: 'auto_increment' }, Extra: 'auto_increment'},
number: { Field: 'number', number: {Field: 'number',
Type: 'decimal(10,3) unsigned', Type: 'decimal(10,3) unsigned',
Null: 'NO', Null: 'NO',
Key: 'MUL', Key: 'MUL',
Default: null, Default: null,
Extra: '' }, Extra: ''},
tinyInt: { Field: 'tinyInt', tinyInt: {Field: 'tinyInt',
Type: 'tinyint(2)', Type: 'tinyint(2)',
Null: 'YES', Null: 'YES',
Key: '', Key: '',
Default: null, Default: null,
Extra: '' }, Extra: ''},
mediumInt: { Field: 'mediumInt', mediumInt: {Field: 'mediumInt',
Type: 'mediumint(8) unsigned', Type: 'mediumint(8) unsigned',
Null: 'NO', Null: 'NO',
Key: '', Key: '',
Default: null, Default: null,
Extra: '' }, Extra: ''},
floater: { Field: 'floater', floater: {Field: 'floater',
Type: 'double(14,6)', Type: 'double(14,6)',
Null: 'YES', Null: 'YES',
Key: '', Key: '',
Default: null, Default: null,
Extra: '' } Extra: ''},
}); });
done(); done();
}); });
}); });
it('DateData should have correct columns', function (done) { it('DateData should have correct columns', function(done) {
getFields('DateData', function (err, fields) { getFields('DateData', function(err, fields) {
fields.should.be.eql({ fields.should.be.eql({
id: { Field: 'id', id: {Field: 'id',
Type: 'int(11)', Type: 'int(11)',
Null: 'NO', Null: 'NO',
Key: 'PRI', Key: 'PRI',
Default: null, Default: null,
Extra: 'auto_increment' }, Extra: 'auto_increment'},
dateTime: { Field: 'dateTime', dateTime: {Field: 'dateTime',
Type: 'datetime', Type: 'datetime',
Null: 'YES', Null: 'YES',
Key: '', Key: '',
Default: null, Default: null,
Extra: '' }, Extra: ''},
timestamp: { Field: 'timestamp', timestamp: {Field: 'timestamp',
Type: 'timestamp', Type: 'timestamp',
Null: 'YES', Null: 'YES',
Key: '', Key: '',
Default: null, Default: null,
Extra: '' } Extra: ''},
}); });
done(); done();
}); });
}); });
it('should autoupdate', function (done) { it('should autoupdate', function(done) {
var userExists = function (cb) { var userExists = function(cb) {
query('SELECT * FROM UserData', function (err, res) { query('SELECT * FROM UserData', function(err, res) {
cb(!err && res[0].email == 'test@example.com'); cb(!err && res[0].email == 'test@example.com');
}); });
} };
UserData.create({email: 'test@example.com'}, function (err, user) { UserData.create({email: 'test@example.com'}, function(err, user) {
assert.ok(!err, 'Could not create user: ' + err); assert.ok(!err, 'Could not create user: ' + err);
userExists(function (yep) { userExists(function(yep) {
assert.ok(yep, 'User does not exist'); assert.ok(yep, 'User does not exist');
}); });
UserData.defineProperty('email', { type: String }); UserData.defineProperty('email', {type: String});
UserData.defineProperty('name', {type: String, UserData.defineProperty('name', {type: String,
dataType: 'char', limit: 50}); dataType: 'char', limit: 50});
UserData.defineProperty('newProperty', {type: Number, unsigned: true, UserData.defineProperty('newProperty', {type: Number, unsigned: true,
dataType: 'bigInt'}); dataType: 'bigInt'});
// UserData.defineProperty('pendingPeriod', false); // UserData.defineProperty('pendingPeriod', false);
// This will not work as expected. // This will not work as expected.
db.autoupdate(function (err) { db.autoupdate(function(err) {
getFields('UserData', function (err, fields) { getFields('UserData', function(err, fields) {
// change nullable for email // change nullable for email
assert.equal(fields.email.Null, 'YES', 'Email does not allow null'); assert.equal(fields.email.Null, 'YES', 'Email does not allow null');
// change type of name // change type of name
@ -278,7 +278,7 @@ describe('migrations', function () {
// assert.ok(!fields.pendingPeriod, // assert.ok(!fields.pendingPeriod,
// 'Did not drop column pendingPeriod'); // 'Did not drop column pendingPeriod');
// user still exists // user still exists
userExists(function (yep) { userExists(function(yep) {
assert.ok(yep, 'User does not exist'); assert.ok(yep, 'User does not exist');
done(); done();
}); });
@ -287,20 +287,20 @@ describe('migrations', function () {
}); });
}); });
it('should check actuality of dataSource', function (done) { it('should check actuality of dataSource', function(done) {
// 'drop column' // 'drop column'
UserData.dataSource.isActual(function (err, ok) { UserData.dataSource.isActual(function(err, ok) {
assert.ok(ok, 'dataSource is not actual (should be)'); assert.ok(ok, 'dataSource is not actual (should be)');
UserData.defineProperty('essay', {type: Schema.Text}); UserData.defineProperty('essay', {type: Schema.Text});
// UserData.defineProperty('email', false); Can't undefine currently. // UserData.defineProperty('email', false); Can't undefine currently.
UserData.dataSource.isActual(function (err, ok) { UserData.dataSource.isActual(function(err, ok) {
assert.ok(!ok, 'dataSource is actual (shouldn\t be)'); assert.ok(!ok, 'dataSource is actual (shouldn\t be)');
done() done();
}); });
}); });
}); });
it('should allow numbers with decimals', function (done) { it('should allow numbers with decimals', function(done) {
// TODO: Default install of MySQL 5.7 returns an error here, which we assert should not happen. // TODO: Default install of MySQL 5.7 returns an error here, which we assert should not happen.
if (/^5\.7/.test(mysqlVersion)) { if (/^5\.7/.test(mysqlVersion)) {
assert.ok(mysqlVersion, 'skipping decimal/number test on mysql 5.7'); assert.ok(mysqlVersion, 'skipping decimal/number test on mysql 5.7');
@ -308,10 +308,10 @@ describe('migrations', function () {
} }
NumberData.create({number: 1.1234567, tinyInt: 123456, mediumInt: -1234567, NumberData.create({number: 1.1234567, tinyInt: 123456, mediumInt: -1234567,
floater: 123456789.1234567 }, function (err, obj) { floater: 123456789.1234567}, function(err, obj) {
assert.ok(!err); assert.ok(!err);
assert.ok(obj); assert.ok(obj);
NumberData.findById(obj.id, function (err, found) { NumberData.findById(obj.id, function(err, found) {
assert.equal(found.number, 1.123); assert.equal(found.number, 1.123);
assert.equal(found.tinyInt, 127); assert.equal(found.tinyInt, 127);
assert.equal(found.mediumInt, 0); assert.equal(found.mediumInt, 0);
@ -321,14 +321,14 @@ describe('migrations', function () {
}); });
}); });
it('should allow both kinds of date columns', function (done) { it('should allow both kinds of date columns', function(done) {
DateData.create({ DateData.create({
dateTime: new Date('Aug 9 1996 07:47:33 GMT'), dateTime: new Date('Aug 9 1996 07:47:33 GMT'),
timestamp: new Date('Sep 22 2007 17:12:22 GMT') timestamp: new Date('Sep 22 2007 17:12:22 GMT'),
}, function (err, obj) { }, function(err, obj) {
assert.ok(!err); assert.ok(!err);
assert.ok(obj); assert.ok(obj);
DateData.findById(obj.id, function (err, found) { DateData.findById(obj.id, function(err, found) {
assert.equal(found.dateTime.toGMTString(), assert.equal(found.dateTime.toGMTString(),
'Fri, 09 Aug 1996 07:47:33 GMT'); 'Fri, 09 Aug 1996 07:47:33 GMT');
assert.equal(found.timestamp.toGMTString(), assert.equal(found.timestamp.toGMTString(),
@ -350,31 +350,29 @@ describe('migrations', function () {
}); });
}); });
it('should disconnect when done', function (done) { it('should disconnect when done', function(done) {
db.disconnect(); db.disconnect();
done(); done();
}); });
}); });
function setup(done) { function setup(done) {
require('./init.js'); require('./init.js');
db = getSchema(); db = getSchema();
UserData = db.define('UserData', { UserData = db.define('UserData', {
email: { type: String, null: false, index: true }, email: {type: String, null: false, index: true},
name: String, name: String,
bio: Schema.Text, bio: Schema.Text,
birthDate: Date, birthDate: Date,
pendingPeriod: Number, pendingPeriod: Number,
createdByAdmin: Boolean, createdByAdmin: Boolean,
}, { indexes: { }, {indexes: {
index0: { index0: {
columns: 'email, createdByAdmin' columns: 'email, createdByAdmin',
} },
} },
}); });
StringData = db.define('StringData', { StringData = db.define('StringData', {
@ -384,7 +382,7 @@ function setup(done) {
mediumString: {type: String, null: false, dataType: 'varchar', limit: 255}, mediumString: {type: String, null: false, dataType: 'varchar', limit: 255},
tinyText: {type: String, dataType: 'tinyText'}, tinyText: {type: String, dataType: 'tinyText'},
giantJSON: {type: Schema.JSON, dataType: 'longText'}, giantJSON: {type: Schema.JSON, dataType: 'longText'},
text: {type: Schema.Text, dataType: 'varchar', limit: 1024} text: {type: Schema.Text, dataType: 'varchar', limit: 1024},
}); });
NumberData = db.define('NumberData', { NumberData = db.define('NumberData', {
@ -393,12 +391,12 @@ function setup(done) {
tinyInt: {type: Number, dataType: 'tinyInt', display: 2}, tinyInt: {type: Number, dataType: 'tinyInt', display: 2},
mediumInt: {type: Number, dataType: 'mediumInt', unsigned: true, mediumInt: {type: Number, dataType: 'mediumInt', unsigned: true,
required: true}, required: true},
floater: {type: Number, dataType: 'double', precision: 14, scale: 6} floater: {type: Number, dataType: 'double', precision: 14, scale: 6},
}); });
DateData = db.define('DateData', { DateData = db.define('DateData', {
dateTime: {type: Date, dataType: 'datetime'}, dateTime: {type: Date, dataType: 'datetime'},
timestamp: {type: Date, dataType: 'timestamp'} timestamp: {type: Date, dataType: 'timestamp'},
}); });
query('SELECT VERSION()', function(err, res) { query('SELECT VERSION()', function(err, res) {
@ -407,15 +405,15 @@ function setup(done) {
}); });
} }
var query = function (sql, cb) { var query = function(sql, cb) {
db.adapter.execute(sql, cb); db.adapter.execute(sql, cb);
}; };
var blankDatabase = function (db, cb) { var blankDatabase = function(db, cb) {
var dbn = db.settings.database; var dbn = db.settings.database;
var cs = db.settings.charset; var cs = db.settings.charset;
var co = db.settings.collation; var co = db.settings.collation;
query('DROP DATABASE IF EXISTS ' + dbn, function (err) { query('DROP DATABASE IF EXISTS ' + dbn, function(err) {
var q = 'CREATE DATABASE ' + dbn; var q = 'CREATE DATABASE ' + dbn;
if (cs) { if (cs) {
q += ' CHARACTER SET ' + cs; q += ' CHARACTER SET ' + cs;
@ -423,46 +421,40 @@ var blankDatabase = function (db, cb) {
if (co) { if (co) {
q += ' COLLATE ' + co; q += ' COLLATE ' + co;
} }
query(q, function (err) { query(q, function(err) {
query('USE ' + dbn, cb); query('USE ' + dbn, cb);
}); });
}); });
}; };
getFields = function (model, cb) { var getFields = function(model, cb) {
query('SHOW FIELDS FROM ' + model, function (err, res) { query('SHOW FIELDS FROM ' + model, function(err, res) {
if (err) { if (err) {
cb(err); cb(err);
} else { } else {
var fields = {}; var fields = {};
res.forEach(function (field) { res.forEach(function(field) {
fields[field.Field] = field; fields[field.Field] = field;
}); });
cb(err, fields); cb(err, fields);
} }
}); });
} };
getIndexes = function (model, cb) { var getIndexes = function(model, cb) {
query('SHOW INDEXES FROM ' + model, function (err, res) { query('SHOW INDEXES FROM ' + model, function(err, res) {
if (err) { if (err) {
console.log(err); console.log(err);
cb(err); cb(err);
} else { } else {
var indexes = {}; var indexes = {};
// Note: this will only show the first key of compound keys // Note: this will only show the first key of compound keys
res.forEach(function (index) { res.forEach(function(index) {
if (parseInt(index.Seq_in_index, 10) == 1) { if (parseInt(index.Seq_in_index, 10) == 1) {
indexes[index.Key_name] = index indexes[index.Key_name] = index;
} }
}); });
cb(err, indexes); cb(err, indexes);
} }
}); });
}; };

View File

@ -3,97 +3,96 @@
// This file is licensed under the MIT License. // This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict';
var assert = require('assert'); var assert = require('assert');
require('./init'); require('./init');
var ds; var ds;
before(function () { before(function() {
ds = getDataSource(); ds = getDataSource();
}); });
describe('MySQL connector', function () { describe('MySQL connector', function() {
it('should auto migrate/update tables', function (done) { it('should auto migrate/update tables', function(done) {
var schema_v1 = var schema_v1 =
{ {
"name": "CustomerTest", 'name': 'CustomerTest',
"options": { 'options': {
"idInjection": false, 'idInjection': false,
"mysql": { 'mysql': {
"schema": "myapp_test", 'schema': 'myapp_test',
"table": "customer_test" 'table': 'customer_test',
} },
},
"properties": {
"id": {
"type": "String",
"length": 20,
"id": 1
}, },
"name": { 'properties': {
"type": "String", 'id': {
"required": false, 'type': 'String',
"length": 40 'length': 20,
'id': 1,
},
'name': {
'type': 'String',
'required': false,
'length': 40,
},
'email': {
'type': 'String',
'required': true,
'length': 40,
},
'age': {
'type': 'Number',
'required': false,
},
}, },
"email": { };
"type": "String",
"required": true,
"length": 40
},
"age": {
"type": "Number",
"required": false
}
}
}
var schema_v2 = var schema_v2 =
{ {
"name": "CustomerTest", 'name': 'CustomerTest',
"options": { 'options': {
"idInjection": false, 'idInjection': false,
"mysql": { 'mysql': {
"schema": "myapp_test", 'schema': 'myapp_test',
"table": "customer_test" 'table': 'customer_test',
} },
},
"properties": {
"id": {
"type": "String",
"length": 20,
"id": 1
}, },
"email": { 'properties': {
"type": "String", 'id': {
"required": false, 'type': 'String',
"length": 60, 'length': 20,
"mysql": { 'id': 1,
"columnName": "email", },
"dataType": "varchar", 'email': {
"dataLength": 60, 'type': 'String',
"nullable": "YES" 'required': false,
} 'length': 60,
'mysql': {
'columnName': 'email',
'dataType': 'varchar',
'dataLength': 60,
'nullable': 'YES',
},
},
'firstName': {
'type': 'String',
'required': false,
'length': 40,
},
'lastName': {
'type': 'String',
'required': false,
'length': 40,
},
}, },
"firstName": { };
"type": "String",
"required": false,
"length": 40
},
"lastName": {
"type": "String",
"required": false,
"length": 40
}
}
}
ds.createModel(schema_v1.name, schema_v1.properties, schema_v1.options); ds.createModel(schema_v1.name, schema_v1.properties, schema_v1.options);
ds.automigrate(function () { ds.automigrate(function() {
ds.discoverModelProperties('customer_test', function(err, props) {
ds.discoverModelProperties('customer_test', function (err, props) {
assert.equal(props.length, 4); assert.equal(props.length, 4);
var names = props.map(function (p) { var names = props.map(function(p) {
return p.columnName; return p.columnName;
}); });
assert.equal(props[0].nullable, 'N'); assert.equal(props[0].nullable, 'N');
@ -107,10 +106,10 @@ describe('MySQL connector', function () {
ds.createModel(schema_v2.name, schema_v2.properties, schema_v2.options); ds.createModel(schema_v2.name, schema_v2.properties, schema_v2.options);
ds.autoupdate(function (err, result) { ds.autoupdate(function(err, result) {
ds.discoverModelProperties('customer_test', function (err, props) { ds.discoverModelProperties('customer_test', function(err, props) {
assert.equal(props.length, 4); assert.equal(props.length, 4);
var names = props.map(function (p) { var names = props.map(function(p) {
return p.columnName; return p.columnName;
}); });
assert.equal(names[0], 'id'); assert.equal(names[0], 'id');
@ -137,6 +136,4 @@ describe('MySQL connector', function () {
done(); done();
}); });
}); });
}); });

View File

@ -3,6 +3,7 @@
// This file is licensed under the MIT License. // This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict';
process.env.NODE_ENV = 'test'; process.env.NODE_ENV = 'test';
require('should'); require('should');
@ -10,14 +11,14 @@ var assert = require('assert');
var DataSource = require('loopback-datasource-juggler').DataSource; var DataSource = require('loopback-datasource-juggler').DataSource;
var db, config; var db, config;
before(function () { before(function() {
require('./init'); require('./init');
config = getConfig(); config = getConfig();
config.database = 'STRONGLOOP'; config.database = 'STRONGLOOP';
db = new DataSource(require('../'), config); db = new DataSource(require('../'), config);
}); });
describe('discoverModels', function () { describe('discoverModels', function() {
describe('Discover database schemas', function() { describe('Discover database schemas', function() {
it('should return an array of db schemas', function(done) { it('should return an array of db schemas', function(done) {
db.connector.discoverDatabaseSchemas(function(err, schemas) { db.connector.discoverDatabaseSchemas(function(err, schemas) {
@ -29,19 +30,18 @@ describe('discoverModels', function () {
}); });
}); });
describe('Discover models including views', function () { describe('Discover models including views', function() {
it('should return an array of tables and views', function (done) { it('should return an array of tables and views', function(done) {
db.discoverModelDefinitions({ db.discoverModelDefinitions({
views: true, views: true,
limit: 3 limit: 3,
}, function (err, models) { }, function(err, models) {
if (err) { if (err) {
console.error(err); console.error(err);
done(err); done(err);
} else { } else {
var views = false; var views = false;
models.forEach(function (m) { models.forEach(function(m) {
// console.dir(m); // console.dir(m);
if (m.type === 'view') { if (m.type === 'view') {
views = true; views = true;
@ -54,18 +54,17 @@ describe('discoverModels', function () {
}); });
}); });
describe('Discover current user\'s tables', function () { describe('Discover current user\'s tables', function() {
it('should return an array of tables for the current user', function (done) { it('should return an array of tables for the current user', function(done) {
db.discoverModelDefinitions({ db.discoverModelDefinitions({
limit: 3 limit: 3,
}, function (err, models) { }, function(err, models) {
if (err) { if (err) {
console.error(err); console.error(err);
done(err); done(err);
} else { } else {
var views = false; var views = false;
models.forEach(function (m) { models.forEach(function(m) {
assert.equal(m.owner, config.username); assert.equal(m.owner, config.username);
}); });
done(null, models); done(null, models);
@ -74,20 +73,19 @@ describe('discoverModels', function () {
}); });
}); });
describe('Discover models excluding views', function () { describe('Discover models excluding views', function() {
// TODO: this test assumes the current user owns the tables // TODO: this test assumes the current user owns the tables
it.skip('should return an array of only tables', function (done) { it.skip('should return an array of only tables', function(done) {
db.discoverModelDefinitions({ db.discoverModelDefinitions({
views: false, views: false,
limit: 3 limit: 3,
}, function (err, models) { }, function(err, models) {
if (err) { if (err) {
console.error(err); console.error(err);
done(err); done(err);
} else { } else {
var views = false; var views = false;
models.forEach(function (m) { models.forEach(function(m) {
// console.dir(m); // console.dir(m);
if (m.type === 'view') { if (m.type === 'view') {
views = true; views = true;
@ -102,19 +100,18 @@ describe('discoverModels', function () {
}); });
}); });
describe('Discover models including other users', function () { describe('Discover models including other users', function() {
it('should return an array of all tables and views', function (done) { it('should return an array of all tables and views', function(done) {
db.discoverModelDefinitions({ db.discoverModelDefinitions({
all: true, all: true,
limit: 3 limit: 3,
}, function (err, models) { }, function(err, models) {
if (err) { if (err) {
console.error(err); console.error(err);
done(err); done(err);
} else { } else {
var others = false; var others = false;
models.forEach(function (m) { models.forEach(function(m) {
// console.dir(m); // console.dir(m);
if (m.owner !== 'STRONGLOOP') { if (m.owner !== 'STRONGLOOP') {
others = true; others = true;
@ -127,15 +124,15 @@ describe('Discover models including other users', function () {
}); });
}); });
describe('Discover model properties', function () { describe('Discover model properties', function() {
describe('Discover a named model', function () { describe('Discover a named model', function() {
it('should return an array of columns for product', function (done) { it('should return an array of columns for product', function(done) {
db.discoverModelProperties('product', function (err, models) { db.discoverModelProperties('product', function(err, models) {
if (err) { if (err) {
console.error(err); console.error(err);
done(err); done(err);
} else { } else {
models.forEach(function (m) { models.forEach(function(m) {
// console.dir(m); // console.dir(m);
assert(m.tableName === 'product'); assert(m.tableName === 'product');
}); });
@ -144,17 +141,16 @@ describe('Discover model properties', function () {
}); });
}); });
}); });
}); });
describe('Discover model primary keys', function () { describe('Discover model primary keys', function() {
it('should return an array of primary keys for product', function (done) { it('should return an array of primary keys for product', function(done) {
db.discoverPrimaryKeys('product', function (err, models) { db.discoverPrimaryKeys('product', function(err, models) {
if (err) { if (err) {
console.error(err); console.error(err);
done(err); done(err);
} else { } else {
models.forEach(function (m) { models.forEach(function(m) {
// console.dir(m); // console.dir(m);
assert(m.tableName === 'product'); assert(m.tableName === 'product');
}); });
@ -163,13 +159,13 @@ describe('Discover model primary keys', function () {
}); });
}); });
it('should return an array of primary keys for STRONGLOOP.PRODUCT', function (done) { it('should return an array of primary keys for STRONGLOOP.PRODUCT', function(done) {
db.discoverPrimaryKeys('product', {owner: 'STRONGLOOP'}, function (err, models) { db.discoverPrimaryKeys('product', {owner: 'STRONGLOOP'}, function(err, models) {
if (err) { if (err) {
console.error(err); console.error(err);
done(err); done(err);
} else { } else {
models.forEach(function (m) { models.forEach(function(m) {
// console.dir(m); // console.dir(m);
assert(m.tableName === 'product'); assert(m.tableName === 'product');
}); });
@ -179,14 +175,14 @@ describe('Discover model primary keys', function () {
}); });
}); });
describe('Discover model foreign keys', function () { describe('Discover model foreign keys', function() {
it('should return an array of foreign keys for INVENTORY', function (done) { it('should return an array of foreign keys for INVENTORY', function(done) {
db.discoverForeignKeys('INVENTORY', function (err, models) { db.discoverForeignKeys('INVENTORY', function(err, models) {
if (err) { if (err) {
console.error(err); console.error(err);
done(err); done(err);
} else { } else {
models.forEach(function (m) { models.forEach(function(m) {
// console.dir(m); // console.dir(m);
assert(m.fkTableName === 'INVENTORY'); assert(m.fkTableName === 'INVENTORY');
}); });
@ -194,13 +190,13 @@ describe('Discover model foreign keys', function () {
} }
}); });
}); });
it('should return an array of foreign keys for STRONGLOOP.INVENTORY', function (done) { it('should return an array of foreign keys for STRONGLOOP.INVENTORY', function(done) {
db.discoverForeignKeys('INVENTORY', {owner: 'STRONGLOOP'}, function (err, models) { db.discoverForeignKeys('INVENTORY', {owner: 'STRONGLOOP'}, function(err, models) {
if (err) { if (err) {
console.error(err); console.error(err);
done(err); done(err);
} else { } else {
models.forEach(function (m) { models.forEach(function(m) {
// console.dir(m); // console.dir(m);
assert(m.fkTableName === 'INVENTORY'); assert(m.fkTableName === 'INVENTORY');
}); });
@ -210,15 +206,15 @@ describe('Discover model foreign keys', function () {
}); });
}); });
describe('Discover LDL schema from a table', function () { describe('Discover LDL schema from a table', function() {
var schema; var schema;
before(function (done) { before(function(done) {
db.discoverSchema('INVENTORY', {owner: 'STRONGLOOP'}, function (err, schema_) { db.discoverSchema('INVENTORY', {owner: 'STRONGLOOP'}, function(err, schema_) {
schema = schema_; schema = schema_;
done(err); done(err);
}); });
}); });
it('should return an LDL schema for INVENTORY', function () { it('should return an LDL schema for INVENTORY', function() {
var productId = 'productId' in schema.properties ? 'productId' : 'productid'; var productId = 'productId' in schema.properties ? 'productId' : 'productid';
var locationId = 'locationId' in schema.properties ? 'locationId' : 'locationid'; var locationId = 'locationId' in schema.properties ? 'locationId' : 'locationid';
console.error('schema:', schema); console.error('schema:', schema);
@ -241,15 +237,16 @@ describe('Discover LDL schema from a table', function () {
}); });
}); });
describe('Discover and build models', function () { describe('Discover and build models', function() {
var models; var models;
before(function (done) { before(function(done) {
db.discoverAndBuildModels('INVENTORY', {owner: 'STRONGLOOP', visited: {}, associations: true}, function (err, models_) { db.discoverAndBuildModels('INVENTORY', {owner: 'STRONGLOOP', visited: {}, associations: true},
models = models_; function(err, models_) {
done(err); models = models_;
}); done(err);
});
}); });
it('should discover and build models', function () { it('should discover and build models', function() {
assert(models.Inventory, 'Inventory model should be discovered and built'); assert(models.Inventory, 'Inventory model should be discovered and built');
var schema = models.Inventory.definition; var schema = models.Inventory.definition;
var productId = 'productId' in schema.properties ? 'productId' : 'productid'; var productId = 'productId' in schema.properties ? 'productId' : 'productid';
@ -267,9 +264,9 @@ describe('Discover and build models', function () {
assert(schema.properties.total); assert(schema.properties.total);
assert.strictEqual(schema.properties.total.type, Number); assert.strictEqual(schema.properties.total.type, Number);
}); });
it('should be able to find an instance', function (done) { it('should be able to find an instance', function(done) {
assert(models.Inventory, 'Inventory model must exist'); assert(models.Inventory, 'Inventory model must exist');
models.Inventory.findOne(function (err, inv) { models.Inventory.findOne(function(err, inv) {
assert(!err, 'error should not be reported'); assert(!err, 'error should not be reported');
done(); done();
}); });

View File

@ -3,6 +3,7 @@
// This file is licensed under the MIT License. // This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict';
var should = require('./init.js'); var should = require('./init.js');
var Post, PostWithStringId, PostWithUniqueTitle, db; var Post, PostWithStringId, PostWithUniqueTitle, db;
@ -20,51 +21,49 @@ ObjectID.prototype.toJSON = function() {
return this.id1 + this.id2; return this.id1 + this.id2;
}; };
describe('mysql', function () { describe('mysql', function() {
before(function(done) {
before(function (done) {
db = getDataSource(); db = getDataSource();
Post = db.define('PostWithDefaultId', { Post = db.define('PostWithDefaultId', {
title: { type: String, length: 255, index: true }, title: {type: String, length: 255, index: true},
content: { type: String }, content: {type: String},
comments: [String], comments: [String],
history: Object, history: Object,
stars: Number, stars: Number,
userId: ObjectID userId: ObjectID,
}); });
PostWithStringId = db.define('PostWithStringId', { PostWithStringId = db.define('PostWithStringId', {
id: {type: String, id: true}, id: {type: String, id: true},
title: { type: String, length: 255, index: true }, title: {type: String, length: 255, index: true},
content: { type: String } content: {type: String},
}); });
PostWithUniqueTitle = db.define('PostWithUniqueTitle', { PostWithUniqueTitle = db.define('PostWithUniqueTitle', {
title: { type: String, length: 255, index: {unique: true} }, title: {type: String, length: 255, index: {unique: true}},
content: { type: String } content: {type: String},
}); });
db.automigrate(['PostWithDefaultId', 'PostWithStringId', 'PostWithUniqueTitle'], function (err) { db.automigrate(['PostWithDefaultId', 'PostWithStringId', 'PostWithUniqueTitle'], function(err) {
should.not.exist(err); should.not.exist(err);
done(err); done(err);
}); });
}); });
beforeEach(function (done) { beforeEach(function(done) {
Post.destroyAll(function () { Post.destroyAll(function() {
PostWithStringId.destroyAll(function () { PostWithStringId.destroyAll(function() {
PostWithUniqueTitle.destroyAll(function () { PostWithUniqueTitle.destroyAll(function() {
done(); done();
}); });
}); });
}); });
}); });
it('should allow array or object', function (done) { it('should allow array or object', function(done) {
Post.create({title: 'a', content: 'AAA', comments: ['1', '2'], Post.create({title: 'a', content: 'AAA', comments: ['1', '2'],
history: {a: 1, b: 'b'}}, function(err, post) { history: {a: 1, b: 'b'}}, function(err, post) {
should.not.exist(err); should.not.exist(err);
Post.findById(post.id, function(err, p) { Post.findById(post.id, function(err, p) {
@ -84,7 +83,6 @@ describe('mysql', function () {
var uid = new ObjectID('123'); var uid = new ObjectID('123');
Post.create({title: 'a', content: 'AAA', userId: uid}, Post.create({title: 'a', content: 'AAA', userId: uid},
function(err, post) { function(err, post) {
should.not.exist(err); should.not.exist(err);
Post.findById(post.id, function(err, p) { Post.findById(post.id, function(err, p) {
@ -98,15 +96,15 @@ describe('mysql', function () {
}); });
}); });
it('updateOrCreate should update the instance', function (done) { it('updateOrCreate should update the instance', function(done) {
Post.create({title: 'a', content: 'AAA'}, function (err, post) { Post.create({title: 'a', content: 'AAA'}, function(err, post) {
post.title = 'b'; post.title = 'b';
Post.updateOrCreate(post, function (err, p) { Post.updateOrCreate(post, function(err, p) {
should.not.exist(err); should.not.exist(err);
p.id.should.be.equal(post.id); p.id.should.be.equal(post.id);
p.content.should.be.equal(post.content); p.content.should.be.equal(post.content);
Post.findById(post.id, function (err, p) { Post.findById(post.id, function(err, p) {
p.id.should.be.equal(post.id); p.id.should.be.equal(post.id);
p.content.should.be.equal(post.content); p.content.should.be.equal(post.content);
@ -115,19 +113,18 @@ describe('mysql', function () {
done(); done();
}); });
}); });
}); });
}); });
it('updateOrCreate should update the instance without removing existing properties', function (done) { it('updateOrCreate should update the instance without removing existing properties', function(done) {
Post.create({title: 'a', content: 'AAA'}, function (err, post) { Post.create({title: 'a', content: 'AAA'}, function(err, post) {
post = post.toObject(); post = post.toObject();
delete post.title; delete post.title;
Post.updateOrCreate(post, function (err, p) { Post.updateOrCreate(post, function(err, p) {
should.not.exist(err); should.not.exist(err);
p.id.should.be.equal(post.id); p.id.should.be.equal(post.id);
p.content.should.be.equal(post.content); p.content.should.be.equal(post.content);
Post.findById(post.id, function (err, p) { Post.findById(post.id, function(err, p) {
p.id.should.be.equal(post.id); p.id.should.be.equal(post.id);
p.content.should.be.equal(post.content); p.content.should.be.equal(post.content);
@ -136,19 +133,18 @@ describe('mysql', function () {
done(); done();
}); });
}); });
}); });
}); });
it('updateOrCreate should create a new instance if it does not exist', function (done) { it('updateOrCreate should create a new instance if it does not exist', function(done) {
var post = {id: 123, title: 'a', content: 'AAA'}; var post = {id: 123, title: 'a', content: 'AAA'};
Post.updateOrCreate(post, function (err, p) { Post.updateOrCreate(post, function(err, p) {
should.not.exist(err); should.not.exist(err);
p.title.should.be.equal(post.title); p.title.should.be.equal(post.title);
p.content.should.be.equal(post.content); p.content.should.be.equal(post.content);
p.id.should.be.equal(post.id); p.id.should.be.equal(post.id);
Post.findById(p.id, function (err, p) { Post.findById(p.id, function(err, p) {
p.id.should.be.equal(post.id); p.id.should.be.equal(post.id);
p.content.should.be.equal(post.content); p.content.should.be.equal(post.content);
@ -158,7 +154,6 @@ describe('mysql', function () {
done(); done();
}); });
}); });
}); });
context('replaceOrCreate', function() { context('replaceOrCreate', function() {
@ -170,13 +165,13 @@ describe('mysql', function () {
Post.replaceOrCreate(post, function(err, p) { Post.replaceOrCreate(post, function(err, p) {
if (err) return done(err); if (err) return done(err);
p.id.should.equal(post.id); p.id.should.equal(post.id);
p.title.should.equal('a'); p.title.should.equal('a');
should.not.exist(p.content); should.not.exist(p.content);
should.not.exist(p._id); should.not.exist(p._id);
Post.findById(post.id, function(err, p) { Post.findById(post.id, function(err, p) {
if (err) return done(err); if (err) return done(err);
p.id.should.equal(post.id); p.id.should.equal(post.id);
p.title.should.equal('a'); p.title.should.equal('a');
should.not.exist(post.content); should.not.exist(post.content);
should.not.exist(p._id); should.not.exist(p._id);
done(); done();
@ -197,7 +192,7 @@ describe('mysql', function () {
if (err) return done(err); if (err) return done(err);
p.id.should.equal(post.id); p.id.should.equal(post.id);
should.not.exist(p._id); should.not.exist(p._id);
p.title.should.equal('b'); p.title.should.equal('b');
should.not.exist(p.content); should.not.exist(p.content);
should.not.exist(p.comments); should.not.exist(p.comments);
Post.findById(post.id, function(err, p) { Post.findById(post.id, function(err, p) {
@ -233,15 +228,15 @@ describe('mysql', function () {
}); });
}); });
it('save should update the instance with the same id', function (done) { it('save should update the instance with the same id', function(done) {
Post.create({title: 'a', content: 'AAA'}, function (err, post) { Post.create({title: 'a', content: 'AAA'}, function(err, post) {
post.title = 'b'; post.title = 'b';
post.save(function (err, p) { post.save(function(err, p) {
should.not.exist(err); should.not.exist(err);
p.id.should.be.equal(post.id); p.id.should.be.equal(post.id);
p.content.should.be.equal(post.content); p.content.should.be.equal(post.content);
Post.findById(post.id, function (err, p) { Post.findById(post.id, function(err, p) {
p.id.should.be.equal(post.id); p.id.should.be.equal(post.id);
p.content.should.be.equal(post.content); p.content.should.be.equal(post.content);
@ -250,19 +245,18 @@ describe('mysql', function () {
done(); done();
}); });
}); });
}); });
}); });
it('save should update the instance without removing existing properties', function (done) { it('save should update the instance without removing existing properties', function(done) {
Post.create({title: 'a', content: 'AAA'}, function (err, post) { Post.create({title: 'a', content: 'AAA'}, function(err, post) {
delete post.title; delete post.title;
post.save(function (err, p) { post.save(function(err, p) {
should.not.exist(err); should.not.exist(err);
p.id.should.be.equal(post.id); p.id.should.be.equal(post.id);
p.content.should.be.equal(post.content); p.content.should.be.equal(post.content);
Post.findById(post.id, function (err, p) { Post.findById(post.id, function(err, p) {
p.id.should.be.equal(post.id); p.id.should.be.equal(post.id);
p.content.should.be.equal(post.content); p.content.should.be.equal(post.content);
@ -271,19 +265,18 @@ describe('mysql', function () {
done(); done();
}); });
}); });
}); });
}); });
it('save should create a new instance if it does not exist', function (done) { it('save should create a new instance if it does not exist', function(done) {
var post = new Post({id: 123, title: 'a', content: 'AAA'}); var post = new Post({id: 123, title: 'a', content: 'AAA'});
post.save(post, function (err, p) { post.save(post, function(err, p) {
should.not.exist(err); should.not.exist(err);
p.title.should.be.equal(post.title); p.title.should.be.equal(post.title);
p.content.should.be.equal(post.content); p.content.should.be.equal(post.content);
p.id.should.be.equal(post.id); p.id.should.be.equal(post.id);
Post.findById(p.id, function (err, p) { Post.findById(p.id, function(err, p) {
should.not.exist(err); should.not.exist(err);
p.id.should.be.equal(post.id); p.id.should.be.equal(post.id);
@ -294,13 +287,12 @@ describe('mysql', function () {
done(); done();
}); });
}); });
}); });
it('all return should honor filter.fields', function (done) { it('all return should honor filter.fields', function(done) {
var post = new Post({title: 'b', content: 'BBB'}) var post = new Post({title: 'b', content: 'BBB'});
post.save(function (err, post) { post.save(function(err, post) {
Post.all({fields: ['title'], where: {title: 'b'}}, function (err, posts) { Post.all({fields: ['title'], where: {title: 'b'}}, function(err, posts) {
should.not.exist(err); should.not.exist(err);
posts.should.have.lengthOf(1); posts.should.have.lengthOf(1);
post = posts[0]; post = posts[0];
@ -310,25 +302,24 @@ describe('mysql', function () {
done(); done();
}); });
}); });
}); });
it('find should order by id if the order is not set for the query filter', it('find should order by id if the order is not set for the query filter',
function (done) { function(done) {
PostWithStringId.create({id: '2', title: 'c', content: 'CCC'}, function (err, post) { PostWithStringId.create({id: '2', title: 'c', content: 'CCC'}, function(err, post) {
PostWithStringId.create({id: '1', title: 'd', content: 'DDD'}, function (err, post) { PostWithStringId.create({id: '1', title: 'd', content: 'DDD'}, function(err, post) {
PostWithStringId.find(function (err, posts) { PostWithStringId.find(function(err, posts) {
should.not.exist(err); should.not.exist(err);
posts.length.should.be.equal(2); posts.length.should.be.equal(2);
posts[0].id.should.be.equal('1'); posts[0].id.should.be.equal('1');
PostWithStringId.find({limit: 1, offset: 0}, function (err, posts) { PostWithStringId.find({limit: 1, offset: 0}, function(err, posts) {
should.not.exist(err); should.not.exist(err);
posts.length.should.be.equal(1); posts.length.should.be.equal(1);
posts[0].id.should.be.equal('1'); posts[0].id.should.be.equal('1');
PostWithStringId.find({limit: 1, offset: 1}, function (err, posts) { PostWithStringId.find({limit: 1, offset: 1}, function(err, posts) {
should.not.exist(err); should.not.exist(err);
posts.length.should.be.equal(1); posts.length.should.be.equal(1);
posts[0].id.should.be.equal('2'); posts[0].id.should.be.equal('2');
@ -340,9 +331,9 @@ describe('mysql', function () {
}); });
}); });
it('should allow to find using like', function (done) { it('should allow to find using like', function(done) {
Post.create({title: 'My Post', content: 'Hello'}, function (err, post) { Post.create({title: 'My Post', content: 'Hello'}, function(err, post) {
Post.find({where: {title: {like: 'M%st'}}}, function (err, posts) { Post.find({where: {title: {like: 'M%st'}}}, function(err, posts) {
should.not.exist(err); should.not.exist(err);
posts.should.have.property('length', 1); posts.should.have.property('length', 1);
done(); done();
@ -350,9 +341,9 @@ describe('mysql', function () {
}); });
}); });
it('should support like for no match', function (done) { it('should support like for no match', function(done) {
Post.create({title: 'My Post', content: 'Hello'}, function (err, post) { Post.create({title: 'My Post', content: 'Hello'}, function(err, post) {
Post.find({where: {title: {like: 'M%XY'}}}, function (err, posts) { Post.find({where: {title: {like: 'M%XY'}}}, function(err, posts) {
should.not.exist(err); should.not.exist(err);
posts.should.have.property('length', 0); posts.should.have.property('length', 0);
done(); done();
@ -360,9 +351,9 @@ describe('mysql', function () {
}); });
}); });
it('should allow to find using nlike', function (done) { it('should allow to find using nlike', function(done) {
Post.create({title: 'My Post', content: 'Hello'}, function (err, post) { Post.create({title: 'My Post', content: 'Hello'}, function(err, post) {
Post.find({where: {title: {nlike: 'M%st'}}}, function (err, posts) { Post.find({where: {title: {nlike: 'M%st'}}}, function(err, posts) {
should.not.exist(err); should.not.exist(err);
posts.should.have.property('length', 0); posts.should.have.property('length', 0);
done(); done();
@ -370,9 +361,9 @@ describe('mysql', function () {
}); });
}); });
it('should support nlike for no match', function (done) { it('should support nlike for no match', function(done) {
Post.create({title: 'My Post', content: 'Hello'}, function (err, post) { Post.create({title: 'My Post', content: 'Hello'}, function(err, post) {
Post.find({where: {title: {nlike: 'M%XY'}}}, function (err, posts) { Post.find({where: {title: {nlike: 'M%XY'}}}, function(err, posts) {
should.not.exist(err); should.not.exist(err);
posts.should.have.property('length', 1); posts.should.have.property('length', 1);
done(); done();
@ -380,12 +371,12 @@ describe('mysql', function () {
}); });
}); });
it('should support "and" operator that is satisfied', function (done) { it('should support "and" operator that is satisfied', function(done) {
Post.create({title: 'My Post', content: 'Hello'}, function (err, post) { Post.create({title: 'My Post', content: 'Hello'}, function(err, post) {
Post.find({where: {and: [ Post.find({where: {and: [
{title: 'My Post'}, {title: 'My Post'},
{content: 'Hello'} {content: 'Hello'},
]}}, function (err, posts) { ]}}, function(err, posts) {
should.not.exist(err); should.not.exist(err);
posts.should.have.property('length', 1); posts.should.have.property('length', 1);
done(); done();
@ -393,12 +384,12 @@ describe('mysql', function () {
}); });
}); });
it('should support "and" operator that is not satisfied', function (done) { it('should support "and" operator that is not satisfied', function(done) {
Post.create({title: 'My Post', content: 'Hello'}, function (err, post) { Post.create({title: 'My Post', content: 'Hello'}, function(err, post) {
Post.find({where: {and: [ Post.find({where: {and: [
{title: 'My Post'}, {title: 'My Post'},
{content: 'Hello1'} {content: 'Hello1'},
]}}, function (err, posts) { ]}}, function(err, posts) {
should.not.exist(err); should.not.exist(err);
posts.should.have.property('length', 0); posts.should.have.property('length', 0);
done(); done();
@ -406,12 +397,12 @@ describe('mysql', function () {
}); });
}); });
it('should support "or" that is satisfied', function (done) { it('should support "or" that is satisfied', function(done) {
Post.create({title: 'My Post', content: 'Hello'}, function (err, post) { Post.create({title: 'My Post', content: 'Hello'}, function(err, post) {
Post.find({where: {or: [ Post.find({where: {or: [
{title: 'My Post'}, {title: 'My Post'},
{content: 'Hello1'} {content: 'Hello1'},
]}}, function (err, posts) { ]}}, function(err, posts) {
should.not.exist(err); should.not.exist(err);
posts.should.have.property('length', 1); posts.should.have.property('length', 1);
done(); done();
@ -419,12 +410,12 @@ describe('mysql', function () {
}); });
}); });
it('should support "or" operator that is not satisfied', function (done) { it('should support "or" operator that is not satisfied', function(done) {
Post.create({title: 'My Post', content: 'Hello'}, function (err, post) { Post.create({title: 'My Post', content: 'Hello'}, function(err, post) {
Post.find({where: {or: [ Post.find({where: {or: [
{title: 'My Post1'}, {title: 'My Post1'},
{content: 'Hello1'} {content: 'Hello1'},
]}}, function (err, posts) { ]}}, function(err, posts) {
should.not.exist(err); should.not.exist(err);
posts.should.have.property('length', 0); posts.should.have.property('length', 0);
done(); done();
@ -433,18 +424,18 @@ describe('mysql', function () {
}); });
// The where object should be parsed by the connector // The where object should be parsed by the connector
it('should support where for count', function (done) { it('should support where for count', function(done) {
Post.create({title: 'My Post', content: 'Hello'}, function (err, post) { Post.create({title: 'My Post', content: 'Hello'}, function(err, post) {
Post.count({and: [ Post.count({and: [
{title: 'My Post'}, {title: 'My Post'},
{content: 'Hello'} {content: 'Hello'},
]}, function (err, count) { ]}, function(err, count) {
should.not.exist(err); should.not.exist(err);
count.should.be.equal(1); count.should.be.equal(1);
Post.count({and: [ Post.count({and: [
{title: 'My Post1'}, {title: 'My Post1'},
{content: 'Hello'} {content: 'Hello'},
]}, function (err, count) { ]}, function(err, count) {
should.not.exist(err); should.not.exist(err);
count.should.be.equal(0); count.should.be.equal(0);
done(); done();
@ -454,15 +445,15 @@ describe('mysql', function () {
}); });
// The where object should be parsed by the connector // The where object should be parsed by the connector
it('should support where for destroyAll', function (done) { it('should support where for destroyAll', function(done) {
Post.create({title: 'My Post1', content: 'Hello'}, function (err, post) { Post.create({title: 'My Post1', content: 'Hello'}, function(err, post) {
Post.create({title: 'My Post2', content: 'Hello'}, function (err, post) { Post.create({title: 'My Post2', content: 'Hello'}, function(err, post) {
Post.destroyAll({and: [ Post.destroyAll({and: [
{title: 'My Post1'}, {title: 'My Post1'},
{content: 'Hello'} {content: 'Hello'},
]}, function (err) { ]}, function(err) {
should.not.exist(err); should.not.exist(err);
Post.count(function (err, count) { Post.count(function(err, count) {
should.not.exist(err); should.not.exist(err);
count.should.be.equal(1); count.should.be.equal(1);
done(); done();
@ -472,13 +463,13 @@ describe('mysql', function () {
}); });
}); });
it('should not allow SQL injection for inq operator', function (done) { it('should not allow SQL injection for inq operator', function(done) {
Post.create({title: 'My Post1', content: 'Hello', stars: 5}, Post.create({title: 'My Post1', content: 'Hello', stars: 5},
function (err, post) { function(err, post) {
Post.create({title: 'My Post2', content: 'Hello', stars: 20}, Post.create({title: 'My Post2', content: 'Hello', stars: 20},
function (err, post) { function(err, post) {
Post.find({where: {title: {inq: ['SELECT title from PostWithDefaultId']}}}, Post.find({where: {title: {inq: ['SELECT title from PostWithDefaultId']}}},
function (err, posts) { function(err, posts) {
should.not.exist(err); should.not.exist(err);
posts.should.have.property('length', 0); posts.should.have.property('length', 0);
done(); done();
@ -487,13 +478,13 @@ describe('mysql', function () {
}); });
}); });
it('should not allow SQL injection for lt operator', function (done) { it('should not allow SQL injection for lt operator', function(done) {
Post.create({title: 'My Post1', content: 'Hello', stars: 5}, Post.create({title: 'My Post1', content: 'Hello', stars: 5},
function (err, post) { function(err, post) {
Post.create({title: 'My Post2', content: 'Hello', stars: 20}, Post.create({title: 'My Post2', content: 'Hello', stars: 20},
function (err, post) { function(err, post) {
Post.find({where: {stars: {lt: 'SELECT title from PostWithDefaultId'}}}, Post.find({where: {stars: {lt: 'SELECT title from PostWithDefaultId'}}},
function (err, posts) { function(err, posts) {
should.not.exist(err); should.not.exist(err);
posts.should.have.property('length', 0); posts.should.have.property('length', 0);
done(); done();
@ -502,13 +493,13 @@ describe('mysql', function () {
}); });
}); });
it('should not allow SQL injection for nin operator', function (done) { it('should not allow SQL injection for nin operator', function(done) {
Post.create({title: 'My Post1', content: 'Hello', stars: 5}, Post.create({title: 'My Post1', content: 'Hello', stars: 5},
function (err, post) { function(err, post) {
Post.create({title: 'My Post2', content: 'Hello', stars: 20}, Post.create({title: 'My Post2', content: 'Hello', stars: 20},
function (err, post) { function(err, post) {
Post.find({where: {title: {nin: ['SELECT title from PostWithDefaultId']}}}, Post.find({where: {title: {nin: ['SELECT title from PostWithDefaultId']}}},
function (err, posts) { function(err, posts) {
should.not.exist(err); should.not.exist(err);
posts.should.have.property('length', 2); posts.should.have.property('length', 2);
done(); done();
@ -517,14 +508,13 @@ describe('mysql', function () {
}); });
}); });
it('should not allow SQL injection for inq operator with number column', function(done) {
it('should not allow SQL injection for inq operator with number column', function (done) {
Post.create({title: 'My Post1', content: 'Hello', stars: 5}, Post.create({title: 'My Post1', content: 'Hello', stars: 5},
function (err, post) { function(err, post) {
Post.create({title: 'My Post2', content: 'Hello', stars: 20}, Post.create({title: 'My Post2', content: 'Hello', stars: 20},
function (err, post) { function(err, post) {
Post.find({where: {stars: {inq: ['SELECT title from PostWithDefaultId']}}}, Post.find({where: {stars: {inq: ['SELECT title from PostWithDefaultId']}}},
function (err, posts) { function(err, posts) {
should.not.exist(err); should.not.exist(err);
posts.should.have.property('length', 0); posts.should.have.property('length', 0);
done(); done();
@ -533,13 +523,13 @@ describe('mysql', function () {
}); });
}); });
it('should not allow SQL injection for inq operator with array value', function (done) { it('should not allow SQL injection for inq operator with array value', function(done) {
Post.create({title: 'My Post1', content: 'Hello', stars: 5}, Post.create({title: 'My Post1', content: 'Hello', stars: 5},
function (err, post) { function(err, post) {
Post.create({title: 'My Post2', content: 'Hello', stars: 20}, Post.create({title: 'My Post2', content: 'Hello', stars: 20},
function (err, post) { function(err, post) {
Post.find({where: {stars: {inq: [5, 'SELECT title from PostWithDefaultId']}}}, Post.find({where: {stars: {inq: [5, 'SELECT title from PostWithDefaultId']}}},
function (err, posts) { function(err, posts) {
should.not.exist(err); should.not.exist(err);
posts.should.have.property('length', 1); posts.should.have.property('length', 1);
done(); done();
@ -548,13 +538,13 @@ describe('mysql', function () {
}); });
}); });
it('should not allow SQL injection for between operator', function (done) { it('should not allow SQL injection for between operator', function(done) {
Post.create({title: 'My Post1', content: 'Hello', stars: 5}, Post.create({title: 'My Post1', content: 'Hello', stars: 5},
function (err, post) { function(err, post) {
Post.create({title: 'My Post2', content: 'Hello', stars: 20}, Post.create({title: 'My Post2', content: 'Hello', stars: 20},
function (err, post) { function(err, post) {
Post.find({where: {stars: {between: [5, 'SELECT title from PostWithDefaultId']}}}, Post.find({where: {stars: {between: [5, 'SELECT title from PostWithDefaultId']}}},
function (err, posts) { function(err, posts) {
should.not.exist(err); should.not.exist(err);
posts.should.have.property('length', 0); posts.should.have.property('length', 0);
done(); done();
@ -563,11 +553,11 @@ describe('mysql', function () {
}); });
}); });
it('should not allow duplicate titles', function (done) { it('should not allow duplicate titles', function(done) {
var data = {title: 'a', content: 'AAA'}; var data = {title: 'a', content: 'AAA'};
PostWithUniqueTitle.create(data, function (err, post) { PostWithUniqueTitle.create(data, function(err, post) {
should.not.exist(err); should.not.exist(err);
PostWithUniqueTitle.create(data, function (err, post) { PostWithUniqueTitle.create(data, function(err, post) {
should.exist(err); should.exist(err);
done(); done();
}); });
@ -581,7 +571,7 @@ describe('mysql', function () {
beforeEach(function createTestFixtures(done) { beforeEach(function createTestFixtures(done) {
Post.create([ Post.create([
{title: 'a', content: 'AAA'}, {title: 'a', content: 'AAA'},
{title: 'b', content: 'BBB'} {title: 'b', content: 'BBB'},
], done); ], done);
}); });
after(function deleteTestFixtures(done) { after(function deleteTestFixtures(done) {
@ -619,27 +609,27 @@ describe('mysql', function () {
it('should print a warning when the ignore flag is set', it('should print a warning when the ignore flag is set',
function(done) { function(done) {
Post.find({where: {content: {regexp: '^a/i'}}}, function(err, posts) { Post.find({where: {content: {regexp: '^a/i'}}}, function(err, posts) {
console.warn.calledOnce.should.be.ok; console.warn.calledOnce.should.be.ok;
done(); done();
}); });
}); });
it('should print a warning when the global flag is set', it('should print a warning when the global flag is set',
function(done) { function(done) {
Post.find({where: {content: {regexp: '^a/g'}}}, function(err, posts) { Post.find({where: {content: {regexp: '^a/g'}}}, function(err, posts) {
console.warn.calledOnce.should.be.ok; console.warn.calledOnce.should.be.ok;
done(); done();
}); });
}); });
it('should print a warning when the multiline flag is set', it('should print a warning when the multiline flag is set',
function(done) { function(done) {
Post.find({where: {content: {regexp: '^a/m'}}}, function(err, posts) { Post.find({where: {content: {regexp: '^a/m'}}}, function(err, posts) {
console.warn.calledOnce.should.be.ok; console.warn.calledOnce.should.be.ok;
done(); done();
}); });
}); });
}); });
}); });
@ -674,27 +664,27 @@ describe('mysql', function () {
it('should print a warning when the ignore flag is set', it('should print a warning when the ignore flag is set',
function(done) { function(done) {
Post.find({where: {content: {regexp: /^a/i}}}, function(err, posts) { Post.find({where: {content: {regexp: /^a/i}}}, function(err, posts) {
console.warn.calledOnce.should.be.ok; console.warn.calledOnce.should.be.ok;
done(); done();
}); });
}); });
it('should print a warning when the global flag is set', it('should print a warning when the global flag is set',
function(done) { function(done) {
Post.find({where: {content: {regexp: /^a/g}}}, function(err, posts) { Post.find({where: {content: {regexp: /^a/g}}}, function(err, posts) {
console.warn.calledOnce.should.be.ok; console.warn.calledOnce.should.be.ok;
done(); done();
}); });
}); });
it('should print a warning when the multiline flag is set', it('should print a warning when the multiline flag is set',
function(done) { function(done) {
Post.find({where: {content: {regexp: /^a/m}}}, function(err, posts) { Post.find({where: {content: {regexp: /^a/m}}}, function(err, posts) {
console.warn.calledOnce.should.be.ok; console.warn.calledOnce.should.be.ok;
done(); done();
}); });
}); });
}); });
}); });
@ -710,11 +700,11 @@ describe('mysql', function () {
it('should work', function(done) { it('should work', function(done) {
Post.find({where: {content: {regexp: new RegExp(/^A/)}}}, Post.find({where: {content: {regexp: new RegExp(/^A/)}}},
function(err, posts) { function(err, posts) {
should.not.exist(err); should.not.exist(err);
posts.length.should.equal(1); posts.length.should.equal(1);
posts[0].content.should.equal('AAA'); posts[0].content.should.equal('AAA');
done(); done();
}); });
}); });
}); });
@ -722,45 +712,45 @@ describe('mysql', function () {
it('should work', function(done) { it('should work', function(done) {
Post.find({where: {content: {regexp: new RegExp(/^a/i)}}}, Post.find({where: {content: {regexp: new RegExp(/^a/i)}}},
function(err, posts) { function(err, posts) {
should.not.exist(err); should.not.exist(err);
posts.length.should.equal(1); posts.length.should.equal(1);
posts[0].content.should.equal('AAA'); posts[0].content.should.equal('AAA');
done(); done();
}); });
}); });
it('should print a warning when the ignore flag is set', it('should print a warning when the ignore flag is set',
function(done) { function(done) {
Post.find({where: {content: {regexp: new RegExp(/^a/i)}}}, Post.find({where: {content: {regexp: new RegExp(/^a/i)}}},
function(err, posts) { function(err, posts) {
console.warn.calledOnce.should.be.ok; console.warn.calledOnce.should.be.ok;
done(); done();
}); });
}); });
it('should print a warning when the global flag is set', it('should print a warning when the global flag is set',
function(done) { function(done) {
Post.find({where: {content: {regexp: new RegExp(/^a/g)}}}, Post.find({where: {content: {regexp: new RegExp(/^a/g)}}},
function(err, posts) { function(err, posts) {
console.warn.calledOnce.should.be.ok; console.warn.calledOnce.should.be.ok;
done(); done();
}); });
}); });
it('should print a warning when the multiline flag is set', it('should print a warning when the multiline flag is set',
function(done) { function(done) {
Post.find({where: {content: {regexp: new RegExp(/^a/m)}}}, Post.find({where: {content: {regexp: new RegExp(/^a/m)}}},
function(err, posts) { function(err, posts) {
console.warn.calledOnce.should.be.ok; console.warn.calledOnce.should.be.ok;
done(); done();
}); });
}); });
}); });
}); });
}); });
after(function (done) { after(function(done) {
Post.destroyAll(function () { Post.destroyAll(function() {
PostWithStringId.destroyAll(function () { PostWithStringId.destroyAll(function() {
PostWithUniqueTitle.destroyAll(done); PostWithUniqueTitle.destroyAll(done);
}); });
}); });

View File

@ -3,9 +3,10 @@
// This file is licensed under the MIT License. // This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict';
var should = require('./init'); var should = require('./init');
var suite = require('loopback-datasource-juggler/test/persistence-hooks.suite.js'); var suite = require('loopback-datasource-juggler/test/persistence-hooks.suite.js');
suite(global.getDataSource(), should, { suite(global.getDataSource(), should, {
replaceOrCreateReportsNewInstance: true replaceOrCreateReportsNewInstance: true,
}); });

View File

@ -3,6 +3,7 @@
// This file is licensed under the MIT License. // This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict';
if (typeof Promise === 'undefined') { if (typeof Promise === 'undefined') {
global.Promise = require('bluebird'); global.Promise = require('bluebird');
} }
@ -13,17 +14,16 @@ require('should');
var db, Post, Review; var db, Post, Review;
describe('transactions with promise', function() { describe('transactions with promise', function() {
before(function(done) { before(function(done) {
db = getDataSource({collation: 'utf8_general_ci', createDatabase: true}); db = getDataSource({collation: 'utf8_general_ci', createDatabase: true});
db.once('connected', function() { db.once('connected', function() {
Post = db.define('PostTX', { Post = db.define('PostTX', {
title: {type: String, length: 255, index: true}, title: {type: String, length: 255, index: true},
content: {type: String} content: {type: String},
}, {mysql: {engine: 'INNODB'}}); }, {mysql: {engine: 'INNODB'}});
Review = db.define('ReviewTX', { Review = db.define('ReviewTX', {
author: String, author: String,
content: {type: String} content: {type: String},
}, {mysql: {engine: 'INNODB'}}); }, {mysql: {engine: 'INNODB'}});
Post.hasMany(Review, {as: 'reviews', foreignKey: 'postId'}); Post.hasMany(Review, {as: 'reviews', foreignKey: 'postId'});
db.automigrate(['PostTX', 'ReviewTX'], done); db.automigrate(['PostTX', 'ReviewTX'], done);
@ -38,7 +38,7 @@ describe('transactions with promise', function() {
// Transaction.begin(db.connector, Transaction.READ_COMMITTED, // Transaction.begin(db.connector, Transaction.READ_COMMITTED,
var promise = Post.beginTransaction({ var promise = Post.beginTransaction({
isolationLevel: Transaction.READ_COMMITTED, isolationLevel: Transaction.READ_COMMITTED,
timeout: timeout timeout: timeout,
}); });
promise.then(function(tx) { promise.then(function(tx) {
(typeof tx.id).should.be.eql('string'); (typeof tx.id).should.be.eql('string');
@ -65,7 +65,7 @@ describe('transactions with promise', function() {
function(p) { function(p) {
p.reviews.create({ p.reviews.create({
author: 'John', author: 'John',
content: 'Review for ' + p.title content: 'Review for ' + p.title,
}, {transaction: currentTx}).then( }, {transaction: currentTx}).then(
function(c) { function(c) {
done(null, c); done(null, c);
@ -102,7 +102,6 @@ describe('transactions with promise', function() {
} }
describe('commit', function() { describe('commit', function() {
var post = {title: 't1', content: 'c1'}; var post = {title: 't1', content: 'c1'};
before(createPostInTx(post)); before(createPostInTx(post));
@ -129,7 +128,6 @@ describe('transactions with promise', function() {
}); });
describe('rollback', function() { describe('rollback', function() {
var post = {title: 't2', content: 'c2'}; var post = {title: 't2', content: 'c2'};
before(createPostInTx(post)); before(createPostInTx(post));
@ -156,7 +154,6 @@ describe('transactions with promise', function() {
}); });
describe('timeout', function() { describe('timeout', function() {
var post = {title: 't3', content: 'c3'}; var post = {title: 't3', content: 'c3'};
before(createPostInTx(post, 500)); before(createPostInTx(post, 500));
@ -176,7 +173,5 @@ describe('transactions with promise', function() {
done(); done();
}); });
}); });
}); });
}); });

View File

@ -3,6 +3,7 @@
// This file is licensed under the MIT License. // This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict';
var Transaction = require('loopback-datasource-juggler').Transaction; var Transaction = require('loopback-datasource-juggler').Transaction;
require('./init.js'); require('./init.js');
require('should'); require('should');
@ -10,17 +11,16 @@ require('should');
var db, Post, Review; var db, Post, Review;
describe('transactions', function() { describe('transactions', function() {
before(function(done) { before(function(done) {
db = getDataSource({collation: 'utf8_general_ci', createDatabase: true}); db = getDataSource({collation: 'utf8_general_ci', createDatabase: true});
db.once('connected', function() { db.once('connected', function() {
Post = db.define('PostTX', { Post = db.define('PostTX', {
title: {type: String, length: 255, index: true}, title: {type: String, length: 255, index: true},
content: {type: String} content: {type: String},
}, {mysql: {engine: 'INNODB'}}); }, {mysql: {engine: 'INNODB'}});
Review = db.define('ReviewTX', { Review = db.define('ReviewTX', {
author: String, author: String,
content: {type: String} content: {type: String},
}, {mysql: {engine: 'INNODB'}}); }, {mysql: {engine: 'INNODB'}});
Post.hasMany(Review, {as: 'reviews', foreignKey: 'postId'}); Post.hasMany(Review, {as: 'reviews', foreignKey: 'postId'});
db.automigrate(['PostTX', 'ReviewTX'], done); db.automigrate(['PostTX', 'ReviewTX'], done);
@ -34,9 +34,9 @@ describe('transactions', function() {
return function(done) { return function(done) {
// Transaction.begin(db.connector, Transaction.READ_COMMITTED, // Transaction.begin(db.connector, Transaction.READ_COMMITTED,
Post.beginTransaction({ Post.beginTransaction({
isolationLevel: Transaction.READ_COMMITTED, isolationLevel: Transaction.READ_COMMITTED,
timeout: timeout timeout: timeout,
}, },
function(err, tx) { function(err, tx) {
if (err) return done(err); if (err) return done(err);
(typeof tx.id).should.be.eql('string'); (typeof tx.id).should.be.eql('string');
@ -64,9 +64,9 @@ describe('transactions', function() {
done(err); done(err);
} else { } else {
p.reviews.create({ p.reviews.create({
author: 'John', author: 'John',
content: 'Review for ' + p.title content: 'Review for ' + p.title,
}, {transaction: tx}, }, {transaction: tx},
function(err, c) { function(err, c) {
done(err); done(err);
}); });
@ -105,7 +105,6 @@ describe('transactions', function() {
} }
describe('commit', function() { describe('commit', function() {
var post = {title: 't1', content: 'c1'}; var post = {title: 't1', content: 'c1'};
before(createPostInTx(post)); before(createPostInTx(post));
@ -132,7 +131,6 @@ describe('transactions', function() {
}); });
describe('rollback', function() { describe('rollback', function() {
var post = {title: 't2', content: 'c2'}; var post = {title: 't2', content: 'c2'};
before(createPostInTx(post)); before(createPostInTx(post));
@ -159,7 +157,6 @@ describe('transactions', function() {
}); });
describe('timeout', function() { describe('timeout', function() {
var post = {title: 't3', content: 'c3'}; var post = {title: 't3', content: 'c3'};
before(createPostInTx(post, 500)); before(createPostInTx(post, 500));
@ -179,7 +176,5 @@ describe('transactions', function() {
done(); done();
}); });
}); });
}); });
}); });