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

Commit f14f6cdf by Sushant Committed by Jan Aagaard Meier

code coverage, tests and docker fix (#7131)

1 parent 2a78517d
......@@ -3,21 +3,14 @@ version: '2'
services:
# PostgreSQL
postgres-95:
image: mdillon/postgis:9.5
image: camptocamp/postgis:9.5
environment:
POSTGRES_USER: sequelize_test
POSTGRES_PASSWORD: sequelize_test
POSTGRES_DB: sequelize_test
ports:
- "127.0.0.1:8998:5432"
container_name: postgres-95
postgres-94:
image: mdillon/postgis:9.4
environment:
POSTGRES_USER: sequelize_test
POSTGRES_PASSWORD: sequelize_test
ports:
- "127.0.0.1:8998:5432"
container_name: postgres-94
# MySQL
mysql-57:
......@@ -30,23 +23,3 @@ services:
ports:
- "127.0.0.1:8999:3306"
container_name: mysql-57
mysql-56:
image: mysql:5.6
environment:
MYSQL_ROOT_PASSWORD: lollerskates
MYSQL_DATABASE: sequelize_test
MYSQL_USER: sequelize_test
MYSQL_PASSWORD: sequelize_test
ports:
- "127.0.0.1:8999:3306"
container_name: mysql-56
mysql-55:
image: mysql:5.5
environment:
MYSQL_ROOT_PASSWORD: lollerskates
MYSQL_DATABASE: sequelize_test
MYSQL_USER: sequelize_test
MYSQL_PASSWORD: sequelize_test
ports:
- "127.0.0.1:8999:3306"
container_name: mysql-55
......@@ -86,24 +86,22 @@ class ConnectionManager extends AbstractConnectionManager {
case 'ESOCKET':
if (_.includes(err.message, 'connect EHOSTUNREACH')) {
reject(new sequelizeErrors.HostNotReachableError(err));
} else if (_.includes(err.message, 'connect ENETUNREACH')) {
reject(new sequelizeErrors.HostNotReachableError(err));
} else if (_.includes(err.message, 'connect EADDRNOTAVAIL')) {
reject(new sequelizeErrors.HostNotReachableError(err));
} else if (_.includes(err.message, 'getaddrinfo ENOTFOUND')) {
reject(new sequelizeErrors.HostNotFoundError(err));
} else if (_.includes(err.message, 'connect ECONNREFUSED')) {
reject(new sequelizeErrors.ConnectionRefusedError(err));
} else {
reject(new sequelizeErrors.ConnectionError(err));
}
break;
case 'ECONNREFUSED':
reject(new sequelizeErrors.ConnectionRefusedError(err));
break;
case 'ER_ACCESS_DENIED_ERROR':
case 'ELOGIN':
reject(new sequelizeErrors.AccessDeniedError(err));
break;
case 'ENOTFOUND':
reject(new sequelizeErrors.HostNotFoundError(err));
break;
case 'EHOSTUNREACH':
reject(new sequelizeErrors.HostNotReachableError(err));
break;
case 'EINVAL':
reject(new sequelizeErrors.InvalidConnectionError(err));
break;
......
'use strict';
/* jshint -W030 */
var chai = require('chai')
, expect = chai.expect
, Support = require('../../support')
, dialect = Support.getTestDialect();
const chai = require('chai');
const expect = chai.expect;
const Support = require('../../support');
const dialect = Support.getTestDialect();
if (dialect.match(/^mssql/)) {
describe('[MSSQL Specific] Query Queue', function () {
it('should work with handleDisconnects', function() {
var sequelize = Support.createSequelizeInstance({pool: {min: 1, max: 1, idle: 5000}})
, cm = sequelize.connectionManager
, conn;
return sequelize.sync()
.then(function() {
return cm.getConnection();
})
.then(function(connection) {
it('should work with handleDisconnects', () => {
const sequelize = Support.createSequelizeInstance({ pool: { min: 1, max: 1, idle: 5000 } });
const cm = sequelize.connectionManager;
let conn;
return sequelize
.sync()
.then(() => cm.getConnection())
.then(connection => {
// Save current connection
conn = connection;
......@@ -25,16 +24,59 @@ if (dialect.match(/^mssql/)) {
// connection removed from pool by MSSQL Conn Manager
conn.unwrap().emit('error', {code: 'ECONNRESET'});
})
.then(function() {
// Get next available connection
return cm.getConnection();
})
.then(function(connection) {
.then(() => cm.getConnection())
.then(connection => {
expect(conn).to.not.be.equal(connection);
expect(cm.validate(conn)).to.not.be.ok;
return cm.releaseConnection(connection);
});
});
it('should handle double disconnect', () => {
const sequelize = Support.createSequelizeInstance({ pool: { min: 1, max: 1, idle: 5000 } });
const cm = sequelize.connectionManager;
let count = 0;
let conn = null;
return sequelize
.sync()
.then(() => cm.getConnection())
.then(connection => {
conn = connection;
const unwrapConn = conn.unwrap();
unwrapConn.on('end', () => {
count++;
});
return cm.disconnect(conn);
})
.then(() => cm.disconnect(conn))
.then(() => {
expect(count).to.be.eql(1);
});
});
describe('Errors', () => {
it('ECONNREFUSED', () => {
const sequelize = Support.createSequelizeInstance({ port: 34237 });
return expect(sequelize.connectionManager.getConnection()).to.have.been.rejectedWith(sequelize.ConnectionRefusedError);
});
it('ENOTFOUND', () => {
const sequelize = Support.createSequelizeInstance({ host: 'http://wowow.example.com' });
return expect(sequelize.connectionManager.getConnection()).to.have.been.rejectedWith(sequelize.HostNotFoundError);
});
it('EHOSTUNREACH', () => {
const sequelize = Support.createSequelizeInstance({ host: '255.255.255.255' });
return expect(sequelize.connectionManager.getConnection()).to.have.been.rejectedWith(sequelize.HostNotReachableError);
});
it('ER_ACCESS_DENIED_ERROR | ELOGIN', () => {
const sequelize = new Support.Sequelize('localhost', 'was', 'ddsd', Support.sequelize.options);
return expect(sequelize.connectionManager.getConnection()).to.have.been.rejectedWith(sequelize.AccessDeniedError);
});
});
});
}
'use strict';
/* jshint -W030 */
var chai = require('chai')
, expect = chai.expect
, Support = require(__dirname + '/../../support')
, dialect = Support.getTestDialect()
, sinon = require('sinon')
, DataTypes = require(__dirname + '/../../../../lib/data-types');
const chai = require('chai');
const expect = chai.expect;
const Support = require(__dirname + '/../../support');
const dialect = Support.getTestDialect();
const sinon = require('sinon');
const DataTypes = require(__dirname + '/../../../../lib/data-types');
if (dialect === 'mysql') {
describe('[MYSQL Specific] Connection Manager', function() {
it('works correctly after being idle', function() {
var User = this.sequelize.define('User', { username: DataTypes.STRING })
, spy = sinon.spy()
, self = this;
describe('[MYSQL Specific] Connection Manager', function () {
it('works correctly after being idle', function () {
const User = this.sequelize.define('User', { username: DataTypes.STRING });
const spy = sinon.spy();
return User.sync({force: true}).then(function() {
return User.create({username: 'user1'}).then(function() {
return User.count().then(function(count) {
expect(count).to.equal(1);
spy();
return self.sequelize.Promise.delay(1000).then(function() {
return User.count().then(function(count) {
expect(count).to.equal(1);
spy();
if (!spy.calledTwice) {
throw new Error('Spy was not called twice');
}
});
});
});
return User
.sync({force: true})
.then(() => User.create({username: 'user1'}))
.then(() => User.count())
.then(count => {
expect(count).to.equal(1);
spy();
return this.sequelize.Promise.delay(1000);
})
.then(() => User.count())
.then(count => {
expect(count).to.equal(1);
spy();
if (!spy.calledTwice) {
throw new Error('Spy was not called twice');
}
});
});
});
it('accepts new queries after shutting down a connection', function() {
it('accepts new queries after shutting down a connection', () => {
// Create a sequelize instance with fast disconnecting connection
var sequelize = Support.createSequelizeInstance({ pool: {
idle: 50,
max: 1
} });
var User = sequelize.define('User', { username: DataTypes.STRING });
const sequelize = Support.createSequelizeInstance({ pool: { idle: 50, max: 1 }});
const User = sequelize.define('User', { username: DataTypes.STRING });
return User.sync({force: true}).then(function() {
return User.create({username: 'user1'});
}).then(function() {
// After 100 ms the DB connection will be disconnected for inactivity
return sequelize.Promise.delay(100);
}).then(function () {
return User
.sync({force: true})
.then(() => User.create({username: 'user1'}))
.then(() => sequelize.Promise.delay(100))
.then(() => {
// This query will be queued just after the `client.end` is executed and before its callback is called
return sequelize.query('SELECT COUNT(*) AS count FROM Users', { type: sequelize.QueryTypes.SELECT });
}).then(function(count) {
})
.then((count) => {
expect(count[0].count).to.equal(1);
});
});
// This should run only on direct mysql
if (dialect === 'mysql') {
it('should maintain connection', function() {
var sequelize = Support.createSequelizeInstance({pool: {min: 1, max: 1, handleDisconnects: true, idle: 5000}})
, cm = sequelize.connectionManager
, conn;
return sequelize.sync()
.then(function() {
return cm.getConnection();
})
.then(function(connection) {
// Save current connection
conn = connection;
})
.then(function() {
return cm.releaseConnection(conn);
})
.then(function() {
// Get next available connection
return cm.getConnection();
})
.then(function(connection) {
// Old threadId should be different from current new one
expect(conn.threadId).to.be.equal(connection.threadId);
expect(cm.validate(conn)).to.be.ok;
it('should maintain connection', () => {
const sequelize = Support.createSequelizeInstance({ pool: {min: 1, max: 1, handleDisconnects: true, idle: 5000 }});
const cm = sequelize.connectionManager;
let conn;
return cm.releaseConnection(connection);
});
});
return sequelize.sync()
.then(() => cm.getConnection())
.then(connection => {
// Save current connection
conn = connection;
it('should work with handleDisconnects', function() {
var sequelize = Support.createSequelizeInstance({pool: {min: 1, max: 1, handleDisconnects: true, idle: 5000}})
, cm = sequelize.connectionManager
, conn;
return cm.releaseConnection(conn);
})
.then(() => {
// Get next available connection
return cm.getConnection();
})
.then((connection) => {
// Old threadId should be different from current new one
expect(conn.threadId).to.be.equal(connection.threadId);
expect(cm.validate(conn)).to.be.ok;
return sequelize.sync()
.then(function() {
return cm.getConnection();
})
.then(function(connection) {
// Save current connection
conn = connection;
// simulate a unexpected end
connection.close();
})
.then(function() {
return cm.releaseConnection(conn);
})
.then(function() {
// Get next available connection
return cm.getConnection();
})
.then(function(connection) {
// Old threadId should be different from current new one
expect(conn.threadId).to.not.be.equal(connection.threadId);
expect(cm.validate(conn)).to.not.be.ok;
return cm.releaseConnection(connection);
});
});
return cm.releaseConnection(connection);
});
});
}
it('should work with handleDisconnects', () => {
const sequelize = Support.createSequelizeInstance({pool: {min: 1, max: 1, handleDisconnects: true, idle: 5000}});
const cm = sequelize.connectionManager;
let conn;
return sequelize
.sync()
.then(() => cm.getConnection())
.then((connection) => {
// Save current connection
conn = connection;
// simulate a unexpected end
connection.close();
})
.then(() => cm.releaseConnection(conn))
.then(() => {
// Get next available connection
return cm.getConnection();
})
.then((connection) => {
// Old threadId should be different from current new one
expect(conn.threadId).to.not.be.equal(connection.threadId);
expect(cm.validate(conn)).to.not.be.ok;
return cm.releaseConnection(connection);
});
});
});
}
......@@ -395,7 +395,7 @@ describe(Support.getTestDialectTeaser('Model'), function() {
engine: 'MyISAM'
});
return this.sequelize.sync({ force: true }).bind(this).then(function() {
return this.sequelize.sync().bind(this).then(function() {
return this.sequelize.sync(); // The second call should not try to create the indices again
}).then(function() {
return this.sequelize.queryInterface.showIndex(Model.tableName);
......
'use strict';
/* jshint -W030 */
var chai = require('chai')
, expect = chai.expect
, Support = require(__dirname + '/support')
, DataTypes = require(__dirname + '/../../lib/data-types')
, dialect = Support.getTestDialect()
, _ = require('lodash')
, count = 0
, log = function (sql) {
// sqlite fires a lot more querys than the other dbs. this is just a simple hack, since i'm lazy
if (dialect !== 'sqlite' || count === 0) {
count++;
}
};
const chai = require('chai');
const expect = chai.expect;
const Support = require(__dirname + '/support');
const DataTypes = require(__dirname + '/../../lib/data-types');
const dialect = Support.getTestDialect();
const _ = require('lodash');
let count = 0;
const log = function() {
// sqlite fires a lot more querys than the other dbs. this is just a simple hack, since i'm lazy
if (dialect !== 'sqlite' || count === 0) {
count++;
}
};
describe(Support.getTestDialectTeaser('QueryInterface'), function() {
beforeEach(function() {
......@@ -25,6 +25,24 @@ describe(Support.getTestDialectTeaser('QueryInterface'), function() {
return this.sequelize.dropAllSchemas();
});
describe('renameTable', function() {
it('should rename table', function() {
return this.queryInterface
.createTable('myTestTable', {
name: DataTypes.STRING
})
.then(() => this.queryInterface.renameTable('myTestTable', 'myTestTableNew'))
.then(() => this.queryInterface.showAllTables())
.then((tableNames) => {
if (dialect === 'mssql') {
tableNames = _.map(tableNames, 'tableName');
}
expect(tableNames).to.contain('myTestTableNew');
expect(tableNames).to.not.contain('myTestTable');
});
});
});
describe('dropAllTables', function() {
it('should drop all tables', function() {
const filterMSSQLDefault = tableNames => tableNames.filter(t => t.tableName !== 'spt_values');
......@@ -228,7 +246,7 @@ describe(Support.getTestDialectTeaser('QueryInterface'), function() {
return self.queryInterface.describeTable('_Country').then(function(metacountry) {
expect(metacountry.code.primaryKey).to.eql(true);
expect(metacountry.name.primaryKey).to.eql(false);
return Alumni.sync({ force: true }).then(function() {
return self.queryInterface.describeTable('_Alumni').then(function(metalumni) {
expect(metalumni.year.primaryKey).to.eql(true);
......@@ -651,7 +669,7 @@ describe(Support.getTestDialectTeaser('QueryInterface'), function() {
expect(table).to.not.have.property('id');
});
});
});
describe('(with a schema)', function() {
......
'use strict';
/* jshint -W110 */
var Support = require(__dirname + '/../../support')
, expectsql = Support.expectsql
, current = Support.sequelize
, QueryGenerator = require('../../../../lib/dialects/mssql/query-generator')
, _ = require('lodash');
const Support = require(__dirname + '/../../support');
const expectsql = Support.expectsql;
const current = Support.sequelize;
const QueryGenerator = require('../../../../lib/dialects/mssql/query-generator');
const _ = require('lodash');
if (current.dialect.name === 'mssql') {
suite('[MSSQL Specific] QueryGenerator', function () {
suite('[MSSQL Specific] QueryGenerator', function() {
// Dialect would normally be set by the query interface that instantiates the query-generator, but here we specify it explicitly
QueryGenerator._dialect = current.dialect;
test('getDefaultConstraintQuery', function () {
test('getDefaultConstraintQuery', () => {
expectsql(QueryGenerator.getDefaultConstraintQuery({tableName: 'myTable', schema: 'mySchema'}, 'myColumn'), {
mssql: "SELECT name FROM SYS.DEFAULT_CONSTRAINTS WHERE PARENT_OBJECT_ID = OBJECT_ID('[mySchema].[myTable]', 'U') AND PARENT_COLUMN_ID = (SELECT column_id FROM sys.columns WHERE NAME = ('myColumn') AND object_id = OBJECT_ID('[mySchema].[myTable]', 'U'));"
});
});
test('dropConstraintQuery', function () {
test('dropConstraintQuery', () => {
expectsql(QueryGenerator.dropConstraintQuery({tableName: 'myTable', schema: 'mySchema'}, 'myConstraint'), {
mssql: "ALTER TABLE [mySchema].[myTable] DROP CONSTRAINT [myConstraint];"
mssql: 'ALTER TABLE [mySchema].[myTable] DROP CONSTRAINT [myConstraint];'
});
});
test('bulkInsertQuery', function() {
test('bulkInsertQuery', () => {
//normal cases
expectsql(QueryGenerator.bulkInsertQuery('myTable', [{ name: 'foo' }, {name: 'bar'}]), {
mssql: "INSERT INTO [myTable] ([name]) VALUES (N'foo'),(N'bar');"
......@@ -39,14 +39,14 @@ if (current.dialect.name === 'mssql') {
});
//Bulk Insert With autogenerated primary key
var attributes = { id: { autoIncrement: true }};
const attributes = { id: { autoIncrement: true }};
expectsql(QueryGenerator.bulkInsertQuery('myTable', [{ id: null }], {}, attributes), {
mssql: "INSERT INTO [myTable] DEFAULT VALUES"
mssql: 'INSERT INTO [myTable] DEFAULT VALUES'
});
});
test('selectFromTableFragment', function() {
var modifiedGen = _.clone(QueryGenerator);
test('selectFromTableFragment', () => {
const modifiedGen = _.clone(QueryGenerator);
// Test newer versions first
// Should be all the same since handling is done in addLimitAndOffset
// for SQL Server 2012 and higher (>= v11.0.0)
......@@ -58,22 +58,22 @@ if (current.dialect.name === 'mssql') {
// Base case
expectsql(modifiedGen.selectFromTableFragment({}, { primaryKeyField: 'id' }, ['id', 'name'], 'myTable', 'myOtherName', 'WHERE id=1'), {
mssql: "SELECT id, name FROM myTable AS myOtherName"
mssql: 'SELECT id, name FROM myTable AS myOtherName'
});
// With limit
expectsql(modifiedGen.selectFromTableFragment({ limit: 10 }, { primaryKeyField: 'id' }, ['id', 'name'], 'myTable', 'myOtherName'), {
mssql: "SELECT id, name FROM myTable AS myOtherName"
mssql: 'SELECT id, name FROM myTable AS myOtherName'
});
// With offset
expectsql(modifiedGen.selectFromTableFragment({ offset: 10 }, { primaryKeyField: 'id' }, ['id', 'name'], 'myTable', 'myOtherName'), {
mssql: "SELECT id, name FROM myTable AS myOtherName"
mssql: 'SELECT id, name FROM myTable AS myOtherName'
});
// With both limit and offset
expectsql(modifiedGen.selectFromTableFragment({ limit: 10, offset: 10 }, { primaryKeyField: 'id' }, ['id', 'name'], 'myTable', 'myOtherName'), {
mssql: "SELECT id, name FROM myTable AS myOtherName"
mssql: 'SELECT id, name FROM myTable AS myOtherName'
});
// Test older version (< v11.0.0)
......@@ -81,29 +81,95 @@ if (current.dialect.name === 'mssql') {
// Base case
expectsql(modifiedGen.selectFromTableFragment({}, { primaryKeyField: 'id' }, ['id', 'name'], 'myTable', 'myOtherName', 'WHERE id=1'), {
mssql: "SELECT id, name FROM myTable AS myOtherName"
mssql: 'SELECT id, name FROM myTable AS myOtherName'
});
// With limit
expectsql(modifiedGen.selectFromTableFragment({ limit: 10 }, { primaryKeyField: 'id' }, ['id', 'name'], 'myTable', 'myOtherName'), {
mssql: "SELECT TOP 10 id, name FROM myTable AS myOtherName"
mssql: 'SELECT TOP 10 id, name FROM myTable AS myOtherName'
});
// With offset
expectsql(modifiedGen.selectFromTableFragment({ offset: 10 }, { primaryKeyField: 'id' }, ['id', 'name'], 'myTable', 'myOtherName'), {
mssql: "SELECT TOP 100 PERCENT id, name FROM (SELECT * FROM (SELECT ROW_NUMBER() OVER (ORDER BY [id]) as row_num, * FROM myTable AS myOtherName) AS myOtherName WHERE row_num > 10) AS myOtherName"
mssql: 'SELECT TOP 100 PERCENT id, name FROM (SELECT * FROM (SELECT ROW_NUMBER() OVER (ORDER BY [id]) as row_num, * FROM myTable AS myOtherName) AS myOtherName WHERE row_num > 10) AS myOtherName'
});
// With both limit and offset
expectsql(modifiedGen.selectFromTableFragment({ limit: 10, offset: 10 }, { primaryKeyField: 'id' }, ['id', 'name'], 'myTable', 'myOtherName'), {
mssql: "SELECT TOP 100 PERCENT id, name FROM (SELECT TOP 10 * FROM (SELECT ROW_NUMBER() OVER (ORDER BY [id]) as row_num, * FROM myTable AS myOtherName) AS myOtherName WHERE row_num > 10) AS myOtherName"
mssql: 'SELECT TOP 100 PERCENT id, name FROM (SELECT TOP 10 * FROM (SELECT ROW_NUMBER() OVER (ORDER BY [id]) as row_num, * FROM myTable AS myOtherName) AS myOtherName WHERE row_num > 10) AS myOtherName'
});
});
test('getPrimaryKeyConstraintQuery', function () {
test('getPrimaryKeyConstraintQuery', () => {
expectsql(QueryGenerator.getPrimaryKeyConstraintQuery('myTable', 'myColumnName'), {
mssql: 'SELECT K.TABLE_NAME AS tableName, K.COLUMN_NAME AS columnName, K.CONSTRAINT_NAME AS constraintName FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS AS C JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE AS K ON C.TABLE_NAME = K.TABLE_NAME AND C.CONSTRAINT_CATALOG = K.CONSTRAINT_CATALOG AND C.CONSTRAINT_SCHEMA = K.CONSTRAINT_SCHEMA AND C.CONSTRAINT_NAME = K.CONSTRAINT_NAME WHERE C.CONSTRAINT_TYPE = \'PRIMARY KEY\' AND K.COLUMN_NAME = \'myColumnName\' AND K.TABLE_NAME = \'myTable\';'
});
});
test('createSchema', () => {
expectsql(QueryGenerator.createSchema('mySchema'), {
mssql: 'IF NOT EXISTS (SELECT schema_name FROM information_schema.schemata WHERE schema_name = \'mySchema\' ) BEGIN EXEC sp_executesql N\'CREATE SCHEMA [mySchema] ;\' END;'
});
});
test('showSchemasQuery', () => {
expectsql(QueryGenerator.showSchemasQuery(), {
mssql: 'SELECT "name" as "schema_name" FROM sys.schemas as s WHERE "s"."name" NOT IN ( \'INFORMATION_SCHEMA\', \'dbo\', \'guest\', \'sys\', \'archive\' ) AND "s"."name" NOT LIKE \'db_%\''
});
});
test('versionQuery', () => {
expectsql(QueryGenerator.versionQuery(), {
mssql: "DECLARE @ms_ver NVARCHAR(20); SET @ms_ver = REVERSE(CONVERT(NVARCHAR(20), SERVERPROPERTY('ProductVersion'))); SELECT REVERSE(SUBSTRING(@ms_ver, CHARINDEX('.', @ms_ver)+1, 20)) AS 'version'"
});
});
test('renameTableQuery', () => {
expectsql(QueryGenerator.renameTableQuery('oldTableName', 'newTableName'), {
mssql: 'EXEC sp_rename [oldTableName], [newTableName];'
});
});
test('showTablesQuery', () => {
expectsql(QueryGenerator.showTablesQuery(), {
mssql: 'SELECT TABLE_NAME, TABLE_SCHEMA FROM INFORMATION_SCHEMA.TABLES;'
});
});
test('dropTableQuery', () => {
expectsql(QueryGenerator.dropTableQuery('dirtyTable'), {
mssql: "IF OBJECT_ID('[dirtyTable]', 'U') IS NOT NULL DROP TABLE [dirtyTable];"
});
});
test('removeColumnQuery', () => {
expectsql(QueryGenerator.removeColumnQuery('myTable', 'myColumn'), {
mssql: 'ALTER TABLE [myTable] DROP COLUMN [myColumn];'
});
});
test('quoteIdentifier', () => {
expectsql(QueryGenerator.quoteIdentifier("'myTable'.'Test'"), {
mssql: '[myTable.Test]'
});
});
test('getForeignKeysQuery', () => {
expectsql(QueryGenerator.getForeignKeysQuery('myTable'), {
mssql: "SELECT constraint_name = C.CONSTRAINT_NAME FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS C WHERE C.CONSTRAINT_TYPE = 'FOREIGN KEY' AND C.TABLE_NAME = 'myTable'"
});
});
test('getForeignKeyQuery', () => {
expectsql(QueryGenerator.getForeignKeyQuery('myTable', 'myColumn'), {
mssql: "SELECT constraint_name = TC.CONSTRAINT_NAME FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS TC JOIN INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE CCU ON TC.CONSTRAINT_NAME = CCU.CONSTRAINT_NAME WHERE TC.CONSTRAINT_TYPE = 'FOREIGN KEY' AND TC.TABLE_NAME = 'myTable' AND CCU.COLUMN_NAME = 'myColumn'"
});
});
test('dropForeignKeyQuery', () => {
expectsql(QueryGenerator.dropForeignKeyQuery('myTable', 'myColumnKey'), {
mssql: 'ALTER TABLE [myTable] DROP [myColumnKey]'
});
});
});
}
'use strict';
var chai = require('chai')
, expect = chai.expect
, Support = require(__dirname + '/support')
, DataTypes = require(__dirname + '/../../lib/data-types')
, Utils = require(__dirname + '/../../lib/utils')
, Support = require(__dirname + '/../support');
// Notice: [] will be replaced by dialect specific tick/quote character when there is not dialect specific expectation but only a default expectation
suite(Support.getTestDialectTeaser('Utils'), function() {
suite('merge', function () {
test('does not clone sequelize models', function () {
var User = this.sequelize.define('user')
, merged = Utils.merge({}, { include: [{model : User }]})
, merged2 = Utils.merge({}, { user: User });
/* jshint -W030 */
const chai = require('chai');
const expect = chai.expect;
const Support = require(__dirname + '/support');
const DataTypes = require(__dirname + '/../../lib/data-types');
const Utils = require(__dirname + '/../../lib/utils');
suite(Support.getTestDialectTeaser('Utils'), () => {
suite('merge', () => {
test('does not clone sequelize models', () => {
const User = Support.sequelize.define('user');
const merged = Utils.merge({}, { include: [{model : User }]});
const merged2 = Utils.merge({}, { user: User });
expect(merged.include[0].model).to.equal(User);
expect(merged2.user).to.equal(User);
});
});
suite('toDefaultValue', function () {
test('return plain data types', function () {
suite('toDefaultValue', () => {
test('return plain data types', () => {
expect(Utils.toDefaultValue(DataTypes.UUIDV4)).to.equal('UUIDV4');
});
test('return uuid v1', function () {
test('return uuid v1', () => {
expect(/^[a-z0-9\-]{36}$/.test(Utils.toDefaultValue(DataTypes.UUIDV1()))).to.be.equal(true);
});
test('return uuid v4', function () {
test('return uuid v4', () => {
expect(/^[a-z0-9\-]{36}/.test(Utils.toDefaultValue(DataTypes.UUIDV4()))).to.be.equal(true);
});
test('return now', function () {
test('return now', () => {
expect(Object.prototype.toString.call(Utils.toDefaultValue(DataTypes.NOW()))).to.be.equal('[object Date]');
});
test('return plain string', function () {
test('return plain string', () => {
expect(Utils.toDefaultValue('Test')).to.equal('Test');
});
test('return plain object', function () {
test('return plain object', () => {
chai.assert.deepEqual({}, Utils.toDefaultValue({}));
});
});
suite('mapFinderOptions', function () {
test('virtual attribute dependencies', function () {
suite('mapFinderOptions', () => {
test('virtual attribute dependencies', () => {
expect(Utils.mapFinderOptions({
attributes: [
'active'
]
}, this.sequelize.define('User', {
}, Support.sequelize.define('User', {
createdAt: {
type: DataTypes.DATE,
field: 'created_at'
......@@ -64,8 +62,8 @@ suite(Support.getTestDialectTeaser('Utils'), function() {
]);
});
test('multiple calls', function () {
var Model = this.sequelize.define('User', {
test('multiple calls', () => {
const Model = Support.sequelize.define('User', {
createdAt: {
type: DataTypes.DATE,
field: 'created_at'
......@@ -93,14 +91,14 @@ suite(Support.getTestDialectTeaser('Utils'), function() {
});
});
suite('mapOptionFieldNames', function () {
test('plain where', function () {
suite('mapOptionFieldNames', () => {
test('plain where', () => {
expect(Utils.mapOptionFieldNames({
where: {
firstName: 'Paul',
lastName: 'Atreides'
}
}, this.sequelize.define('User', {
}, Support.sequelize.define('User', {
firstName: {
type: DataTypes.STRING,
field: 'first_name'
......@@ -117,7 +115,7 @@ suite(Support.getTestDialectTeaser('Utils'), function() {
});
});
test('$or where', function () {
test('$or where', () => {
expect(Utils.mapOptionFieldNames({
where: {
$or: {
......@@ -125,7 +123,7 @@ suite(Support.getTestDialectTeaser('Utils'), function() {
lastName: 'Atreides'
}
}
}, this.sequelize.define('User', {
}, Support.sequelize.define('User', {
firstName: {
type: DataTypes.STRING,
field: 'first_name'
......@@ -144,7 +142,7 @@ suite(Support.getTestDialectTeaser('Utils'), function() {
});
});
test('$or[] where', function () {
test('$or[] where', () => {
expect(Utils.mapOptionFieldNames({
where: {
$or: [
......@@ -152,7 +150,7 @@ suite(Support.getTestDialectTeaser('Utils'), function() {
{lastName: 'Atreides'}
]
}
}, this.sequelize.define('User', {
}, Support.sequelize.define('User', {
firstName: {
type: DataTypes.STRING,
field: 'first_name'
......@@ -171,7 +169,7 @@ suite(Support.getTestDialectTeaser('Utils'), function() {
});
});
test('$and where', function () {
test('$and where', () => {
expect(Utils.mapOptionFieldNames({
where: {
$and: {
......@@ -179,7 +177,7 @@ suite(Support.getTestDialectTeaser('Utils'), function() {
lastName: 'Atreides'
}
}
}, this.sequelize.define('User', {
}, Support.sequelize.define('User', {
firstName: {
type: DataTypes.STRING,
field: 'first_name'
......@@ -197,10 +195,11 @@ suite(Support.getTestDialectTeaser('Utils'), function() {
}
});
});
test('string field order', function() {
expect(Utils.mapOptionFieldNames({
order: 'firstName DESC'
}, this.sequelize.define('User', {
order: 'firstName DESC'
}, Support.sequelize.define('User', {
firstName: {
type: DataTypes.STRING,
field: 'first_name'
......@@ -209,10 +208,11 @@ suite(Support.getTestDialectTeaser('Utils'), function() {
order: 'firstName DESC'
});
});
test('string in array order', function() {
expect(Utils.mapOptionFieldNames({
order: ['firstName DESC']
}, this.sequelize.define('User', {
}, Support.sequelize.define('User', {
firstName: {
type: DataTypes.STRING,
field: 'first_name'
......@@ -221,10 +221,11 @@ suite(Support.getTestDialectTeaser('Utils'), function() {
order: ['firstName DESC']
});
});
test('single field alias order', function() {
expect(Utils.mapOptionFieldNames({
order: [['firstName', 'DESC']]
}, this.sequelize.define('User', {
}, Support.sequelize.define('User', {
firstName: {
type: DataTypes.STRING,
field: 'first_name'
......@@ -233,10 +234,11 @@ suite(Support.getTestDialectTeaser('Utils'), function() {
order: [['first_name', 'DESC']]
});
});
test('multi field alias order', function() {
expect(Utils.mapOptionFieldNames({
order: [['firstName', 'DESC'], ['lastName', 'ASC']]
}, this.sequelize.define('User', {
}, Support.sequelize.define('User', {
firstName: {
type: DataTypes.STRING,
field: 'first_name'
......@@ -249,10 +251,11 @@ suite(Support.getTestDialectTeaser('Utils'), function() {
order: [['first_name', 'DESC'], ['last_name', 'ASC']]
});
});
test('multi field alias no direction order', function() {
expect(Utils.mapOptionFieldNames({
order: [['firstName'], ['lastName']]
}, this.sequelize.define('User', {
}, Support.sequelize.define('User', {
firstName: {
type: DataTypes.STRING,
field: 'first_name'
......@@ -265,10 +268,11 @@ suite(Support.getTestDialectTeaser('Utils'), function() {
order: [['first_name'], ['last_name']]
});
});
test('field alias to another field order', function() {
expect(Utils.mapOptionFieldNames({
order: [['firstName', 'DESC']]
}, this.sequelize.define('User', {
}, Support.sequelize.define('User', {
firstName: {
type: DataTypes.STRING,
field: 'lastName'
......@@ -281,10 +285,11 @@ suite(Support.getTestDialectTeaser('Utils'), function() {
order: [['lastName', 'DESC']]
});
});
test('multi field no alias order', function() {
expect(Utils.mapOptionFieldNames({
order: [['firstName', 'DESC'], ['lastName', 'ASC']]
}, this.sequelize.define('User', {
}, Support.sequelize.define('User', {
firstName: {
type: DataTypes.STRING
},
......@@ -295,14 +300,15 @@ suite(Support.getTestDialectTeaser('Utils'), function() {
order: [['firstName', 'DESC'], ['lastName', 'ASC']]
});
});
test('multi field alias sub model order', function() {
var Location = this.sequelize.define('Location', {
const Location = Support.sequelize.define('Location', {
latLong: {
type: DataTypes.STRING,
field: 'lat_long'
}
});
var Item = this.sequelize.define('Item', {
const Item = Support.sequelize.define('Item', {
fontColor: {
type: DataTypes.STRING,
field: 'font_color'
......@@ -310,7 +316,7 @@ suite(Support.getTestDialectTeaser('Utils'), function() {
});
expect(Utils.mapOptionFieldNames({
order: [[Item, Location, 'latLong', 'DESC'], ['lastName', 'ASC']]
}, this.sequelize.define('User', {
}, Support.sequelize.define('User', {
lastName: {
type: DataTypes.STRING
}
......@@ -318,14 +324,15 @@ suite(Support.getTestDialectTeaser('Utils'), function() {
order: [[Item, Location, 'lat_long', 'DESC'], ['lastName', 'ASC']]
});
});
test('multi field alias sub model no direction order', function() {
var Location = this.sequelize.define('Location', {
const Location = Support.sequelize.define('Location', {
latLong: {
type: DataTypes.STRING,
field: 'lat_long'
}
});
var Item = this.sequelize.define('Item', {
const Item = Support.sequelize.define('Item', {
fontColor: {
type: DataTypes.STRING,
field: 'font_color'
......@@ -333,7 +340,7 @@ suite(Support.getTestDialectTeaser('Utils'), function() {
});
expect(Utils.mapOptionFieldNames({
order: [[Item, Location, 'latLong'], ['lastName', 'ASC']]
}, this.sequelize.define('User', {
}, Support.sequelize.define('User', {
lastName: {
type: DataTypes.STRING
}
......@@ -341,11 +348,12 @@ suite(Support.getTestDialectTeaser('Utils'), function() {
order: [[Item, Location, 'lat_long'], ['lastName', 'ASC']]
});
});
test('function order', function() {
var fn = this.sequelize.fn('otherfn', 123);
const fn = Support.sequelize.fn('otherfn', 123);
expect(Utils.mapOptionFieldNames({
order: [[fn, 'ASC']]
}, this.sequelize.define('User', {
}, Support.sequelize.define('User', {
firstName: {
type: DataTypes.STRING
}
......@@ -353,11 +361,12 @@ suite(Support.getTestDialectTeaser('Utils'), function() {
order: [[fn, 'ASC']]
});
});
test('function no direction order', function() {
var fn = this.sequelize.fn('otherfn', 123);
const fn = Support.sequelize.fn('otherfn', 123);
expect(Utils.mapOptionFieldNames({
order: [[fn]]
}, this.sequelize.define('User', {
}, Support.sequelize.define('User', {
firstName: {
type: DataTypes.STRING
}
......@@ -365,10 +374,11 @@ suite(Support.getTestDialectTeaser('Utils'), function() {
order: [[fn]]
});
});
test('string no direction order', function() {
expect(Utils.mapOptionFieldNames({
order: [['firstName']]
}, this.sequelize.define('User', {
}, Support.sequelize.define('User', {
firstName: {
type: DataTypes.STRING,
field: 'first_name'
......@@ -377,8 +387,9 @@ suite(Support.getTestDialectTeaser('Utils'), function() {
order: [['first_name']]
});
});
test('model alias order', function() {
var Item = this.sequelize.define('Item', {
const Item = Support.sequelize.define('Item', {
fontColor: {
type: DataTypes.STRING,
field: 'font_color'
......@@ -386,7 +397,7 @@ suite(Support.getTestDialectTeaser('Utils'), function() {
});
expect(Utils.mapOptionFieldNames({
order: [[{ model: Item, as: 'another'}, 'fontColor', 'ASC']]
}, this.sequelize.define('User', {
}, Support.sequelize.define('User', {
firstName: {
type: DataTypes.STRING
},
......@@ -397,8 +408,9 @@ suite(Support.getTestDialectTeaser('Utils'), function() {
order: [[{ model: Item, as: 'another'}, 'font_color', 'ASC']]
});
});
test('model alias no direction order', function() {
var Item = this.sequelize.define('Item', {
const Item = Support.sequelize.define('Item', {
fontColor: {
type: DataTypes.STRING,
field: 'font_color'
......@@ -406,7 +418,7 @@ suite(Support.getTestDialectTeaser('Utils'), function() {
});
expect(Utils.mapOptionFieldNames({
order: [[{ model: Item, as: 'another'}, 'fontColor']]
}, this.sequelize.define('User', {
}, Support.sequelize.define('User', {
firstName: {
type: DataTypes.STRING
}
......@@ -414,8 +426,9 @@ suite(Support.getTestDialectTeaser('Utils'), function() {
order: [[{ model: Item, as: 'another'}, 'font_color']]
});
});
test('model alias wrong field order', function() {
var Item = this.sequelize.define('Item', {
const Item = Support.sequelize.define('Item', {
fontColor: {
type: DataTypes.STRING,
field: 'font_color'
......@@ -423,7 +436,7 @@ suite(Support.getTestDialectTeaser('Utils'), function() {
});
expect(Utils.mapOptionFieldNames({
order: [[{ model: Item, as: 'another'}, 'firstName', 'ASC']]
}, this.sequelize.define('User', {
}, Support.sequelize.define('User', {
firstName: {
type: DataTypes.STRING
}
......@@ -431,10 +444,9 @@ suite(Support.getTestDialectTeaser('Utils'), function() {
order: [[{ model: Item, as: 'another'}, 'firstName', 'ASC']]
});
});
});
suite('stack', function() {
suite('stack', () => {
test('stack trace starts after call to Util.stack()', function this_here_test() {
function a() {
......@@ -449,7 +461,7 @@ suite(Support.getTestDialectTeaser('Utils'), function() {
return Utils.stack();
}
var stack = a();
const stack = a();
expect(stack[0].getFunctionName()).to.eql('c');
expect(stack[1].getFunctionName()).to.eql('b');
......@@ -458,13 +470,13 @@ suite(Support.getTestDialectTeaser('Utils'), function() {
});
});
suite('Sequelize.cast', function() {
var sql = Support.sequelize;
var generator = sql.queryInterface.QueryGenerator;
var run = generator.handleSequelizeMethod.bind(generator);
var expectsql = Support.expectsql;
suite('Sequelize.cast', () => {
const sql = Support.sequelize;
const generator = sql.queryInterface.QueryGenerator;
const run = generator.handleSequelizeMethod.bind(generator);
const expectsql = Support.expectsql;
test('accepts condition object (auto casting)', function fn() {
test('accepts condition object (auto casting)', () => {
expectsql(run(sql.fn('SUM', sql.cast({
$or: {
foo: 'foo',
......@@ -475,5 +487,32 @@ suite(Support.getTestDialectTeaser('Utils'), function() {
mssql: 'SUM(CAST(([foo] = N\'foo\' OR [bar] = N\'bar\') AS INT))'
});
});
});
});
suite('Logger', () => {
const logger = Utils.getLogger();
test('deprecate', () => {
expect(logger.deprecate).to.be.function;
logger.deprecate('test deprecation');
});
test('debug', () => {
expect(logger.debug).to.be.function;
logger.debug('test debug');
});
test('warn', () => {
expect(logger.warn).to.be.function;
logger.warn('test warning');
});
test('debugContext', () => {
expect(logger.debugContext).to.be.function;
const testLogger = logger.debugContext('test');
expect(testLogger).to.be.function;
expect(testLogger.namespace).to.be.eql('sequelize:test');
});
});
});
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!