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

Commit 5336424a by Andy Edwards Committed by GitHub

test(integration/dialects): asyncify (#12239)

1 parent a35ec013
......@@ -55,7 +55,7 @@ describe(Support.getTestDialectTeaser('Connection Manager'), () => {
expect(connectionManager.pool.write).to.be.instanceOf(Pool);
});
it('should round robin calls to the read pool', () => {
it('should round robin calls to the read pool', async () => {
if (Support.getTestDialect() === 'sqlite') {
return;
}
......@@ -91,10 +91,9 @@ describe(Support.getTestDialectTeaser('Connection Manager'), () => {
const _getConnection = connectionManager.getConnection.bind(connectionManager, queryOptions);
return _getConnection()
.then(_getConnection)
.then(_getConnection)
.then(() => {
await _getConnection();
await _getConnection();
await _getConnection();
chai.expect(connectStub.callCount).to.equal(4);
// First call is the get connection for DB versions - ignore
......@@ -103,9 +102,8 @@ describe(Support.getTestDialectTeaser('Connection Manager'), () => {
chai.expect(calls[2].args[0].host).to.eql('slave2');
chai.expect(calls[3].args[0].host).to.eql('slave1');
});
});
it('should trigger deprecation for non supported engine version', () => {
it('should trigger deprecation for non supported engine version', async () => {
const deprecationStub = sandbox.stub(deprecations, 'unsupportedEngine');
const sequelize = Support.createSequelizeInstance();
const connectionManager = new ConnectionManager(sequelize.dialect, sequelize);
......@@ -126,14 +124,12 @@ describe(Support.getTestDialectTeaser('Connection Manager'), () => {
useMaster: true
};
return connectionManager.getConnection(queryOptions)
.then(() => {
await connectionManager.getConnection(queryOptions);
chai.expect(deprecationStub).to.have.been.calledOnce;
});
});
it('should allow forced reads from the write pool', () => {
it('should allow forced reads from the write pool', async () => {
const master = { ...poolEntry };
master.host = 'the-boss';
......@@ -161,15 +157,13 @@ describe(Support.getTestDialectTeaser('Connection Manager'), () => {
useMaster: true
};
return connectionManager.getConnection(queryOptions)
.then(() => {
await connectionManager.getConnection(queryOptions);
chai.expect(connectStub).to.have.been.calledTwice; // Once to get DB version, and once to actually get the connection.
const calls = connectStub.getCalls();
chai.expect(calls[1].args[0].host).to.eql('the-boss');
});
});
it('should clear the pool after draining it', () => {
it('should clear the pool after draining it', async () => {
const options = {
replication: null
};
......@@ -181,9 +175,8 @@ describe(Support.getTestDialectTeaser('Connection Manager'), () => {
const poolDrainSpy = sandbox.spy(connectionManager.pool, 'drain');
const poolClearSpy = sandbox.spy(connectionManager.pool, 'destroyAllNow');
return connectionManager.close().then(() => {
await connectionManager.close();
expect(poolDrainSpy.calledOnce).to.be.true;
expect(poolClearSpy.calledOnce).to.be.true;
});
});
});
......@@ -11,33 +11,30 @@ if (dialect !== 'mariadb') return;
describe('[MariaDB Specific] Associations', () => {
describe('many-to-many', () => {
describe('where tables have the same prefix', () => {
it('should create a table wp_table1wp_table2s', function() {
it('should create a table wp_table1wp_table2s', async function() {
const Table2 = this.sequelize.define('wp_table2', { foo: DataTypes.STRING }),
Table1 = this.sequelize.define('wp_table1',
{ foo: DataTypes.STRING });
Table1.belongsToMany(Table2, { through: 'wp_table1swp_table2s' });
Table2.belongsToMany(Table1, { through: 'wp_table1swp_table2s' });
return Table1.sync({ force: true }).then(() => {
return Table2.sync({ force: true }).then(() => {
await Table1.sync({ force: true });
await Table2.sync({ force: true });
expect(this.sequelize.modelManager.getModel(
'wp_table1swp_table2s')).to.exist;
});
});
});
});
describe('when join table name is specified', () => {
beforeEach(function() {
beforeEach(async function() {
const Table2 = this.sequelize.define('ms_table1', { foo: DataTypes.STRING }),
Table1 = this.sequelize.define('ms_table2',
{ foo: DataTypes.STRING });
Table1.belongsToMany(Table2, { through: 'table1_to_table2' });
Table2.belongsToMany(Table1, { through: 'table1_to_table2' });
return Table1.sync({ force: true }).then(() => {
return Table2.sync({ force: true });
});
await Table1.sync({ force: true });
await Table2.sync({ force: true });
});
it('should not use only a specified name', function() {
......@@ -50,7 +47,7 @@ describe('[MariaDB Specific] Associations', () => {
});
describe('HasMany', () => {
beforeEach(function() {
beforeEach(async function() {
//prevent periods from occurring in the table name since they are used to delimit (table.column)
this.User = this.sequelize.define(`User${Math.ceil(Math.random() * 10000000)}`, { name: DataTypes.STRING });
this.Task = this.sequelize.define(`Task${Math.ceil(Math.random() * 10000000)}`, { name: DataTypes.STRING });
......@@ -68,10 +65,9 @@ describe('[MariaDB Specific] Associations', () => {
tasks[i] = { name: `Task${Math.random()}` };
}
return this.sequelize.sync({ force: true })
.then(() => this.User.bulkCreate(users))
.then(() => this.Task.bulkCreate(tasks));
await this.sequelize.sync({ force: true });
await this.User.bulkCreate(users);
await this.Task.bulkCreate(tasks);
});
});
......
......@@ -13,17 +13,15 @@ if (dialect !== 'mariadb') {
describe('[MARIADB Specific] Connection Manager', () => {
it('has existing init SQL', () => {
it('has existing init SQL', async () => {
const sequelize = Support.createSequelizeInstance(
{ dialectOptions: { initSql: 'SET @myUserVariable=\'myValue\'' } });
return sequelize.query('SELECT @myUserVariable')
.then(res => {
const res = await sequelize.query('SELECT @myUserVariable');
expect(res[0]).to.deep.equal([{ '@myUserVariable': 'myValue' }]);
sequelize.close();
});
});
it('has existing init SQL array', () => {
it('has existing init SQL array', async () => {
const sequelize = Support.createSequelizeInstance(
{
dialectOptions: {
......@@ -31,42 +29,40 @@ describe('[MARIADB Specific] Connection Manager', () => {
'SET @myUserVariable2=\'myValue\'']
}
});
return sequelize.query('SELECT @myUserVariable1, @myUserVariable2')
.then(res => {
const res = await sequelize.query('SELECT @myUserVariable1, @myUserVariable2');
expect(res[0]).to.deep.equal(
[{ '@myUserVariable1': 'myValue', '@myUserVariable2': 'myValue' }]);
sequelize.close();
});
});
describe('Errors', () => {
const testHost = env.MARIADB_PORT_3306_TCP_ADDR || env.SEQ_MARIADB_HOST || env.SEQ_HOST || '127.0.0.1';
it('Connection timeout', () => {
it('Connection timeout', async () => {
const sequelize = Support.createSequelizeInstance({ host: testHost, port: 65535, dialectOptions: { connectTimeout: 500 } });
return expect(sequelize.connectionManager.getConnection()).to.have.been.rejectedWith(Sequelize.SequelizeConnectionError);
await expect(sequelize.connectionManager.getConnection()).to.have.been.rejectedWith(Sequelize.SequelizeConnectionError);
});
it('ECONNREFUSED', () => {
it('ECONNREFUSED', async () => {
const sequelize = Support.createSequelizeInstance({ host: testHost, port: 65535 });
return expect(sequelize.connectionManager.getConnection()).to.have.been.rejectedWith(Sequelize.ConnectionRefusedError);
await expect(sequelize.connectionManager.getConnection()).to.have.been.rejectedWith(Sequelize.ConnectionRefusedError);
});
it('ENOTFOUND', () => {
it('ENOTFOUND', async () => {
const sequelize = Support.createSequelizeInstance({ host: 'http://wowow.example.com' });
return expect(sequelize.connectionManager.getConnection()).to.have.been.rejectedWith(Sequelize.HostNotFoundError);
await expect(sequelize.connectionManager.getConnection()).to.have.been.rejectedWith(Sequelize.HostNotFoundError);
});
it('EHOSTUNREACH', () => {
it('EHOSTUNREACH', async () => {
const sequelize = Support.createSequelizeInstance({ host: '255.255.255.255' });
return expect(sequelize.connectionManager.getConnection()).to.have.been.rejectedWith(Sequelize.HostNotReachableError);
await expect(sequelize.connectionManager.getConnection()).to.have.been.rejectedWith(Sequelize.HostNotReachableError);
});
it('ER_ACCESS_DENIED_ERROR | ELOGIN', () => {
it('ER_ACCESS_DENIED_ERROR | ELOGIN', async () => {
const sequelize = new Support.Sequelize('localhost', 'was', 'ddsd', Support.sequelize.options);
return expect(sequelize.connectionManager.getConnection()).to.have.been.rejectedWith(Sequelize.AccessDeniedError);
await expect(sequelize.connectionManager.getConnection()).to.have.been.rejectedWith(Sequelize.AccessDeniedError);
});
});
......
......@@ -8,14 +8,14 @@ const chai = require('chai'),
if (dialect !== 'mariadb') return;
describe('[MariaDB Specific] DAO', () => {
beforeEach(function() {
beforeEach(async function() {
this.sequelize.options.quoteIdentifiers = true;
this.User = this.sequelize.define('User', {
username: DataTypes.STRING,
email: DataTypes.STRING,
location: DataTypes.GEOMETRY()
});
return this.User.sync({ force: true });
await this.User.sync({ force: true });
});
afterEach(function() {
......@@ -24,113 +24,100 @@ describe('[MariaDB Specific] DAO', () => {
describe('integers', () => {
describe('integer', () => {
beforeEach(function() {
beforeEach(async function() {
this.User = this.sequelize.define('User', {
aNumber: DataTypes.INTEGER
});
return this.User.sync({ force: true });
await this.User.sync({ force: true });
});
it('positive', function() {
it('positive', async function() {
const User = this.User;
return User.create({ aNumber: 2147483647 }).then(user => {
const user = await User.create({ aNumber: 2147483647 });
expect(user.aNumber).to.equal(2147483647);
return User.findOne({ where: { aNumber: 2147483647 } }).then(_user => {
const _user = await User.findOne({ where: { aNumber: 2147483647 } });
expect(_user.aNumber).to.equal(2147483647);
});
});
});
it('negative', function() {
it('negative', async function() {
const User = this.User;
return User.create({ aNumber: -2147483647 }).then(user => {
const user = await User.create({ aNumber: -2147483647 });
expect(user.aNumber).to.equal(-2147483647);
return User.findOne({ where: { aNumber: -2147483647 } }).then(_user => {
const _user = await User.findOne({ where: { aNumber: -2147483647 } });
expect(_user.aNumber).to.equal(-2147483647);
});
});
});
});
describe('bigint', () => {
beforeEach(function() {
beforeEach(async function() {
this.User = this.sequelize.define('User', {
aNumber: DataTypes.BIGINT
});
return this.User.sync({ force: true });
await this.User.sync({ force: true });
});
it('positive', function() {
it('positive', async function() {
const User = this.User;
return User.create({ aNumber: '9223372036854775807' }).then(user => {
const user = await User.create({ aNumber: '9223372036854775807' });
expect(user.aNumber).to.equal('9223372036854775807');
return User.findOne({ where: { aNumber: '9223372036854775807' } }).then(
_user => {
return expect(_user.aNumber.toString()).to.equal(
'9223372036854775807');
});
});
const _user = await User.findOne({ where: { aNumber: '9223372036854775807' } });
await expect(_user.aNumber.toString()).to.equal('9223372036854775807');
});
it('negative', function() {
it('negative', async function() {
const User = this.User;
return User.create({ aNumber: '-9223372036854775807' }).then(user => {
const user = await User.create({ aNumber: '-9223372036854775807' });
expect(user.aNumber).to.equal('-9223372036854775807');
return User.findOne(
{ where: { aNumber: '-9223372036854775807' } }).then(_user => {
return expect(_user.aNumber.toString()).to.equal(
'-9223372036854775807');
});
});
const _user = await User.findOne(
{ where: { aNumber: '-9223372036854775807' } });
await expect(_user.aNumber.toString()).to.equal('-9223372036854775807');
});
});
});
it('should save geometry correctly', function() {
it('should save geometry correctly', async function() {
const point = { type: 'Point', coordinates: [39.807222, -76.984722] };
return this.User.create(
{ username: 'user', email: 'foo@bar.com', location: point }).then(
newUser => {
const newUser = await this.User.create(
{ username: 'user', email: 'foo@bar.com', location: point });
expect(newUser.location).to.deep.eql(point);
});
});
it('should update geometry correctly', function() {
it('should update geometry correctly', async function() {
const User = this.User;
const point1 = { type: 'Point', coordinates: [39.807222, -76.984722] };
const point2 = { type: 'Point', coordinates: [39.828333, -77.232222] };
return User.create(
{ username: 'user', email: 'foo@bar.com', location: point1 })
.then(oldUser => {
return User.update({ location: point2 },
{ where: { username: oldUser.username } })
.then(() => {
return User.findOne({ where: { username: oldUser.username } });
})
.then(updatedUser => {
const oldUser = await User.create(
{ username: 'user', email: 'foo@bar.com', location: point1 });
await User.update({ location: point2 },
{ where: { username: oldUser.username } });
const updatedUser = await User.findOne({ where: { username: oldUser.username } });
expect(updatedUser.location).to.deep.eql(point2);
});
});
});
it('should read geometry correctly', function() {
it('should read geometry correctly', async function() {
const User = this.User;
const point = { type: 'Point', coordinates: [39.807222, -76.984722] };
return User.create(
{ username: 'user', email: 'foo@bar.com', location: point }).then(
user => {
return User.findOne({ where: { username: user.username } });
}).then(user => {
const user0 = await User.create(
{ username: 'user', email: 'foo@bar.com', location: point });
const user = await User.findOne({ where: { username: user0.username } });
expect(user.location).to.deep.eql(point);
});
});
});
......@@ -9,12 +9,16 @@ const chai = require('chai'),
if (dialect !== 'mariadb') return;
describe('[MariaDB Specific] Errors', () => {
const validateError = (promise, errClass, errValues) => {
const validateError = async (promise, errClass, errValues) => {
const wanted = { ...errValues };
return expect(promise).to.have.been.rejectedWith(errClass).then(() =>
promise.catch(err => Object.keys(wanted).forEach(
k => expect(err[k]).to.eql(wanted[k]))));
await expect(promise).to.have.been.rejectedWith(errClass);
try {
return await promise;
} catch (err) {
return Object.keys(wanted).forEach(k => expect(err[k]).to.eql(wanted[k]));
}
};
describe('ForeignKeyConstraintError', () => {
......@@ -33,28 +37,26 @@ describe('[MariaDB Specific] Errors', () => {
{ foreignKey: 'primaryUserId', as: 'primaryUsers' });
});
it('in context of DELETE restriction', function() {
it('in context of DELETE restriction', async function() {
const ForeignKeyConstraintError = this.sequelize.ForeignKeyConstraintError;
const ctx = {};
return this.sequelize.sync({ force: true }).then(() => {
return Promise.all([
await this.sequelize.sync({ force: true });
const [user1, task1] = await Promise.all([
this.User.create({ id: 67, username: 'foo' }),
this.Task.create({ id: 52, title: 'task' })
]);
}).then(([user1, task1]) => {
ctx.user1 = user1;
ctx.task1 = task1;
return user1.setTasks([task1]);
}).then(() => {
return Promise.all([
validateError(ctx.user1.destroy(), ForeignKeyConstraintError, {
await user1.setTasks([task1]);
await Promise.all([
validateError(user1.destroy(), ForeignKeyConstraintError, {
fields: ['userId'],
table: 'users',
value: undefined,
index: 'tasksusers_ibfk_1',
reltype: 'parent'
}),
validateError(ctx.task1.destroy(), ForeignKeyConstraintError, {
validateError(task1.destroy(), ForeignKeyConstraintError, {
fields: ['taskId'],
table: 'tasks',
value: undefined,
......@@ -63,20 +65,23 @@ describe('[MariaDB Specific] Errors', () => {
})
]);
});
});
it('in context of missing relation', function() {
it('in context of missing relation', async function() {
const ForeignKeyConstraintError = this.sequelize.ForeignKeyConstraintError;
return this.sequelize.sync({ force: true }).then(() =>
validateError(this.Task.create({ title: 'task', primaryUserId: 5 }),
ForeignKeyConstraintError, {
await this.sequelize.sync({ force: true });
await validateError(
this.Task.create({ title: 'task', primaryUserId: 5 }),
ForeignKeyConstraintError,
{
fields: ['primaryUserId'],
table: 'users',
value: 5,
index: 'tasks_ibfk_1',
reltype: 'child'
}));
}
);
});
});
......
......@@ -9,19 +9,13 @@ if (dialect.match(/^mariadb/)) {
describe('QueryInterface', () => {
describe('databases', () => {
it('should create and drop database', function() {
return this.sequelize.query('SHOW DATABASES')
.then(res => {
it('should create and drop database', async function() {
const res = await this.sequelize.query('SHOW DATABASES');
const databaseNumber = res[0].length;
return this.sequelize.getQueryInterface().createDatabase('myDB')
.then(() => {
return this.sequelize.query('SHOW DATABASES');
})
.then(databases => {
await this.sequelize.getQueryInterface().createDatabase('myDB');
const databases = await this.sequelize.query('SHOW DATABASES');
expect(databases[0]).to.have.length(databaseNumber + 1);
return this.sequelize.getQueryInterface().dropDatabase('myDB');
});
});
await this.sequelize.getQueryInterface().dropDatabase('myDB');
});
});
});
......
......@@ -9,24 +9,24 @@ const dialect = Support.getTestDialect();
if (dialect.match(/^mssql/)) {
describe('[MSSQL Specific] Connection Manager', () => {
describe('Errors', () => {
it('ECONNREFUSED', () => {
it('ECONNREFUSED', async () => {
const sequelize = Support.createSequelizeInstance({ host: '127.0.0.1', port: 34237 });
return expect(sequelize.connectionManager.getConnection()).to.have.been.rejectedWith(Sequelize.ConnectionRefusedError);
await expect(sequelize.connectionManager.getConnection()).to.have.been.rejectedWith(Sequelize.ConnectionRefusedError);
});
it('ENOTFOUND', () => {
it('ENOTFOUND', async () => {
const sequelize = Support.createSequelizeInstance({ host: 'http://wowow.example.com' });
return expect(sequelize.connectionManager.getConnection()).to.have.been.rejectedWith(Sequelize.HostNotFoundError);
await expect(sequelize.connectionManager.getConnection()).to.have.been.rejectedWith(Sequelize.HostNotFoundError);
});
it('EHOSTUNREACH', () => {
it('EHOSTUNREACH', async () => {
const sequelize = Support.createSequelizeInstance({ host: '255.255.255.255' });
return expect(sequelize.connectionManager.getConnection()).to.have.been.rejectedWith(Sequelize.HostNotReachableError);
await expect(sequelize.connectionManager.getConnection()).to.have.been.rejectedWith(Sequelize.HostNotReachableError);
});
it('ER_ACCESS_DENIED_ERROR | ELOGIN', () => {
it('ER_ACCESS_DENIED_ERROR | ELOGIN', async () => {
const sequelize = new Support.Sequelize('localhost', 'was', 'ddsd', Support.sequelize.options);
return expect(sequelize.connectionManager.getConnection()).to.have.been.rejectedWith(Sequelize.AccessDeniedError);
await expect(sequelize.connectionManager.getConnection()).to.have.been.rejectedWith(Sequelize.AccessDeniedError);
});
});
});
......
......@@ -11,20 +11,20 @@ const chai = require('chai'),
if (dialect.match(/^mssql/)) {
describe('[MSSQL Specific] Query Queue', () => {
beforeEach(function() {
beforeEach(async function() {
const User = this.User = this.sequelize.define('User', {
username: DataTypes.STRING
});
return this.sequelize.sync({ force: true }).then(() => {
return User.create({ username: 'John' });
});
await this.sequelize.sync({ force: true });
await User.create({ username: 'John' });
});
it('should queue concurrent requests to a connection', function() {
it('should queue concurrent requests to a connection', async function() {
const User = this.User;
return expect(this.sequelize.transaction(t => {
await expect(this.sequelize.transaction(async t => {
return Promise.all([
User.findOne({
transaction: t
......
......@@ -9,7 +9,7 @@ const chai = require('chai'),
if (dialect.match(/^mssql/)) {
describe('[MSSQL Specific] Regressions', () => {
it('does not duplicate columns in ORDER BY statement, #9008', function() {
it('does not duplicate columns in ORDER BY statement, #9008', async function() {
const LoginLog = this.sequelize.define('LoginLog', {
ID: {
field: 'id',
......@@ -45,22 +45,23 @@ if (dialect.match(/^mssql/)) {
foreignKey: 'UserID'
});
return this.sequelize.sync({ force: true })
.then(() => User.bulkCreate([
await this.sequelize.sync({ force: true });
const [vyom, shakti, nikita, arya] = await User.bulkCreate([
{ UserName: 'Vayom' },
{ UserName: 'Shaktimaan' },
{ UserName: 'Nikita' },
{ UserName: 'Aryamaan' }
], { returning: true }))
.then(([vyom, shakti, nikita, arya]) => {
return Promise.all([
], { returning: true });
await Promise.all([
vyom.createLoginLog(),
shakti.createLoginLog(),
nikita.createLoginLog(),
arya.createLoginLog()
]);
}).then(() => {
return LoginLog.findAll({
const logs = await LoginLog.findAll({
include: [
{
model: User,
......@@ -75,41 +76,36 @@ if (dialect.match(/^mssql/)) {
offset: 0,
limit: 10
});
}).then(logs => {
expect(logs).to.have.length(2);
expect(logs[0].User.get('UserName')).to.equal('Shaktimaan');
expect(logs[1].User.get('UserName')).to.equal('Aryamaan');
});
});
});
it('sets the varchar(max) length correctly on describeTable', function() {
it('sets the varchar(max) length correctly on describeTable', async function() {
const Users = this.sequelize.define('_Users', {
username: Sequelize.STRING('MAX')
}, { freezeTableName: true });
return Users.sync({ force: true }).then(() => {
return this.sequelize.getQueryInterface().describeTable('_Users').then(metadata => {
await Users.sync({ force: true });
const metadata = await this.sequelize.getQueryInterface().describeTable('_Users');
const username = metadata.username;
expect(username.type).to.include('(MAX)');
});
});
});
it('sets the char(10) length correctly on describeTable', function() {
it('sets the char(10) length correctly on describeTable', async function() {
const Users = this.sequelize.define('_Users', {
username: Sequelize.CHAR(10)
}, { freezeTableName: true });
return Users.sync({ force: true }).then(() => {
return this.sequelize.getQueryInterface().describeTable('_Users').then(metadata => {
await Users.sync({ force: true });
const metadata = await this.sequelize.getQueryInterface().describeTable('_Users');
const username = metadata.username;
expect(username.type).to.include('(10)');
});
});
});
it('saves value bigger than 2147483647, #11245', function() {
it('saves value bigger than 2147483647, #11245', async function() {
const BigIntTable = this.sequelize.define('BigIntTable', {
business_id: {
type: Sequelize.BIGINT,
......@@ -121,19 +117,17 @@ if (dialect.match(/^mssql/)) {
const bigIntValue = 2147483648;
return BigIntTable.sync({ force: true })
.then(() => {
return BigIntTable.create({
await BigIntTable.sync({ force: true });
await BigIntTable.create({
business_id: bigIntValue
});
})
.then(() => BigIntTable.findOne())
.then(record => {
const record = await BigIntTable.findOne();
expect(Number(record.business_id)).to.equals(bigIntValue);
});
});
it('saves boolean is true, #12090', function() {
it('saves boolean is true, #12090', async function() {
const BooleanTable = this.sequelize.define('BooleanTable', {
status: {
type: Sequelize.BOOLEAN,
......@@ -145,15 +139,13 @@ if (dialect.match(/^mssql/)) {
const value = true;
return BooleanTable.sync({ force: true })
.then(() => {
return BooleanTable.create({
await BooleanTable.sync({ force: true });
await BooleanTable.create({
status: value
});
})
.then(() => BooleanTable.findOne())
.then(record => {
const record = await BooleanTable.findOne();
expect(record.status).to.equals(value);
});
});
}
......@@ -10,30 +10,27 @@ if (dialect === 'mysql') {
describe('[MYSQL Specific] Associations', () => {
describe('many-to-many', () => {
describe('where tables have the same prefix', () => {
it('should create a table wp_table1wp_table2s', function() {
it('should create a table wp_table1wp_table2s', async function() {
const Table2 = this.sequelize.define('wp_table2', { foo: DataTypes.STRING }),
Table1 = this.sequelize.define('wp_table1', { foo: DataTypes.STRING });
Table1.belongsToMany(Table2, { through: 'wp_table1swp_table2s' });
Table2.belongsToMany(Table1, { through: 'wp_table1swp_table2s' });
return Table1.sync({ force: true }).then(() => {
return Table2.sync({ force: true }).then(() => {
await Table1.sync({ force: true });
await Table2.sync({ force: true });
expect(this.sequelize.modelManager.getModel('wp_table1swp_table2s')).to.exist;
});
});
});
});
describe('when join table name is specified', () => {
beforeEach(function() {
beforeEach(async function() {
const Table2 = this.sequelize.define('ms_table1', { foo: DataTypes.STRING }),
Table1 = this.sequelize.define('ms_table2', { foo: DataTypes.STRING });
Table1.belongsToMany(Table2, { through: 'table1_to_table2' });
Table2.belongsToMany(Table1, { through: 'table1_to_table2' });
return Table1.sync({ force: true }).then(() => {
return Table2.sync({ force: true });
});
await Table1.sync({ force: true });
await Table2.sync({ force: true });
});
it('should not use only a specified name', function() {
......@@ -44,7 +41,7 @@ if (dialect === 'mysql') {
});
describe('HasMany', () => {
beforeEach(function() {
beforeEach(async function() {
//prevent periods from occurring in the table name since they are used to delimit (table.column)
this.User = this.sequelize.define(`User${Math.ceil(Math.random() * 10000000)}`, { name: DataTypes.STRING });
this.Task = this.sequelize.define(`Task${Math.ceil(Math.random() * 10000000)}`, { name: DataTypes.STRING });
......@@ -62,70 +59,48 @@ if (dialect === 'mysql') {
tasks[i] = { name: `Task${Math.random()}` };
}
return this.sequelize.sync({ force: true }).then(() => {
return this.User.bulkCreate(users).then(() => {
return this.Task.bulkCreate(tasks);
});
});
await this.sequelize.sync({ force: true });
await this.User.bulkCreate(users);
await this.Task.bulkCreate(tasks);
});
describe('addDAO / getModel', () => {
beforeEach(function() {
beforeEach(async function() {
this.user = null;
this.task = null;
return this.User.findAll().then(_users => {
return this.Task.findAll().then(_tasks => {
const _users = await this.User.findAll();
const _tasks = await this.Task.findAll();
this.user = _users[0];
this.task = _tasks[0];
});
});
});
it('should correctly add an association to the dao', function() {
return this.user.getTasks().then(_tasks => {
expect(_tasks.length).to.equal(0);
return this.user.addTask(this.task).then(() => {
return this.user.getTasks().then(_tasks => {
expect(_tasks.length).to.equal(1);
});
});
});
it('should correctly add an association to the dao', async function() {
expect(await this.user.getTasks()).to.have.length(0);
await this.user.addTask(this.task);
expect(await this.user.getTasks()).to.have.length(1);
});
});
describe('removeDAO', () => {
beforeEach(function() {
beforeEach(async function() {
this.user = null;
this.tasks = null;
return this.User.findAll().then(_users => {
return this.Task.findAll().then(_tasks => {
const _users = await this.User.findAll();
const _tasks = await this.Task.findAll();
this.user = _users[0];
this.tasks = _tasks;
});
});
});
it('should correctly remove associated objects', function() {
return this.user.getTasks().then(__tasks => {
expect(__tasks.length).to.equal(0);
return this.user.setTasks(this.tasks).then(() => {
return this.user.getTasks().then(_tasks => {
expect(_tasks.length).to.equal(this.tasks.length);
return this.user.removeTask(this.tasks[0]).then(() => {
return this.user.getTasks().then(_tasks => {
expect(_tasks.length).to.equal(this.tasks.length - 1);
return this.user.removeTasks([this.tasks[1], this.tasks[2]]).then(() => {
return this.user.getTasks().then(_tasks => {
expect(_tasks).to.have.length(this.tasks.length - 3);
});
});
});
});
});
});
});
it('should correctly remove associated objects', async function() {
expect(await this.user.getTasks()).to.have.length(0);
await this.user.setTasks(this.tasks);
expect(await this.user.getTasks()).to.have.length(this.tasks.length);
await this.user.removeTask(this.tasks[0]);
expect(await this.user.getTasks()).to.have.length(this.tasks.length - 1);
await this.user.removeTasks([this.tasks[1], this.tasks[2]]);
expect(await this.user.getTasks()).to.have.length(this.tasks.length - 3);
});
});
});
......
......@@ -8,31 +8,32 @@ const DataTypes = require('../../../../lib/data-types');
if (dialect === 'mysql') {
describe('[MYSQL Specific] Connection Manager', () => {
it('-FOUND_ROWS can be suppressed to get back legacy behavior', () => {
it('-FOUND_ROWS can be suppressed to get back legacy behavior', async () => {
const sequelize = Support.createSequelizeInstance({ dialectOptions: { flags: '' } });
const User = sequelize.define('User', { username: DataTypes.STRING });
return User.sync({ force: true })
.then(() => User.create({ id: 1, username: 'jozef' }))
.then(() => User.update({ username: 'jozef' }, {
await User.sync({ force: true });
await User.create({ id: 1, username: 'jozef' });
const [affectedCount] = await User.update({ username: 'jozef' }, {
where: {
id: 1
}
}))
});
// https://github.com/sequelize/sequelize/issues/7184
.then(([affectedCount]) => affectedCount.should.equal(1));
await affectedCount.should.equal(1);
});
it('should acquire a valid connection when keepDefaultTimezone is true', () => {
it('should acquire a valid connection when keepDefaultTimezone is true', async () => {
const sequelize = Support.createSequelizeInstance({ keepDefaultTimezone: true, pool: { min: 1, max: 1, handleDisconnects: true, idle: 5000 } });
const cm = sequelize.connectionManager;
return sequelize
.sync()
.then(() => cm.getConnection())
.then(connection => {
await sequelize.sync();
const connection = await cm.getConnection();
expect(cm.validate(connection)).to.be.ok;
return cm.releaseConnection(connection);
});
await cm.releaseConnection(connection);
});
});
}
......@@ -10,11 +10,16 @@ const DataTypes = require('../../../../lib/data-types');
if (dialect === 'mysql') {
describe('[MYSQL Specific] Errors', () => {
const validateError = (promise, errClass, errValues) => {
const validateError = async (promise, errClass, errValues) => {
const wanted = { ...errValues };
return expect(promise).to.have.been.rejectedWith(errClass).then(() =>
promise.catch(err => Object.keys(wanted).forEach(k => expect(err[k]).to.eql(wanted[k]))));
await expect(promise).to.have.been.rejectedWith(errClass);
try {
return await promise;
} catch (err) {
return Object.keys(wanted).forEach(k => expect(err[k]).to.eql(wanted[k]));
}
};
describe('ForeignKeyConstraintError', () => {
......@@ -29,27 +34,25 @@ if (dialect === 'mysql') {
this.Task.belongsTo(this.User, { foreignKey: 'primaryUserId', as: 'primaryUsers' });
});
it('in context of DELETE restriction', function() {
const ctx = {};
return this.sequelize.sync({ force: true }).then(() => {
return Promise.all([
it('in context of DELETE restriction', async function() {
await this.sequelize.sync({ force: true });
const [user1, task1] = await Promise.all([
this.User.create({ id: 67, username: 'foo' }),
this.Task.create({ id: 52, title: 'task' })
]);
}).then(([user1, task1]) => {
ctx.user1 = user1;
ctx.task1 = task1;
return user1.setTasks([task1]);
}).then(() => {
return Promise.all([
validateError(ctx.user1.destroy(), Sequelize.ForeignKeyConstraintError, {
await user1.setTasks([task1]);
await Promise.all([
validateError(user1.destroy(), Sequelize.ForeignKeyConstraintError, {
fields: ['userId'],
table: 'users',
value: undefined,
index: 'tasksusers_ibfk_1',
reltype: 'parent'
}),
validateError(ctx.task1.destroy(), Sequelize.ForeignKeyConstraintError, {
validateError(task1.destroy(), Sequelize.ForeignKeyConstraintError, {
fields: ['taskId'],
table: 'tasks',
value: undefined,
......@@ -58,17 +61,21 @@ if (dialect === 'mysql') {
})
]);
});
});
it('in context of missing relation', function() {
return this.sequelize.sync({ force: true }).then(() =>
validateError(this.Task.create({ title: 'task', primaryUserId: 5 }), Sequelize.ForeignKeyConstraintError, {
it('in context of missing relation', async function() {
await this.sequelize.sync({ force: true });
await validateError(
this.Task.create({ title: 'task', primaryUserId: 5 }),
Sequelize.ForeignKeyConstraintError,
{
fields: ['primaryUserId'],
table: 'users',
value: 5,
index: 'tasks_ibfk_1',
reltype: 'child'
}));
}
);
});
});
});
......
......@@ -11,7 +11,7 @@ describe(Support.getTestDialectTeaser('Warning'), () => {
// We can only test MySQL warnings when using MySQL.
if (dialect === 'mysql') {
describe('logging', () => {
it('logs warnings when there are warnings', () => {
it('logs warnings when there are warnings', async () => {
const logger = sinon.spy(console, 'log');
const sequelize = Support.createSequelizeInstance({
logging: logger,
......@@ -23,20 +23,16 @@ describe(Support.getTestDialectTeaser('Warning'), () => {
name: Sequelize.DataTypes.STRING(1, true)
});
return sequelize.sync({ force: true }).then(() => {
return sequelize.authenticate();
}).then(() => {
return sequelize.query("SET SESSION sql_mode='';");
}).then(() => {
return Model.create({
await sequelize.sync({ force: true });
await sequelize.authenticate();
await sequelize.query("SET SESSION sql_mode='';");
await Model.create({
name: 'very-long-long-name'
});
}).then(() => {
// last log is warning message
expect(logger.args[logger.args.length - 1][0]).to.be.match(/^MySQL Warnings \(default\):.*/m);
}, () => {
expect.fail();
});
});
});
}
......
......@@ -43,7 +43,7 @@ if (dialect.match(/^postgres/)) {
describe('HasMany', () => {
describe('addDAO / getModel', () => {
beforeEach(function() {
beforeEach(async function() {
//prevent periods from occurring in the table name since they are used to delimit (table.column)
this.User = this.sequelize.define(`User${config.rand()}`, { name: DataTypes.STRING });
this.Task = this.sequelize.define(`Task${config.rand()}`, { name: DataTypes.STRING });
......@@ -61,34 +61,24 @@ if (dialect.match(/^postgres/)) {
tasks[i] = { name: `Task${Math.random()}` };
}
return this.sequelize.sync({ force: true }).then(() => {
return this.User.bulkCreate(users).then(() => {
return this.Task.bulkCreate(tasks).then(() => {
return this.User.findAll().then(_users => {
return this.Task.findAll().then(_tasks => {
await this.sequelize.sync({ force: true });
await this.User.bulkCreate(users);
await this.Task.bulkCreate(tasks);
const _users = await this.User.findAll();
const _tasks = await this.Task.findAll();
this.user = _users[0];
this.task = _tasks[0];
});
});
});
});
});
});
it('should correctly add an association to the dao', function() {
return this.user.getTasks().then(_tasks => {
expect(_tasks).to.have.length(0);
return this.user.addTask(this.task).then(() => {
return this.user.getTasks().then(_tasks => {
expect(_tasks).to.have.length(1);
});
});
});
it('should correctly add an association to the dao', async function() {
expect(await this.user.getTasks()).to.have.length(0);
await this.user.addTask(this.task);
expect(await this.user.getTasks()).to.have.length(1);
});
});
describe('removeDAO', () => {
it('should correctly remove associated objects', function() {
it('should correctly remove associated objects', async function() {
const users = [],
tasks = [];
......@@ -106,39 +96,23 @@ if (dialect.match(/^postgres/)) {
tasks[i] = { id: i + 1, name: `Task${Math.random()}` };
}
return this.sequelize.sync({ force: true }).then(() => {
return this.User.bulkCreate(users).then(() => {
return this.Task.bulkCreate(tasks).then(() => {
return this.User.findAll().then(_users => {
return this.Task.findAll().then(_tasks => {
await this.sequelize.sync({ force: true });
await this.User.bulkCreate(users);
await this.Task.bulkCreate(tasks);
const _users = await this.User.findAll();
const _tasks = await this.Task.findAll();
this.user = _users[0];
this.task = _tasks[0];
this.users = _users;
this.tasks = _tasks;
return this.user.getTasks().then(__tasks => {
expect(__tasks).to.have.length(0);
return this.user.setTasks(this.tasks).then(() => {
return this.user.getTasks().then(_tasks => {
expect(_tasks).to.have.length(this.tasks.length);
return this.user.removeTask(this.tasks[0]).then(() => {
return this.user.getTasks().then(_tasks => {
expect(_tasks).to.have.length(this.tasks.length - 1);
return this.user.removeTasks([this.tasks[1], this.tasks[2]]).then(() => {
return this.user.getTasks().then(_tasks => {
expect(_tasks).to.have.length(this.tasks.length - 3);
});
});
});
});
});
});
});
});
});
});
});
});
expect(await this.user.getTasks()).to.have.length(0);
await this.user.setTasks(this.tasks);
expect(await this.user.getTasks()).to.have.length(this.tasks.length);
await this.user.removeTask(this.tasks[0]);
expect(await this.user.getTasks()).to.have.length(this.tasks.length - 1);
await this.user.removeTasks([this.tasks[1], this.tasks[2]]);
expect(await this.user.getTasks()).to.have.length(this.tasks.length - 3);
});
});
});
......
......@@ -8,46 +8,38 @@ const chai = require('chai'),
if (dialect.match(/^postgres/)) {
describe('[POSTGRES] Sequelize', () => {
function checkTimezoneParsing(baseOptions) {
async function checkTimezoneParsing(baseOptions) {
const options = { ...baseOptions, timezone: 'Asia/Kolkata', timestamps: true };
const sequelize = Support.createSequelizeInstance(options);
const tzTable = sequelize.define('tz_table', { foo: DataTypes.STRING });
return tzTable.sync({ force: true }).then(() => {
return tzTable.create({ foo: 'test' }).then(row => {
await tzTable.sync({ force: true });
const row = await tzTable.create({ foo: 'test' });
expect(row).to.be.not.null;
});
});
}
it('should correctly parse the moment based timezone while fetching hstore oids', function() {
return checkTimezoneParsing(this.sequelize.options);
it('should correctly parse the moment based timezone while fetching hstore oids', async function() {
await checkTimezoneParsing(this.sequelize.options);
});
it('should set client_min_messages to warning by default', () => {
return Support.sequelize.query('SHOW client_min_messages')
.then(result => {
it('should set client_min_messages to warning by default', async () => {
const result = await Support.sequelize.query('SHOW client_min_messages');
expect(result[0].client_min_messages).to.equal('warning');
});
});
it('should allow overriding client_min_messages', () => {
it('should allow overriding client_min_messages', async () => {
const sequelize = Support.createSequelizeInstance({ clientMinMessages: 'ERROR' });
return sequelize.query('SHOW client_min_messages')
.then(result => {
const result = await sequelize.query('SHOW client_min_messages');
expect(result[0].client_min_messages).to.equal('error');
});
});
it('should not set client_min_messages if clientMinMessages is false', () => {
it('should not set client_min_messages if clientMinMessages is false', async () => {
const sequelize = Support.createSequelizeInstance({ clientMinMessages: false });
return sequelize.query('SHOW client_min_messages')
.then(result => {
const result = await sequelize.query('SHOW client_min_messages');
// `notice` is Postgres's default
expect(result[0].client_min_messages).to.equal('notice');
});
});
});
describe('Dynamic OIDs', () => {
const dynamicTypesToCheck = [
......@@ -79,9 +71,9 @@ if (dialect.match(/^postgres/)) {
return User.sync({ force: true });
}
it('should fetch regular dynamic oids and create parsers', () => {
it('should fetch regular dynamic oids and create parsers', async () => {
const sequelize = Support.sequelize;
return reloadDynamicOIDs(sequelize).then(() => {
await reloadDynamicOIDs(sequelize);
dynamicTypesToCheck.forEach(type => {
expect(type.types.postgres,
`DataType.${type.key}.types.postgres`).to.not.be.empty;
......@@ -101,11 +93,10 @@ if (dialect.match(/^postgres/)) {
});
});
});
it('should fetch enum dynamic oids and create parsers', () => {
it('should fetch enum dynamic oids and create parsers', async () => {
const sequelize = Support.sequelize;
return reloadDynamicOIDs(sequelize).then(() => {
await reloadDynamicOIDs(sequelize);
const enumOids = sequelize.connectionManager.enumOids;
const oidParserMap = sequelize.connectionManager.oidParserMap;
......@@ -119,11 +110,10 @@ if (dialect.match(/^postgres/)) {
expect(oidParserMap.get(arrayOid), 'oidParserMap.get(enumOids.arrayOids)').to.be.a('function');
}
});
});
it('should fetch range dynamic oids and create parsers', () => {
it('should fetch range dynamic oids and create parsers', async () => {
const sequelize = Support.sequelize;
return reloadDynamicOIDs(sequelize).then(() => {
await reloadDynamicOIDs(sequelize);
for (const baseKey in expCastTypes) {
const name = expCastTypes[baseKey];
const entry = sequelize.connectionManager.nameOidMap[name];
......@@ -139,7 +129,6 @@ if (dialect.match(/^postgres/)) {
`oidParserMap.get(nameOidMap[${name}].arrayRangeOid)`).to.be.a('function');
}
});
});
});
}
......@@ -11,7 +11,7 @@ const chai = require('chai'),
if (dialect.match(/^postgres/)) {
describe('[POSTGRES Specific] DAO', () => {
beforeEach(function() {
beforeEach(async function() {
this.sequelize.options.quoteIdentifiers = true;
this.User = this.sequelize.define('User', {
username: DataTypes.STRING,
......@@ -35,15 +35,15 @@ if (dialect.match(/^postgres/)) {
holidays: DataTypes.ARRAY(DataTypes.RANGE(DataTypes.DATE)),
location: DataTypes.GEOMETRY()
});
return this.User.sync({ force: true });
await this.User.sync({ force: true });
});
afterEach(function() {
this.sequelize.options.quoteIdentifiers = true;
});
it('should be able to search within an array', function() {
return this.User.findAll({
it('should be able to search within an array', async function() {
await this.User.findAll({
where: {
email: ['hello', 'world']
},
......@@ -54,144 +54,116 @@ if (dialect.match(/^postgres/)) {
});
});
it('should be able to update a field with type ARRAY(JSON)', function() {
return this.User.create({
it('should be able to update a field with type ARRAY(JSON)', async function() {
const userInstance = await this.User.create({
username: 'bob',
email: ['myemail@email.com'],
friends: [{
name: 'John Smith'
}]
}).then(userInstance => {
});
expect(userInstance.friends).to.have.length(1);
expect(userInstance.friends[0].name).to.equal('John Smith');
return userInstance.update({
const obj = await userInstance.update({
friends: [{
name: 'John Smythe'
}]
});
}).then(obj => obj['friends'])
.then(friends => {
const friends = await obj['friends'];
expect(friends).to.have.length(1);
expect(friends[0].name).to.equal('John Smythe');
return friends;
});
await friends;
});
it('should be able to find a record while searching in an array', function() {
return this.User.bulkCreate([
it('should be able to find a record while searching in an array', async function() {
await this.User.bulkCreate([
{ username: 'bob', email: ['myemail@email.com'] },
{ username: 'tony', email: ['wrongemail@email.com'] }
]).then(() => {
return this.User.findAll({ where: { email: ['myemail@email.com'] } }).then(user => {
]);
const user = await this.User.findAll({ where: { email: ['myemail@email.com'] } });
expect(user).to.be.instanceof(Array);
expect(user).to.have.length(1);
expect(user[0].username).to.equal('bob');
});
});
});
describe('json', () => {
it('should be able to retrieve a row with ->> operator', function() {
return Promise.all([
it('should be able to retrieve a row with ->> operator', async function() {
await Promise.all([
this.User.create({ username: 'swen', emergency_contact: { name: 'kate' } }),
this.User.create({ username: 'anna', emergency_contact: { name: 'joe' } })])
.then(() => {
return this.User.findOne({ where: sequelize.json("emergency_contact->>'name'", 'kate'), attributes: ['username', 'emergency_contact'] });
})
.then(user => {
this.User.create({ username: 'anna', emergency_contact: { name: 'joe' } })]);
const user = await this.User.findOne({ where: sequelize.json("emergency_contact->>'name'", 'kate'), attributes: ['username', 'emergency_contact'] });
expect(user.emergency_contact.name).to.equal('kate');
});
});
it('should be able to query using the nested query language', function() {
return Promise.all([
it('should be able to query using the nested query language', async function() {
await Promise.all([
this.User.create({ username: 'swen', emergency_contact: { name: 'kate' } }),
this.User.create({ username: 'anna', emergency_contact: { name: 'joe' } })])
.then(() => {
return this.User.findOne({
this.User.create({ username: 'anna', emergency_contact: { name: 'joe' } })]);
const user = await this.User.findOne({
where: sequelize.json({ emergency_contact: { name: 'kate' } })
});
})
.then(user => {
expect(user.emergency_contact.name).to.equal('kate');
});
});
it('should be able to query using dot syntax', function() {
return Promise.all([
it('should be able to query using dot syntax', async function() {
await Promise.all([
this.User.create({ username: 'swen', emergency_contact: { name: 'kate' } }),
this.User.create({ username: 'anna', emergency_contact: { name: 'joe' } })])
.then(() => {
return this.User.findOne({ where: sequelize.json('emergency_contact.name', 'joe') });
})
.then(user => {
this.User.create({ username: 'anna', emergency_contact: { name: 'joe' } })]);
const user = await this.User.findOne({ where: sequelize.json('emergency_contact.name', 'joe') });
expect(user.emergency_contact.name).to.equal('joe');
});
});
it('should be able to query using dot syntax with uppercase name', function() {
return Promise.all([
it('should be able to query using dot syntax with uppercase name', async function() {
await Promise.all([
this.User.create({ username: 'swen', emergencyContact: { name: 'kate' } }),
this.User.create({ username: 'anna', emergencyContact: { name: 'joe' } })])
.then(() => {
return this.User.findOne({
this.User.create({ username: 'anna', emergencyContact: { name: 'joe' } })]);
const user = await this.User.findOne({
attributes: [[sequelize.json('emergencyContact.name'), 'contactName']],
where: sequelize.json('emergencyContact.name', 'joe')
});
})
.then(user => {
expect(user.get('contactName')).to.equal('joe');
});
});
it('should be able to store values that require JSON escaping', function() {
it('should be able to store values that require JSON escaping', async function() {
const text = "Multi-line '$string' needing \"escaping\" for $$ and $1 type values";
return this.User.create({ username: 'swen', emergency_contact: { value: text } })
.then(user => {
expect(user.isNewRecord).to.equal(false);
})
.then(() => {
return this.User.findOne({ where: { username: 'swen' } });
})
.then(() => {
return this.User.findOne({ where: sequelize.json('emergency_contact.value', text) });
})
.then(user => {
const user0 = await this.User.create({ username: 'swen', emergency_contact: { value: text } });
expect(user0.isNewRecord).to.equal(false);
await this.User.findOne({ where: { username: 'swen' } });
const user = await this.User.findOne({ where: sequelize.json('emergency_contact.value', text) });
expect(user.username).to.equal('swen');
});
});
it('should be able to findOrCreate with values that require JSON escaping', function() {
it('should be able to findOrCreate with values that require JSON escaping', async function() {
const text = "Multi-line '$string' needing \"escaping\" for $$ and $1 type values";
return this.User.findOrCreate({ where: { username: 'swen' }, defaults: { emergency_contact: { value: text } } })
.then(user => {
expect(!user.isNewRecord).to.equal(true);
})
.then(() => {
return this.User.findOne({ where: { username: 'swen' } });
})
.then(() => {
return this.User.findOne({ where: sequelize.json('emergency_contact.value', text) });
})
.then(user => {
const user0 = await this.User.findOrCreate({ where: { username: 'swen' }, defaults: { emergency_contact: { value: text } } });
expect(!user0.isNewRecord).to.equal(true);
await this.User.findOne({ where: { username: 'swen' } });
const user = await this.User.findOne({ where: sequelize.json('emergency_contact.value', text) });
expect(user.username).to.equal('swen');
});
});
});
describe('hstore', () => {
it('should tell me that a column is hstore and not USER-DEFINED', function() {
return this.sequelize.queryInterface.describeTable('Users').then(table => {
it('should tell me that a column is hstore and not USER-DEFINED', async function() {
const table = await this.sequelize.queryInterface.describeTable('Users');
expect(table.settings.type).to.equal('HSTORE');
expect(table.document.type).to.equal('HSTORE');
});
});
it('should NOT stringify hstore with insert', function() {
return this.User.create({
it('should NOT stringify hstore with insert', async function() {
await this.User.create({
username: 'bob',
email: ['myemail@email.com'],
settings: { mailing: false, push: 'facebook', frequency: 3 }
......@@ -203,7 +175,7 @@ if (dialect.match(/^postgres/)) {
});
});
it('should not rename hstore fields', function() {
it('should not rename hstore fields', async function() {
const Equipment = this.sequelize.define('Equipment', {
grapplingHook: {
type: DataTypes.STRING,
......@@ -214,8 +186,9 @@ if (dialect.match(/^postgres/)) {
}
});
return Equipment.sync({ force: true }).then(() => {
return Equipment.findAll({
await Equipment.sync({ force: true });
await Equipment.findAll({
where: {
utilityBelt: {
grapplingHook: true
......@@ -226,9 +199,8 @@ if (dialect.match(/^postgres/)) {
}
});
});
});
it('should not rename json fields', function() {
it('should not rename json fields', async function() {
const Equipment = this.sequelize.define('Equipment', {
grapplingHook: {
type: DataTypes.STRING,
......@@ -239,8 +211,9 @@ if (dialect.match(/^postgres/)) {
}
});
return Equipment.sync({ force: true }).then(() => {
return Equipment.findAll({
await Equipment.sync({ force: true });
await Equipment.findAll({
where: {
utilityBelt: {
grapplingHook: true
......@@ -251,50 +224,48 @@ if (dialect.match(/^postgres/)) {
}
});
});
});
});
describe('range', () => {
it('should tell me that a column is range and not USER-DEFINED', function() {
return this.sequelize.queryInterface.describeTable('Users').then(table => {
it('should tell me that a column is range and not USER-DEFINED', async function() {
const table = await this.sequelize.queryInterface.describeTable('Users');
expect(table.course_period.type).to.equal('TSTZRANGE');
expect(table.available_amount.type).to.equal('INT4RANGE');
});
});
});
describe('enums', () => {
it('should be able to create enums with escape values', function() {
it('should be able to create enums with escape values', async function() {
const User = this.sequelize.define('UserEnums', {
mood: DataTypes.ENUM('happy', 'sad', '1970\'s')
});
return User.sync({ force: true });
await User.sync({ force: true });
});
it('should be able to ignore enum types that already exist', function() {
it('should be able to ignore enum types that already exist', async function() {
const User = this.sequelize.define('UserEnums', {
mood: DataTypes.ENUM('happy', 'sad', 'meh')
});
return User.sync({ force: true }).then(() => {
return User.sync();
});
await User.sync({ force: true });
await User.sync();
});
it('should be able to create/drop enums multiple times', function() {
it('should be able to create/drop enums multiple times', async function() {
const User = this.sequelize.define('UserEnums', {
mood: DataTypes.ENUM('happy', 'sad', 'meh')
});
return User.sync({ force: true }).then(() => {
return User.sync({ force: true });
});
await User.sync({ force: true });
await User.sync({ force: true });
});
it('should be able to create/drop multiple enums multiple times', function() {
it('should be able to create/drop multiple enums multiple times', async function() {
const DummyModel = this.sequelize.define('Dummy-pg', {
username: DataTypes.STRING,
theEnumOne: {
......@@ -315,16 +286,14 @@ if (dialect.match(/^postgres/)) {
}
});
return DummyModel.sync({ force: true }).then(() => {
await DummyModel.sync({ force: true });
// now sync one more time:
return DummyModel.sync({ force: true }).then(() => {
await DummyModel.sync({ force: true });
// sync without dropping
return DummyModel.sync();
});
});
await DummyModel.sync();
});
it('should be able to create/drop multiple enums multiple times with field name (#7812)', function() {
it('should be able to create/drop multiple enums multiple times with field name (#7812)', async function() {
const DummyModel = this.sequelize.define('Dummy-pg', {
username: DataTypes.STRING,
theEnumOne: {
......@@ -347,55 +316,47 @@ if (dialect.match(/^postgres/)) {
}
});
return DummyModel.sync({ force: true }).then(() => {
await DummyModel.sync({ force: true });
// now sync one more time:
return DummyModel.sync({ force: true }).then(() => {
await DummyModel.sync({ force: true });
// sync without dropping
return DummyModel.sync();
});
});
await DummyModel.sync();
});
it('should be able to add values to enum types', function() {
it('should be able to add values to enum types', async function() {
let User = this.sequelize.define('UserEnums', {
mood: DataTypes.ENUM('happy', 'sad', 'meh')
});
return User.sync({ force: true }).then(() => {
await User.sync({ force: true });
User = this.sequelize.define('UserEnums', {
mood: DataTypes.ENUM('neutral', 'happy', 'sad', 'ecstatic', 'meh', 'joyful')
});
return User.sync();
}).then(() => {
return this.sequelize.getQueryInterface().pgListEnums(User.getTableName());
}).then(enums => {
await User.sync();
const enums = await this.sequelize.getQueryInterface().pgListEnums(User.getTableName());
expect(enums).to.have.length(1);
expect(enums[0].enum_value).to.equal('{neutral,happy,sad,ecstatic,meh,joyful}');
});
});
it('should be able to add multiple values with different order', function() {
it('should be able to add multiple values with different order', async function() {
let User = this.sequelize.define('UserEnums', {
priority: DataTypes.ENUM('1', '2', '6')
});
return User.sync({ force: true }).then(() => {
await User.sync({ force: true });
User = this.sequelize.define('UserEnums', {
priority: DataTypes.ENUM('0', '1', '2', '3', '4', '5', '6', '7')
});
return User.sync();
}).then(() => {
return this.sequelize.getQueryInterface().pgListEnums(User.getTableName());
}).then(enums => {
await User.sync();
const enums = await this.sequelize.getQueryInterface().pgListEnums(User.getTableName());
expect(enums).to.have.length(1);
expect(enums[0].enum_value).to.equal('{0,1,2,3,4,5,6,7}');
});
});
describe('ARRAY(ENUM)', () => {
it('should be able to ignore enum types that already exist', function() {
it('should be able to ignore enum types that already exist', async function() {
const User = this.sequelize.define('UserEnums', {
permissions: DataTypes.ARRAY(DataTypes.ENUM([
'access',
......@@ -405,10 +366,12 @@ if (dialect.match(/^postgres/)) {
]))
});
return User.sync({ force: true }).then(() => User.sync());
await User.sync({ force: true });
await User.sync();
});
it('should be able to create/drop enums multiple times', function() {
it('should be able to create/drop enums multiple times', async function() {
const User = this.sequelize.define('UserEnums', {
permissions: DataTypes.ARRAY(DataTypes.ENUM([
'access',
......@@ -418,10 +381,12 @@ if (dialect.match(/^postgres/)) {
]))
});
return User.sync({ force: true }).then(() => User.sync({ force: true }));
await User.sync({ force: true });
await User.sync({ force: true });
});
it('should be able to add values to enum types', function() {
it('should be able to add values to enum types', async function() {
let User = this.sequelize.define('UserEnums', {
permissions: DataTypes.ARRAY(DataTypes.ENUM([
'access',
......@@ -431,23 +396,20 @@ if (dialect.match(/^postgres/)) {
]))
});
return User.sync({ force: true }).then(() => {
await User.sync({ force: true });
User = this.sequelize.define('UserEnums', {
permissions: DataTypes.ARRAY(
DataTypes.ENUM('view', 'access', 'edit', 'write', 'check', 'delete')
)
});
return User.sync();
}).then(() => {
return this.sequelize.getQueryInterface().pgListEnums(User.getTableName());
}).then(enums => {
await User.sync();
const enums = await this.sequelize.getQueryInterface().pgListEnums(User.getTableName());
expect(enums).to.have.length(1);
expect(enums[0].enum_value).to.equal('{view,access,edit,write,check,delete}');
});
});
it('should be able to insert new record', function() {
it('should be able to insert new record', async function() {
const User = this.sequelize.define('UserEnums', {
name: DataTypes.STRING,
type: DataTypes.ENUM('A', 'B', 'C'),
......@@ -460,24 +422,22 @@ if (dialect.match(/^postgres/)) {
]))
});
return User.sync({ force: true })
.then(() => {
return User.create({
await User.sync({ force: true });
const user = await User.create({
name: 'file.exe',
type: 'C',
owners: ['userA', 'userB'],
permissions: ['access', 'write']
});
})
.then(user => {
expect(user.name).to.equal('file.exe');
expect(user.type).to.equal('C');
expect(user.owners).to.deep.equal(['userA', 'userB']);
expect(user.permissions).to.deep.equal(['access', 'write']);
});
});
it('should fail when trying to insert foreign element on ARRAY(ENUM)', function() {
it('should fail when trying to insert foreign element on ARRAY(ENUM)', async function() {
const User = this.sequelize.define('UserEnums', {
name: DataTypes.STRING,
type: DataTypes.ENUM('A', 'B', 'C'),
......@@ -490,7 +450,7 @@ if (dialect.match(/^postgres/)) {
]))
});
return expect(User.sync({ force: true }).then(() => {
await expect(User.sync({ force: true }).then(() => {
return User.create({
name: 'file.exe',
type: 'C',
......@@ -500,7 +460,7 @@ if (dialect.match(/^postgres/)) {
})).to.be.rejectedWith(/invalid input value for enum "enum_UserEnums_permissions": "cosmic_ray_disk_access"/);
});
it('should be able to find records', function() {
it('should be able to find records', async function() {
const User = this.sequelize.define('UserEnums', {
name: DataTypes.STRING,
type: DataTypes.ENUM('A', 'B', 'C'),
......@@ -512,9 +472,9 @@ if (dialect.match(/^postgres/)) {
]))
});
return User.sync({ force: true })
.then(() => {
return User.bulkCreate([{
await User.sync({ force: true });
await User.bulkCreate([{
name: 'file1.exe',
type: 'C',
permissions: ['access', 'write']
......@@ -527,9 +487,8 @@ if (dialect.match(/^postgres/)) {
type: 'B',
permissions: ['access', 'write', 'delete']
}]);
})
.then(() => {
return User.findAll({
const users = await User.findAll({
where: {
type: {
[Op.in]: ['A', 'C']
......@@ -539,8 +498,7 @@ if (dialect.match(/^postgres/)) {
}
}
});
})
.then(users => {
expect(users.length).to.equal(1);
expect(users[0].name).to.equal('file1.exe');
expect(users[0].type).to.equal('C');
......@@ -548,84 +506,75 @@ if (dialect.match(/^postgres/)) {
});
});
});
});
describe('integers', () => {
describe('integer', () => {
beforeEach(function() {
beforeEach(async function() {
this.User = this.sequelize.define('User', {
aNumber: DataTypes.INTEGER
});
return this.User.sync({ force: true });
await this.User.sync({ force: true });
});
it('positive', function() {
it('positive', async function() {
const User = this.User;
return User.create({ aNumber: 2147483647 }).then(user => {
const user = await User.create({ aNumber: 2147483647 });
expect(user.aNumber).to.equal(2147483647);
return User.findOne({ where: { aNumber: 2147483647 } }).then(_user => {
const _user = await User.findOne({ where: { aNumber: 2147483647 } });
expect(_user.aNumber).to.equal(2147483647);
});
});
});
it('negative', function() {
it('negative', async function() {
const User = this.User;
return User.create({ aNumber: -2147483647 }).then(user => {
const user = await User.create({ aNumber: -2147483647 });
expect(user.aNumber).to.equal(-2147483647);
return User.findOne({ where: { aNumber: -2147483647 } }).then(_user => {
const _user = await User.findOne({ where: { aNumber: -2147483647 } });
expect(_user.aNumber).to.equal(-2147483647);
});
});
});
});
describe('bigint', () => {
beforeEach(function() {
beforeEach(async function() {
this.User = this.sequelize.define('User', {
aNumber: DataTypes.BIGINT
});
return this.User.sync({ force: true });
await this.User.sync({ force: true });
});
it('positive', function() {
it('positive', async function() {
const User = this.User;
return User.create({ aNumber: '9223372036854775807' }).then(user => {
const user = await User.create({ aNumber: '9223372036854775807' });
expect(user.aNumber).to.equal('9223372036854775807');
return User.findOne({ where: { aNumber: '9223372036854775807' } }).then(_user => {
const _user = await User.findOne({ where: { aNumber: '9223372036854775807' } });
expect(_user.aNumber).to.equal('9223372036854775807');
});
});
});
it('negative', function() {
it('negative', async function() {
const User = this.User;
return User.create({ aNumber: '-9223372036854775807' }).then(user => {
const user = await User.create({ aNumber: '-9223372036854775807' });
expect(user.aNumber).to.equal('-9223372036854775807');
return User.findOne({ where: { aNumber: '-9223372036854775807' } }).then(_user => {
const _user = await User.findOne({ where: { aNumber: '-9223372036854775807' } });
expect(_user.aNumber).to.equal('-9223372036854775807');
});
});
});
});
});
describe('timestamps', () => {
beforeEach(function() {
beforeEach(async function() {
this.User = this.sequelize.define('User', {
dates: DataTypes.ARRAY(DataTypes.DATE)
});
return this.User.sync({ force: true });
await this.User.sync({ force: true });
});
it('should use bind params instead of "TIMESTAMP WITH TIME ZONE"', function() {
return this.User.create({
it('should use bind params instead of "TIMESTAMP WITH TIME ZONE"', async function() {
await this.User.create({
dates: []
}, {
logging(sql) {
......@@ -637,127 +586,105 @@ if (dialect.match(/^postgres/)) {
});
describe('model', () => {
it('create handles array correctly', function() {
return this.User
.create({ username: 'user', email: ['foo@bar.com', 'bar@baz.com'] })
.then(oldUser => {
it('create handles array correctly', async function() {
const oldUser = await this.User
.create({ username: 'user', email: ['foo@bar.com', 'bar@baz.com'] });
expect(oldUser.email).to.contain.members(['foo@bar.com', 'bar@baz.com']);
});
});
it('should save hstore correctly', function() {
return this.User.create({ username: 'user', email: ['foo@bar.com'], settings: { created: '"value"' } }).then(newUser => {
it('should save hstore correctly', async function() {
const newUser = await this.User.create({ username: 'user', email: ['foo@bar.com'], settings: { created: '"value"' } });
// Check to see if the default value for an hstore field works
expect(newUser.document).to.deep.equal({ default: "'value'" });
expect(newUser.settings).to.deep.equal({ created: '"value"' });
// Check to see if updating an hstore field works
return newUser.update({ settings: { should: 'update', to: 'this', first: 'place' } }).then(oldUser => {
const oldUser = await newUser.update({ settings: { should: 'update', to: 'this', first: 'place' } });
// Postgres always returns keys in alphabetical order (ascending)
expect(oldUser.settings).to.deep.equal({ first: 'place', should: 'update', to: 'this' });
});
});
});
it('should save hstore array correctly', function() {
it('should save hstore array correctly', async function() {
const User = this.User;
return this.User.create({
await this.User.create({
username: 'bob',
email: ['myemail@email.com'],
phones: [{ number: '123456789', type: 'mobile' }, { number: '987654321', type: 'landline' }, { number: '8675309', type: "Jenny's" }, { number: '5555554321', type: '"home\n"' }]
}).then(() => {
return User.findByPk(1).then(user => {
});
const user = await User.findByPk(1);
expect(user.phones.length).to.equal(4);
expect(user.phones[1].number).to.equal('987654321');
expect(user.phones[2].type).to.equal("Jenny's");
expect(user.phones[3].type).to.equal('"home\n"');
});
});
});
it('should bulkCreate with hstore property', function() {
it('should bulkCreate with hstore property', async function() {
const User = this.User;
return this.User.bulkCreate([{
await this.User.bulkCreate([{
username: 'bob',
email: ['myemail@email.com'],
settings: { mailing: true, push: 'facebook', frequency: 3 }
}]).then(() => {
return User.findByPk(1).then(user => {
}]);
const user = await User.findByPk(1);
expect(user.settings.mailing).to.equal('true');
});
});
});
it('should update hstore correctly', function() {
return this.User.create({ username: 'user', email: ['foo@bar.com'], settings: { test: '"value"' } }).then(newUser => {
it('should update hstore correctly', async function() {
const newUser = await this.User.create({ username: 'user', email: ['foo@bar.com'], settings: { test: '"value"' } });
// Check to see if the default value for an hstore field works
expect(newUser.document).to.deep.equal({ default: "'value'" });
expect(newUser.settings).to.deep.equal({ test: '"value"' });
// Check to see if updating an hstore field works
return this.User.update({ settings: { should: 'update', to: 'this', first: 'place' } }, { where: newUser.where() }).then(() => {
return newUser.reload().then(() => {
await this.User.update({ settings: { should: 'update', to: 'this', first: 'place' } }, { where: newUser.where() });
await newUser.reload();
// Postgres always returns keys in alphabetical order (ascending)
expect(newUser.settings).to.deep.equal({ first: 'place', should: 'update', to: 'this' });
});
});
});
});
it('should update hstore correctly and return the affected rows', function() {
return this.User.create({ username: 'user', email: ['foo@bar.com'], settings: { test: '"value"' } }).then(oldUser => {
it('should update hstore correctly and return the affected rows', async function() {
const oldUser = await this.User.create({ username: 'user', email: ['foo@bar.com'], settings: { test: '"value"' } });
// Update the user and check that the returned object's fields have been parsed by the hstore library
return this.User.update({ settings: { should: 'update', to: 'this', first: 'place' } }, { where: oldUser.where(), returning: true }).then(([count, users]) => {
const [count, users] = await this.User.update({ settings: { should: 'update', to: 'this', first: 'place' } }, { where: oldUser.where(), returning: true });
expect(count).to.equal(1);
expect(users[0].settings).to.deep.equal({ should: 'update', to: 'this', first: 'place' });
});
});
});
it('should read hstore correctly', function() {
it('should read hstore correctly', async function() {
const data = { username: 'user', email: ['foo@bar.com'], settings: { test: '"value"' } };
return this.User.create(data)
.then(() => {
return this.User.findOne({ where: { username: 'user' } });
})
.then(user => {
await this.User.create(data);
const user = await this.User.findOne({ where: { username: 'user' } });
// Check that the hstore fields are the same when retrieving the user
expect(user.settings).to.deep.equal(data.settings);
});
});
it('should read an hstore array correctly', function() {
it('should read an hstore array correctly', async function() {
const data = { username: 'user', email: ['foo@bar.com'], phones: [{ number: '123456789', type: 'mobile' }, { number: '987654321', type: 'landline' }] };
return this.User.create(data)
.then(() => {
await this.User.create(data);
// Check that the hstore fields are the same when retrieving the user
return this.User.findOne({ where: { username: 'user' } });
}).then(user => {
const user = await this.User.findOne({ where: { username: 'user' } });
expect(user.phones).to.deep.equal(data.phones);
});
});
it('should read hstore correctly from multiple rows', function() {
return this.User
.create({ username: 'user1', email: ['foo@bar.com'], settings: { test: '"value"' } })
.then(() => {
return this.User.create({ username: 'user2', email: ['foo2@bar.com'], settings: { another: '"example"' } });
})
.then(() => {
it('should read hstore correctly from multiple rows', async function() {
await this.User
.create({ username: 'user1', email: ['foo@bar.com'], settings: { test: '"value"' } });
await this.User.create({ username: 'user2', email: ['foo2@bar.com'], settings: { another: '"example"' } });
// Check that the hstore fields are the same when retrieving the user
return this.User.findAll({ order: ['username'] });
})
.then(users => {
const users = await this.User.findAll({ order: ['username'] });
expect(users[0].settings).to.deep.equal({ test: '"value"' });
expect(users[1].settings).to.deep.equal({ another: '"example"' });
});
});
it('should read hstore correctly from included models as well', function() {
it('should read hstore correctly from included models as well', async function() {
const HstoreSubmodel = this.sequelize.define('hstoreSubmodel', {
someValue: DataTypes.HSTORE
});
......@@ -765,30 +692,21 @@ if (dialect.match(/^postgres/)) {
this.User.hasMany(HstoreSubmodel);
return this.sequelize
.sync({ force: true })
.then(() => {
return this.User.create({ username: 'user1' })
.then(user => {
return HstoreSubmodel.create({ someValue: submodelValue })
.then(submodel => {
return user.setHstoreSubmodels([submodel]);
});
});
})
.then(() => {
return this.User.findOne({ where: { username: 'user1' }, include: [HstoreSubmodel] });
})
.then(user => {
await this.sequelize
.sync({ force: true });
const user0 = await this.User.create({ username: 'user1' });
const submodel = await HstoreSubmodel.create({ someValue: submodelValue });
await user0.setHstoreSubmodels([submodel]);
const user = await this.User.findOne({ where: { username: 'user1' }, include: [HstoreSubmodel] });
expect(user.hasOwnProperty('hstoreSubmodels')).to.be.ok;
expect(user.hstoreSubmodels.length).to.equal(1);
expect(user.hstoreSubmodels[0].someValue).to.deep.equal(submodelValue);
});
});
it('should save range correctly', function() {
it('should save range correctly', async function() {
const period = [new Date(2015, 0, 1), new Date(2015, 11, 31)];
return this.User.create({ username: 'user', email: ['foo@bar.com'], course_period: period }).then(newUser => {
const newUser = await this.User.create({ username: 'user', email: ['foo@bar.com'], course_period: period });
// Check to see if the default value for a range field works
expect(newUser.acceptable_marks.length).to.equal(2);
......@@ -804,29 +722,27 @@ if (dialect.match(/^postgres/)) {
expect(newUser.course_period[1].inclusive).to.deep.equal(false); // exclusive
// Check to see if updating a range field works
return newUser.update({ acceptable_marks: [0.8, 0.9] })
.then(() => newUser.reload()) // Ensure the acceptable_marks array is loaded with the complete range definition
.then(() => {
await newUser.update({ acceptable_marks: [0.8, 0.9] });
await newUser.reload(); // Ensure the acceptable_marks array is loaded with the complete range definition
expect(newUser.acceptable_marks.length).to.equal(2);
expect(newUser.acceptable_marks[0].value).to.equal('0.8'); // lower bound
expect(newUser.acceptable_marks[1].value).to.equal('0.9'); // upper bound
});
});
});
it('should save range array correctly', function() {
it('should save range array correctly', async function() {
const User = this.User;
const holidays = [
[new Date(2015, 3, 1), new Date(2015, 3, 15)],
[new Date(2015, 8, 1), new Date(2015, 9, 15)]
];
return User.create({
await User.create({
username: 'bob',
email: ['myemail@email.com'],
holidays
}).then(() => {
return User.findByPk(1).then(user => {
});
const user = await User.findByPk(1);
expect(user.holidays.length).to.equal(2);
expect(user.holidays[0].length).to.equal(2);
expect(user.holidays[0][0].value instanceof Date).to.be.ok;
......@@ -839,19 +755,18 @@ if (dialect.match(/^postgres/)) {
expect(user.holidays[1][0].value).to.equalTime(holidays[1][0]);
expect(user.holidays[1][1].value).to.equalTime(holidays[1][1]);
});
});
});
it('should bulkCreate with range property', function() {
it('should bulkCreate with range property', async function() {
const User = this.User;
const period = [new Date(2015, 0, 1), new Date(2015, 11, 31)];
return User.bulkCreate([{
await User.bulkCreate([{
username: 'bob',
email: ['myemail@email.com'],
course_period: period
}]).then(() => {
return User.findByPk(1).then(user => {
}]);
const user = await User.findByPk(1);
expect(user.course_period[0].value instanceof Date).to.be.ok;
expect(user.course_period[1].value instanceof Date).to.be.ok;
expect(user.course_period[0].value).to.equalTime(period[0]); // lower bound
......@@ -859,14 +774,12 @@ if (dialect.match(/^postgres/)) {
expect(user.course_period[0].inclusive).to.deep.equal(true); // inclusive
expect(user.course_period[1].inclusive).to.deep.equal(false); // exclusive
});
});
});
it('should update range correctly', function() {
it('should update range correctly', async function() {
const User = this.User;
const period = [new Date(2015, 0, 1), new Date(2015, 11, 31)];
return User.create({ username: 'user', email: ['foo@bar.com'], course_period: period }).then(newUser => {
const newUser = await User.create({ username: 'user', email: ['foo@bar.com'], course_period: period });
// Check to see if the default value for a range field works
expect(newUser.acceptable_marks.length).to.equal(2);
expect(newUser.acceptable_marks[0].value).to.equal('0.65'); // lower bound
......@@ -884,8 +797,8 @@ if (dialect.match(/^postgres/)) {
const period2 = [new Date(2015, 1, 1), new Date(2015, 10, 30)];
// Check to see if updating a range field works
return User.update({ course_period: period2 }, { where: newUser.where() }).then(() => {
return newUser.reload().then(() => {
await User.update({ course_period: period2 }, { where: newUser.where() });
await newUser.reload();
expect(newUser.course_period[0].value instanceof Date).to.be.ok;
expect(newUser.course_period[1].value instanceof Date).to.be.ok;
expect(newUser.course_period[0].value).to.equalTime(period2[0]); // lower bound
......@@ -893,22 +806,19 @@ if (dialect.match(/^postgres/)) {
expect(newUser.course_period[0].inclusive).to.deep.equal(true); // inclusive
expect(newUser.course_period[1].inclusive).to.deep.equal(false); // exclusive
});
});
});
});
it('should update range correctly and return the affected rows', function() {
it('should update range correctly and return the affected rows', async function() {
const User = this.User;
const period = [new Date(2015, 1, 1), new Date(2015, 10, 30)];
return User.create({
const oldUser = await User.create({
username: 'user',
email: ['foo@bar.com'],
course_period: [new Date(2015, 0, 1), new Date(2015, 11, 31)]
}).then(oldUser => {
});
// Update the user and check that the returned object's fields have been parsed by the range parser
return User.update({ course_period: period }, { where: oldUser.where(), returning: true })
.then(([count, users]) => {
const [count, users] = await User.update({ course_period: period }, { where: oldUser.where(), returning: true });
expect(count).to.equal(1);
expect(users[0].course_period[0].value instanceof Date).to.be.ok;
expect(users[0].course_period[1].value instanceof Date).to.be.ok;
......@@ -917,27 +827,21 @@ if (dialect.match(/^postgres/)) {
expect(users[0].course_period[0].inclusive).to.deep.equal(true); // inclusive
expect(users[0].course_period[1].inclusive).to.deep.equal(false); // exclusive
});
});
});
it('should read range correctly', function() {
it('should read range correctly', async function() {
const User = this.User;
const course_period = [{ value: new Date(2015, 1, 1), inclusive: false }, { value: new Date(2015, 10, 30), inclusive: false }];
const data = { username: 'user', email: ['foo@bar.com'], course_period };
return User.create(data)
.then(() => {
return User.findOne({ where: { username: 'user' } });
})
.then(user => {
await User.create(data);
const user = await User.findOne({ where: { username: 'user' } });
// Check that the range fields are the same when retrieving the user
expect(user.course_period).to.deep.equal(data.course_period);
});
});
it('should read range array correctly', function() {
it('should read range array correctly', async function() {
const User = this.User;
const holidays = [
[{ value: new Date(2015, 3, 1, 10), inclusive: true }, { value: new Date(2015, 3, 15), inclusive: true }],
......@@ -945,32 +849,25 @@ if (dialect.match(/^postgres/)) {
];
const data = { username: 'user', email: ['foo@bar.com'], holidays };
return User.create(data)
.then(() => {
await User.create(data);
// Check that the range fields are the same when retrieving the user
return User.findOne({ where: { username: 'user' } });
}).then(user => {
const user = await User.findOne({ where: { username: 'user' } });
expect(user.holidays).to.deep.equal(data.holidays);
});
});
it('should read range correctly from multiple rows', function() {
it('should read range correctly from multiple rows', async function() {
const User = this.User;
const periods = [
[new Date(2015, 0, 1), new Date(2015, 11, 31)],
[new Date(2016, 0, 1), new Date(2016, 11, 31)]
];
return User
.create({ username: 'user1', email: ['foo@bar.com'], course_period: periods[0] })
.then(() => {
return User.create({ username: 'user2', email: ['foo2@bar.com'], course_period: periods[1] });
})
.then(() => {
await User
.create({ username: 'user1', email: ['foo@bar.com'], course_period: periods[0] });
await User.create({ username: 'user2', email: ['foo2@bar.com'], course_period: periods[1] });
// Check that the range fields are the same when retrieving the user
return User.findAll({ order: ['username'] });
})
.then(users => {
const users = await User.findAll({ order: ['username'] });
expect(users[0].course_period[0].value).to.equalTime(periods[0][0]); // lower bound
expect(users[0].course_period[1].value).to.equalTime(periods[0][1]); // upper bound
expect(users[0].course_period[0].inclusive).to.deep.equal(true); // inclusive
......@@ -980,9 +877,8 @@ if (dialect.match(/^postgres/)) {
expect(users[1].course_period[0].inclusive).to.deep.equal(true); // inclusive
expect(users[1].course_period[1].inclusive).to.deep.equal(false); // exclusive
});
});
it('should read range correctly from included models as well', function() {
it('should read range correctly from included models as well', async function() {
const period = [new Date(2016, 0, 1), new Date(2016, 11, 31)];
const HolidayDate = this.sequelize.define('holidayDate', {
period: DataTypes.RANGE(DataTypes.DATE)
......@@ -990,22 +886,15 @@ if (dialect.match(/^postgres/)) {
this.User.hasMany(HolidayDate);
return this.sequelize
.sync({ force: true })
.then(() => {
return this.User
.create({ username: 'user', email: ['foo@bar.com'] })
.then(user => {
return HolidayDate.create({ period })
.then(holidayDate => {
return user.setHolidayDates([holidayDate]);
});
});
})
.then(() => {
return this.User.findOne({ where: { username: 'user' }, include: [HolidayDate] });
})
.then(user => {
await this.sequelize
.sync({ force: true });
const user0 = await this.User
.create({ username: 'user', email: ['foo@bar.com'] });
const holidayDate = await HolidayDate.create({ period });
await user0.setHolidayDates([holidayDate]);
const user = await this.User.findOne({ where: { username: 'user' }, include: [HolidayDate] });
expect(user.hasOwnProperty('holidayDates')).to.be.ok;
expect(user.holidayDates.length).to.equal(1);
expect(user.holidayDates[0].period.length).to.equal(2);
......@@ -1013,39 +902,33 @@ if (dialect.match(/^postgres/)) {
expect(user.holidayDates[0].period[1].value).to.equalTime(period[1]);
});
});
});
it('should save geometry correctly', function() {
it('should save geometry correctly', async function() {
const point = { type: 'Point', coordinates: [39.807222, -76.984722] };
return this.User.create({ username: 'user', email: ['foo@bar.com'], location: point }).then(newUser => {
const newUser = await this.User.create({ username: 'user', email: ['foo@bar.com'], location: point });
expect(newUser.location).to.deep.eql(point);
});
});
it('should update geometry correctly', function() {
it('should update geometry correctly', async function() {
const User = this.User;
const point1 = { type: 'Point', coordinates: [39.807222, -76.984722] };
const point2 = { type: 'Point', coordinates: [39.828333, -77.232222] };
return User.create({ username: 'user', email: ['foo@bar.com'], location: point1 }).then(oldUser => {
return User.update({ location: point2 }, { where: { username: oldUser.username }, returning: true }).then(([, updatedUsers]) => {
const oldUser = await User.create({ username: 'user', email: ['foo@bar.com'], location: point1 });
const [, updatedUsers] = await User.update({ location: point2 }, { where: { username: oldUser.username }, returning: true });
expect(updatedUsers[0].location).to.deep.eql(point2);
});
});
});
it('should read geometry correctly', function() {
it('should read geometry correctly', async function() {
const User = this.User;
const point = { type: 'Point', coordinates: [39.807222, -76.984722] };
return User.create({ username: 'user', email: ['foo@bar.com'], location: point }).then(user => {
return User.findOne({ where: { username: user.username } });
}).then(user => {
const user0 = await User.create({ username: 'user', email: ['foo@bar.com'], location: point });
const user = await User.findOne({ where: { username: user0.username } });
expect(user.location).to.deep.eql(point);
});
});
describe('[POSTGRES] Unquoted identifiers', () => {
it('can insert and select', function() {
it('can insert and select', async function() {
this.sequelize.options.quoteIdentifiers = false;
this.sequelize.getQueryInterface().queryGenerator.options.quoteIdentifiers = false;
......@@ -1056,10 +939,11 @@ if (dialect.match(/^postgres/)) {
quoteIdentifiers: false
});
return this.User.sync({ force: true }).then(() => {
return this.User
.create({ username: 'user', fullName: 'John Smith' })
.then(user => {
await this.User.sync({ force: true });
const user = await this.User
.create({ username: 'user', fullName: 'John Smith' });
// We can insert into a table with non-quoted identifiers
expect(user.id).to.exist;
expect(user.id).not.to.be.null;
......@@ -1067,31 +951,28 @@ if (dialect.match(/^postgres/)) {
expect(user.fullName).to.equal('John Smith');
// We can query by non-quoted identifiers
return this.User.findOne({
const user2 = await this.User.findOne({
where: { fullName: 'John Smith' }
}).then(user2 => {
});
// We can map values back to non-quoted identifiers
expect(user2.id).to.equal(user.id);
expect(user2.username).to.equal('user');
expect(user2.fullName).to.equal('John Smith');
// We can query and aggregate by non-quoted identifiers
return this.User
const count = await this.User
.count({
where: { fullName: 'John Smith' }
})
.then(count => {
});
this.sequelize.options.quoteIndentifiers = true;
this.sequelize.getQueryInterface().queryGenerator.options.quoteIdentifiers = true;
this.sequelize.options.logging = false;
expect(count).to.equal(1);
});
});
});
});
});
it('can select nested include', function() {
it('can select nested include', async function() {
this.sequelize.options.quoteIdentifiers = false;
this.sequelize.getQueryInterface().queryGenerator.options.quoteIdentifiers = false;
this.Professor = this.sequelize.define('Professor', {
......@@ -1118,18 +999,14 @@ if (dialect.match(/^postgres/)) {
this.Class.belongsTo(this.Professor);
this.Class.belongsToMany(this.Student, { through: this.ClassStudent });
this.Student.belongsToMany(this.Class, { through: this.ClassStudent });
return this.Professor.sync({ force: true })
.then(() => {
return this.Student.sync({ force: true });
})
.then(() => {
return this.Class.sync({ force: true });
})
.then(() => {
return this.ClassStudent.sync({ force: true });
})
.then(() => {
return this.Professor.bulkCreate([
try {
await this.Professor.sync({ force: true });
await this.Student.sync({ force: true });
await this.Class.sync({ force: true });
await this.ClassStudent.sync({ force: true });
await this.Professor.bulkCreate([
{
id: 1,
fullName: 'Albus Dumbledore'
......@@ -1139,9 +1016,8 @@ if (dialect.match(/^postgres/)) {
fullName: 'Severus Snape'
}
]);
})
.then(() => {
return this.Class.bulkCreate([
await this.Class.bulkCreate([
{
id: 1,
name: 'Transfiguration',
......@@ -1158,9 +1034,8 @@ if (dialect.match(/^postgres/)) {
ProfessorId: 2
}
]);
})
.then(() => {
return this.Student.bulkCreate([
await this.Student.bulkCreate([
{
id: 1,
fullName: 'Harry Potter'
......@@ -1178,9 +1053,8 @@ if (dialect.match(/^postgres/)) {
fullName: 'Hermione Granger'
}
]);
})
.then(() => {
return Promise.all([
await Promise.all([
this.Student.findByPk(1)
.then(Harry => {
return Harry.setClasses([1, 2, 3]);
......@@ -1198,9 +1072,8 @@ if (dialect.match(/^postgres/)) {
return Hermione.setClasses([1, 2, 3]);
})
]);
})
.then(() => {
return this.Professor.findAll({
const professors = await this.Professor.findAll({
include: [
{
model: this.Class,
......@@ -1217,16 +1090,14 @@ if (dialect.match(/^postgres/)) {
[this.Class, this.Student, 'id']
]
});
})
.then(professors => {
expect(professors.length).to.eql(2);
expect(professors[0].fullName).to.eql('Albus Dumbledore');
expect(professors[0].Classes.length).to.eql(1);
expect(professors[0].Classes[0].Students.length).to.eql(3);
})
.finally(() => {
} finally {
this.sequelize.getQueryInterface().queryGenerator.options.quoteIdentifiers = true;
});
}
});
});
});
......
......@@ -72,7 +72,7 @@ if (dialect === 'postgres') {
describe('DATE SQL', () => {
// create dummy user
it('should be able to create and update records with Infinity/-Infinity', function() {
it('should be able to create and update records with Infinity/-Infinity', async function() {
this.sequelize.options.typeValidation = true;
const date = new Date();
......@@ -97,69 +97,68 @@ if (dialect === 'postgres') {
timestamps: true
});
return User.sync({
await User.sync({
force: true
}).then(() => {
return User.create({
});
const user4 = await User.create({
username: 'bob',
anotherTime: Infinity
}, {
validate: true
});
}).then(user => {
expect(user.username).to.equal('bob');
expect(user.beforeTime).to.equal(-Infinity);
expect(user.sometime).to.be.withinTime(date, new Date());
expect(user.anotherTime).to.equal(Infinity);
expect(user.afterTime).to.equal(Infinity);
return user.update({
expect(user4.username).to.equal('bob');
expect(user4.beforeTime).to.equal(-Infinity);
expect(user4.sometime).to.be.withinTime(date, new Date());
expect(user4.anotherTime).to.equal(Infinity);
expect(user4.afterTime).to.equal(Infinity);
const user3 = await user4.update({
sometime: Infinity
}, {
returning: true
});
}).then(user => {
expect(user.sometime).to.equal(Infinity);
return user.update({
expect(user3.sometime).to.equal(Infinity);
const user2 = await user3.update({
sometime: Infinity
});
}).then(user => {
expect(user.sometime).to.equal(Infinity);
return user.update({
expect(user2.sometime).to.equal(Infinity);
const user1 = await user2.update({
sometime: this.sequelize.fn('NOW')
}, {
returning: true
});
}).then(user => {
expect(user.sometime).to.be.withinTime(date, new Date());
expect(user1.sometime).to.be.withinTime(date, new Date());
// find
return User.findAll();
}).then(users => {
const users = await User.findAll();
expect(users[0].beforeTime).to.equal(-Infinity);
expect(users[0].sometime).to.not.equal(Infinity);
expect(users[0].afterTime).to.equal(Infinity);
return users[0].update({
const user0 = await users[0].update({
sometime: date
});
}).then(user => {
expect(user.sometime).to.equalTime(date);
return user.update({
expect(user0.sometime).to.equalTime(date);
const user = await user0.update({
sometime: date
});
}).then(user => {
expect(user.sometime).to.equalTime(date);
});
});
});
describe('DATEONLY SQL', () => {
// create dummy user
it('should be able to create and update records with Infinity/-Infinity', function() {
it('should be able to create and update records with Infinity/-Infinity', async function() {
this.sequelize.options.typeValidation = true;
const date = new Date();
......@@ -184,66 +183,65 @@ if (dialect === 'postgres') {
timestamps: true
});
return User.sync({
await User.sync({
force: true
}).then(() => {
return User.create({
});
const user4 = await User.create({
username: 'bob',
anotherTime: Infinity
}, {
validate: true
});
}).then(user => {
expect(user.username).to.equal('bob');
expect(user.beforeTime).to.equal(-Infinity);
expect(new Date(user.sometime)).to.be.withinDate(date, new Date());
expect(user.anotherTime).to.equal(Infinity);
expect(user.afterTime).to.equal(Infinity);
return user.update({
expect(user4.username).to.equal('bob');
expect(user4.beforeTime).to.equal(-Infinity);
expect(new Date(user4.sometime)).to.be.withinDate(date, new Date());
expect(user4.anotherTime).to.equal(Infinity);
expect(user4.afterTime).to.equal(Infinity);
const user3 = await user4.update({
sometime: Infinity
}, {
returning: true
});
}).then(user => {
expect(user.sometime).to.equal(Infinity);
return user.update({
expect(user3.sometime).to.equal(Infinity);
const user2 = await user3.update({
sometime: Infinity
});
}).then(user => {
expect(user.sometime).to.equal(Infinity);
return user.update({
expect(user2.sometime).to.equal(Infinity);
const user1 = await user2.update({
sometime: this.sequelize.fn('NOW')
}, {
returning: true
});
}).then(user => {
expect(user.sometime).to.not.equal(Infinity);
expect(new Date(user.sometime)).to.be.withinDate(date, new Date());
expect(user1.sometime).to.not.equal(Infinity);
expect(new Date(user1.sometime)).to.be.withinDate(date, new Date());
// find
return User.findAll();
}).then(users => {
const users = await User.findAll();
expect(users[0].beforeTime).to.equal(-Infinity);
expect(users[0].sometime).to.not.equal(Infinity);
expect(users[0].afterTime).to.equal(Infinity);
return users[0].update({
const user0 = await users[0].update({
sometime: '1969-07-20'
});
}).then(user => {
expect(user.sometime).to.equal('1969-07-20');
return user.update({
expect(user0.sometime).to.equal('1969-07-20');
const user = await user0.update({
sometime: '1969-07-20'
});
}).then(user => {
expect(user.sometime).to.equal('1969-07-20');
});
});
});
});
}
......@@ -11,19 +11,19 @@ const chai = require('chai'),
if (dialect.match(/^postgres/)) {
describe('[POSTGRES Specific] ExclusionConstraintError', () => {
const constraintName = 'overlap_period';
beforeEach(function() {
beforeEach(async function() {
this.Booking = this.sequelize.define('Booking', {
roomNo: DataTypes.INTEGER,
period: DataTypes.RANGE(DataTypes.DATE)
});
return this.Booking
.sync({ force: true })
.then(() => {
return this.sequelize.query(
await this.Booking
.sync({ force: true });
await this.sequelize.query(
`ALTER TABLE "${this.Booking.tableName}" ADD CONSTRAINT ${constraintName} EXCLUDE USING gist ("roomNo" WITH =, period WITH &&)`
);
});
});
it('should contain error specific properties', () => {
const errDetails = {
......@@ -40,24 +40,23 @@ if (dialect.match(/^postgres/)) {
});
});
it('should throw ExclusionConstraintError when "period" value overlaps existing', function() {
it('should throw ExclusionConstraintError when "period" value overlaps existing', async function() {
const Booking = this.Booking;
return Booking
await Booking
.create({
roomNo: 1,
guestName: 'Incognito Visitor',
period: [new Date(2015, 0, 1), new Date(2015, 0, 3)]
})
.then(() => {
return expect(Booking
});
await expect(Booking
.create({
roomNo: 1,
guestName: 'Frequent Visitor',
period: [new Date(2015, 0, 2), new Date(2015, 0, 5)]
})).to.eventually.be.rejectedWith(Sequelize.ExclusionConstraintError);
});
});
});
}
......@@ -16,117 +16,111 @@ if (dialect.match(/^postgres/)) {
});
describe('createSchema', () => {
beforeEach(function() {
beforeEach(async function() {
// make sure we don't have a pre-existing schema called testSchema.
return this.queryInterface.dropSchema('testschema').catch(() => {});
await this.queryInterface.dropSchema('testschema').catch(() => {});
});
it('creates a schema', function() {
return this.queryInterface.createSchema('testschema')
.then(() => this.sequelize.query(`
it('creates a schema', async function() {
await this.queryInterface.createSchema('testschema');
const res = await this.sequelize.query(`
SELECT schema_name
FROM information_schema.schemata
WHERE schema_name = 'testschema';
`, { type: this.sequelize.QueryTypes.SELECT }))
.then(res => {
`, { type: this.sequelize.QueryTypes.SELECT });
expect(res, 'query results').to.not.be.empty;
expect(res[0].schema_name).to.be.equal('testschema');
});
});
it('works even when schema exists', function() {
return this.queryInterface.createSchema('testschema')
.then(() => this.queryInterface.createSchema('testschema'))
.then(() => this.sequelize.query(`
it('works even when schema exists', async function() {
await this.queryInterface.createSchema('testschema');
await this.queryInterface.createSchema('testschema');
const res = await this.sequelize.query(`
SELECT schema_name
FROM information_schema.schemata
WHERE schema_name = 'testschema';
`, { type: this.sequelize.QueryTypes.SELECT }))
.then(res => {
`, { type: this.sequelize.QueryTypes.SELECT });
expect(res, 'query results').to.not.be.empty;
expect(res[0].schema_name).to.be.equal('testschema');
});
});
});
describe('databaseVersion', () => {
it('reports version', function() {
return this.queryInterface.databaseVersion()
.then(res => {
it('reports version', async function() {
const res = await this.queryInterface.databaseVersion();
// check that result matches expected version number format. example 9.5.4
expect(res).to.match(/\d\.\d/);
});
});
});
describe('renameFunction', () => {
beforeEach(function() {
beforeEach(async function() {
// ensure the function names we'll use don't exist before we start.
// then setup our function to rename
return this.queryInterface.dropFunction('rftest1', [])
.catch(() => {})
.then(() => this.queryInterface.dropFunction('rftest2', []))
.catch(() => {})
.then(() => this.queryInterface.createFunction('rftest1', [], 'varchar', 'plpgsql', 'return \'testreturn\';', {}));
await this.queryInterface.dropFunction('rftest1', [])
.catch(() => {});
await this.queryInterface.dropFunction('rftest2', [])
.catch(() => {});
await this.queryInterface.createFunction('rftest1', [], 'varchar', 'plpgsql', 'return \'testreturn\';', {});
});
it('renames a function', function() {
return this.queryInterface.renameFunction('rftest1', [], 'rftest2')
.then(() => this.sequelize.query('select rftest2();', { type: this.sequelize.QueryTypes.SELECT }))
.then(res => {
it('renames a function', async function() {
await this.queryInterface.renameFunction('rftest1', [], 'rftest2');
const res = await this.sequelize.query('select rftest2();', { type: this.sequelize.QueryTypes.SELECT });
expect(res[0].rftest2).to.be.eql('testreturn');
});
});
});
describe('createFunction', () => {
beforeEach(function() {
beforeEach(async function() {
// make sure we don't have a pre-existing function called create_job
// this is needed to cover the edge case of afterEach not getting called because of an unexpected issue or stopage with the
// test suite causing a failure of afterEach's cleanup to be called.
return this.queryInterface.dropFunction('create_job', [{ type: 'varchar', name: 'test' }])
await this.queryInterface.dropFunction('create_job', [{ type: 'varchar', name: 'test' }])
// suppress errors here. if create_job doesn't exist thats ok.
.catch(() => {});
});
after(function() {
after(async function() {
// cleanup
return this.queryInterface.dropFunction('create_job', [{ type: 'varchar', name: 'test' }])
await this.queryInterface.dropFunction('create_job', [{ type: 'varchar', name: 'test' }])
// suppress errors here. if create_job doesn't exist thats ok.
.catch(() => {});
});
it('creates a stored procedure', function() {
it('creates a stored procedure', async function() {
const body = 'return test;';
const options = {};
// make our call to create a function
return this.queryInterface.createFunction('create_job', [{ type: 'varchar', name: 'test' }], 'varchar', 'plpgsql', body, options)
await this.queryInterface.createFunction('create_job', [{ type: 'varchar', name: 'test' }], 'varchar', 'plpgsql', body, options);
// validate
.then(() => this.sequelize.query('select create_job(\'test\');', { type: this.sequelize.QueryTypes.SELECT }))
.then(res => {
const res = await this.sequelize.query('select create_job(\'test\');', { type: this.sequelize.QueryTypes.SELECT });
expect(res[0].create_job).to.be.eql('test');
});
});
it('treats options as optional', function() {
it('treats options as optional', async function() {
const body = 'return test;';
// run with null options parameter
return this.queryInterface.createFunction('create_job', [{ type: 'varchar', name: 'test' }], 'varchar', 'plpgsql', body, null)
await this.queryInterface.createFunction('create_job', [{ type: 'varchar', name: 'test' }], 'varchar', 'plpgsql', body, null);
// validate
.then(() => this.sequelize.query('select create_job(\'test\');', { type: this.sequelize.QueryTypes.SELECT }))
.then(res => {
const res = await this.sequelize.query('select create_job(\'test\');', { type: this.sequelize.QueryTypes.SELECT });
expect(res[0].create_job).to.be.eql('test');
});
});
it('produces an error when missing expected parameters', function() {
it('produces an error when missing expected parameters', async function() {
const body = 'return 1;';
const options = {};
return Promise.all([
await Promise.all([
// requires functionName
expect(this.queryInterface.createFunction(null, [{ name: 'test' }], 'integer', 'plpgsql', body, options))
.to.be.rejectedWith(/createFunction missing some parameters. Did you pass functionName, returnType, language and body/),
......@@ -153,20 +147,26 @@ if (dialect.match(/^postgres/)) {
]);
});
it('overrides a function', function() {
it('overrides a function', async function() {
const first_body = 'return \'first\';';
const second_body = 'return \'second\';';
// create function
return this.queryInterface.createFunction('create_job', [{ type: 'varchar', name: 'test' }], 'varchar', 'plpgsql', first_body, null)
await this.queryInterface.createFunction('create_job', [{ type: 'varchar', name: 'test' }], 'varchar', 'plpgsql', first_body, null);
// override
.then(() => this.queryInterface.createFunction('create_job', [{ type: 'varchar', name: 'test' }], 'varchar', 'plpgsql', second_body, null, { force: true }))
await this.queryInterface.createFunction(
'create_job',
[{ type: 'varchar', name: 'test' }],
'varchar',
'plpgsql',
second_body,
null,
{ force: true }
);
// validate
.then(() => this.sequelize.query("select create_job('abc');", { type: this.sequelize.QueryTypes.SELECT }))
.then(res => {
const res = await this.sequelize.query("select create_job('abc');", { type: this.sequelize.QueryTypes.SELECT });
expect(res[0].create_job).to.be.eql('second');
});
});
it('produces an error when options.variables is missing expected parameters', function() {
const body = 'return 1;';
......@@ -180,43 +180,45 @@ if (dialect.match(/^postgres/)) {
.to.be.rejectedWith(/function variable must have a name and type/);
});
it('uses declared variables', function() {
it('uses declared variables', async function() {
const body = 'RETURN myVar + 1;';
const options = { variables: [{ type: 'integer', name: 'myVar', default: 100 }] };
return this.queryInterface.createFunction('add_one', [], 'integer', 'plpgsql', body, [], options)
.then(() => this.sequelize.query('select add_one();', { type: this.sequelize.QueryTypes.SELECT }))
.then(res => {
await this.queryInterface.createFunction('add_one', [], 'integer', 'plpgsql', body, [], options);
const res = await this.sequelize.query('select add_one();', { type: this.sequelize.QueryTypes.SELECT });
expect(res[0].add_one).to.be.eql(101);
});
});
});
describe('dropFunction', () => {
beforeEach(function() {
beforeEach(async function() {
const body = 'return test;';
const options = {};
// make sure we have a droptest function in place.
return this.queryInterface.createFunction('droptest', [{ type: 'varchar', name: 'test' }], 'varchar', 'plpgsql', body, options)
await this.queryInterface.createFunction(
'droptest',
[{ type: 'varchar', name: 'test' }],
'varchar',
'plpgsql',
body,
options
)
// suppress errors.. this could fail if the function is already there.. thats ok.
.catch(() => {});
});
it('can drop a function', function() {
return expect(
it('can drop a function', async function() {
// call drop function
this.queryInterface.dropFunction('droptest', [{ type: 'varchar', name: 'test' }])
await this.queryInterface.dropFunction('droptest', [{ type: 'varchar', name: 'test' }]);
await expect(
// now call the function we attempted to drop.. if dropFunction worked as expect it should produce an error.
.then(() => {
// call the function we attempted to drop.. if it is still there then throw an error informing that the expected behavior is not met.
return this.sequelize.query('select droptest(\'test\');', { type: this.sequelize.QueryTypes.SELECT });
})
this.sequelize.query('select droptest(\'test\');', { type: this.sequelize.QueryTypes.SELECT })
// test that we did get the expected error indicating that droptest was properly removed.
).to.be.rejectedWith(/.*function droptest.* does not exist/);
});
it('produces an error when missing expected parameters', function() {
return Promise.all([
it('produces an error when missing expected parameters', async function() {
await Promise.all([
expect(this.queryInterface.dropFunction())
.to.be.rejectedWith(/.*requires functionName/),
......@@ -230,47 +232,44 @@ if (dialect.match(/^postgres/)) {
});
describe('indexes', () => {
beforeEach(function() {
return this.queryInterface.dropTable('Group')
.then(() => this.queryInterface.createTable('Group', {
beforeEach(async function() {
await this.queryInterface.dropTable('Group');
await this.queryInterface.createTable('Group', {
username: DataTypes.STRING,
isAdmin: DataTypes.BOOLEAN,
from: DataTypes.STRING
}));
});
});
it('supports newlines', function() {
return this.queryInterface.addIndex('Group', [this.sequelize.literal(`(
it('supports newlines', async function() {
await this.queryInterface.addIndex('Group', [this.sequelize.literal(`(
CASE "username"
WHEN 'foo' THEN 'bar'
ELSE 'baz'
END
)`)], { name: 'group_username_case' })
.then(() => this.queryInterface.showIndex('Group'))
.then(indexes => {
)`)], { name: 'group_username_case' });
const indexes = await this.queryInterface.showIndex('Group');
const indexColumns = _.uniq(indexes.map(index => index.name));
expect(indexColumns).to.include('group_username_case');
});
});
it('adds, reads and removes a named functional index to the table', function() {
return this.queryInterface.addIndex('Group', [this.sequelize.fn('lower', this.sequelize.col('username'))], {
it('adds, reads and removes a named functional index to the table', async function() {
await this.queryInterface.addIndex('Group', [this.sequelize.fn('lower', this.sequelize.col('username'))], {
name: 'group_username_lower'
})
.then(() => this.queryInterface.showIndex('Group'))
.then(indexes => {
const indexColumns = _.uniq(indexes.map(index => index.name));
});
const indexes0 = await this.queryInterface.showIndex('Group');
const indexColumns0 = _.uniq(indexes0.map(index => index.name));
expect(indexColumns).to.include('group_username_lower');
})
.then(() => this.queryInterface.removeIndex('Group', 'group_username_lower'))
.then(() => this.queryInterface.showIndex('Group'))
.then(indexes => {
expect(indexColumns0).to.include('group_username_lower');
await this.queryInterface.removeIndex('Group', 'group_username_lower');
const indexes = await this.queryInterface.showIndex('Group');
const indexColumns = _.uniq(indexes.map(index => index.name));
expect(indexColumns).to.be.empty;
});
});
});
});
}
......@@ -12,7 +12,7 @@ if (dialect.match(/^postgres/)) {
const taskAlias = 'AnActualVeryLongAliasThatShouldBreakthePostgresLimitOfSixtyFourCharacters';
const teamAlias = 'Toto';
const executeTest = (options, test) => {
const executeTest = async (options, test) => {
const sequelize = Support.createSequelizeInstance(options);
const User = sequelize.define('User', { name: DataTypes.STRING, updatedAt: DataTypes.DATE }, { underscored: true });
......@@ -23,12 +23,13 @@ if (dialect.match(/^postgres/)) {
User.belongsToMany(Team, { as: teamAlias, foreignKey: 'teamId', through: 'UserTeam' });
Team.belongsToMany(User, { foreignKey: 'userId', through: 'UserTeam' });
return sequelize.sync({ force: true }).then(() => {
return Team.create({ name: 'rocket' }).then(team => {
return Task.create({ title: 'SuperTask' }).then(task => {
return User.create({ name: 'test', task_id: task.id, updatedAt: new Date() }).then(user => {
return user[`add${teamAlias}`](team).then(() => {
return User.findOne({
await sequelize.sync({ force: true });
const team = await Team.create({ name: 'rocket' });
const task = await Task.create({ title: 'SuperTask' });
const user = await User.create({ name: 'test', task_id: task.id, updatedAt: new Date() });
await user[`add${teamAlias}`](team);
return test(await User.findOne({
include: [
{
model: Task,
......@@ -39,32 +40,26 @@ if (dialect.match(/^postgres/)) {
as: teamAlias
}
]
}).then(test);
});
});
});
});
});
}));
};
it('should throw due to alias being truncated', function() {
it('should throw due to alias being truncated', async function() {
const options = { ...this.sequelize.options, minifyAliases: false };
return executeTest(options, res => {
await executeTest(options, res => {
expect(res[taskAlias]).to.not.exist;
});
});
it('should be able to retrieve include due to alias minifying', function() {
it('should be able to retrieve include due to alias minifying', async function() {
const options = { ...this.sequelize.options, minifyAliases: true };
return executeTest(options, res => {
await executeTest(options, res => {
expect(res[taskAlias].title).to.be.equal('SuperTask');
});
});
it('should throw due to table name being truncated', () => {
it('should throw due to table name being truncated', async () => {
const sequelize = Support.createSequelizeInstance({ minifyAliases: true });
const User = sequelize.define('user_model_name_that_is_long_for_demo_but_also_surpasses_the_character_limit',
......@@ -95,11 +90,12 @@ if (dialect.match(/^postgres/)) {
User.hasMany(Project, { foreignKey: 'userId' });
Project.belongsTo(Company, { foreignKey: 'companyId' });
return sequelize.sync({ force: true }).then(() => {
return Company.create({ name: 'Sequelize' }).then(comp => {
return User.create({ name: 'standard user' }).then(user => {
return Project.create({ name: 'Manhattan', companyId: comp.id, userId: user.id }).then(() => {
return User.findAll({
await sequelize.sync({ force: true });
const comp = await Company.create({ name: 'Sequelize' });
const user = await User.create({ name: 'standard user' });
await Project.create({ name: 'Manhattan', companyId: comp.id, userId: user.id });
await User.findAll({
include: {
model: Project,
include: Company
......@@ -107,8 +103,4 @@ if (dialect.match(/^postgres/)) {
});
});
});
});
});
});
});
}
\ No newline at end of file
......@@ -184,9 +184,10 @@ if (dialect.match(/^postgres/)) {
expect(range.parse('some_non_array')).to.deep.equal('some_non_array');
});
it('should handle native postgres timestamp format', () => {
it('should handle native postgres timestamp format', async () => {
// Make sure nameOidMap is loaded
return Support.sequelize.connectionManager.getConnection().then(connection => {
const connection = await Support.sequelize.connectionManager.getConnection();
Support.sequelize.connectionManager.releaseConnection(connection);
const tsName = DataTypes.postgres.DATE.types.postgres[0],
......@@ -194,7 +195,6 @@ if (dialect.match(/^postgres/)) {
parser = pg.types.getTypeParser(tsOid);
expect(range.parse('(2016-01-01 08:00:00-04,)', parser)[0].value.toISOString()).to.equal('2016-01-01T12:00:00.000Z');
});
});
});
describe('stringify and parse', () => {
......
......@@ -8,7 +8,7 @@ const chai = require('chai'),
if (dialect.match(/^postgres/)) {
describe('[POSTGRES Specific] Regressions', () => {
it('properly fetch OIDs after sync, #8749', function() {
it('properly fetch OIDs after sync, #8749', async function() {
const User = this.sequelize.define('User', {
active: Sequelize.BOOLEAN
});
......@@ -27,24 +27,18 @@ if (dialect.match(/^postgres/)) {
User.hasMany(Media);
Media.belongsTo(User);
return this.sequelize
.sync({ force: true })
.then(() => User.create({ active: true }))
.then(user => {
expect(user.active).to.be.true;
expect(user.get('active')).to.be.true;
await this.sequelize.sync({ force: true });
return User.findOne();
})
.then(user => {
expect(user.active).to.be.true;
expect(user.get('active')).to.be.true;
const user1 = await User.create({ active: true });
expect(user1.active).to.be.true;
expect(user1.get('active')).to.be.true;
return User.findOne({ raw: true });
})
.then(user => {
const user0 = await User.findOne();
expect(user0.active).to.be.true;
expect(user0.get('active')).to.be.true;
const user = await User.findOne({ raw: true });
expect(user.active).to.be.true;
});
});
});
}
......@@ -18,22 +18,21 @@ if (dialect === 'sqlite') {
jetpack.remove(directoryName);
});
it('close connection and remove journal and wal files', function() {
it('close connection and remove journal and wal files', async function() {
const sequelize = Support.createSequelizeInstance({
storage: jetpack.path(fileName)
});
const User = sequelize.define('User', { username: DataTypes.STRING });
return User
.sync({ force: true })
.then(() => sequelize.query('PRAGMA journal_mode = WAL'))
.then(() => User.create({ username: 'user1' }))
.then(() => {
return sequelize.transaction(transaction => {
await User.sync({ force: true });
await sequelize.query('PRAGMA journal_mode = WAL');
await User.create({ username: 'user1' });
await sequelize.transaction(transaction => {
return User.create({ username: 'user2' }, { transaction });
});
})
.then(async () => {
expect(jetpack.exists(fileName)).to.be.equal('file');
expect(jetpack.exists(`${fileName}-shm`), 'shm file should exists').to.be.equal('file');
expect(jetpack.exists(`${fileName}-wal`), 'wal file should exists').to.be.equal('file');
......@@ -47,23 +46,20 @@ if (dialect === 'sqlite') {
expect(jetpack.exists(`${fileName}-shm`), 'shm file should exists').to.be.equal('file');
expect(jetpack.exists(`${fileName}-wal`), 'wal file should exists').to.be.equal('file');
return sequelize.close();
})
.then(() => {
await sequelize.close();
expect(jetpack.exists(fileName)).to.be.equal('file');
expect(jetpack.exists(`${fileName}-shm`), 'shm file exists').to.be.false;
expect(jetpack.exists(`${fileName}-wal`), 'wal file exists').to.be.false;
return this.sequelize.query('PRAGMA journal_mode = DELETE');
});
await this.sequelize.query('PRAGMA journal_mode = DELETE');
});
it('automatic path provision for `options.storage`', () => {
return Support.createSequelizeInstance({ storage: nestedFileName })
it('automatic path provision for `options.storage`', async () => {
await Support.createSequelizeInstance({ storage: nestedFileName })
.define('User', { username: DataTypes.STRING })
.sync({ force: true }).then(() => {
.sync({ force: true });
expect(jetpack.exists(nestedFileName)).to.be.equal('file');
});
});
});
}
......@@ -14,14 +14,14 @@ if (dialect === 'sqlite') {
this.sequelize.options.storage = ':memory:';
});
beforeEach(function() {
beforeEach(async function() {
this.sequelize.options.storage = dbFile;
this.User = this.sequelize.define('User', {
age: DataTypes.INTEGER,
name: DataTypes.STRING,
bio: DataTypes.TEXT
});
return this.User.sync({ force: true });
await this.User.sync({ force: true });
});
storages.forEach(storage => {
......@@ -33,140 +33,131 @@ if (dialect === 'sqlite') {
});
describe('create', () => {
it('creates a table entry', function() {
return this.User.create({ age: 21, name: 'John Wayne', bio: 'noot noot' }).then(user => {
it('creates a table entry', async function() {
const user = await this.User.create({ age: 21, name: 'John Wayne', bio: 'noot noot' });
expect(user.age).to.equal(21);
expect(user.name).to.equal('John Wayne');
expect(user.bio).to.equal('noot noot');
return this.User.findAll().then(users => {
const users = await this.User.findAll();
const usernames = users.map(user => {
return user.name;
});
expect(usernames).to.contain('John Wayne');
});
});
});
it('should allow the creation of an object with options as attribute', function() {
it('should allow the creation of an object with options as attribute', async function() {
const Person = this.sequelize.define('Person', {
name: DataTypes.STRING,
options: DataTypes.TEXT
});
return Person.sync({ force: true }).then(() => {
await Person.sync({ force: true });
const options = JSON.stringify({ foo: 'bar', bar: 'foo' });
return Person.create({
const people = await Person.create({
name: 'John Doe',
options
}).then(people => {
expect(people.options).to.deep.equal(options);
});
});
expect(people.options).to.deep.equal(options);
});
it('should allow the creation of an object with a boolean (true) as attribute', function() {
it('should allow the creation of an object with a boolean (true) as attribute', async function() {
const Person = this.sequelize.define('Person', {
name: DataTypes.STRING,
has_swag: DataTypes.BOOLEAN
});
return Person.sync({ force: true }).then(() => {
return Person.create({
await Person.sync({ force: true });
const people = await Person.create({
name: 'John Doe',
has_swag: true
}).then(people => {
expect(people.has_swag).to.be.ok;
});
});
expect(people.has_swag).to.be.ok;
});
it('should allow the creation of an object with a boolean (false) as attribute', function() {
it('should allow the creation of an object with a boolean (false) as attribute', async function() {
const Person = this.sequelize.define('Person', {
name: DataTypes.STRING,
has_swag: DataTypes.BOOLEAN
});
return Person.sync({ force: true }).then(() => {
return Person.create({
await Person.sync({ force: true });
const people = await Person.create({
name: 'John Doe',
has_swag: false
}).then(people => {
expect(people.has_swag).to.not.be.ok;
});
});
expect(people.has_swag).to.not.be.ok;
});
});
describe('.findOne', () => {
beforeEach(function() {
return this.User.create({ name: 'user', bio: 'footbar' });
beforeEach(async function() {
await this.User.create({ name: 'user', bio: 'footbar' });
});
it('finds normal lookups', function() {
return this.User.findOne({ where: { name: 'user' } }).then(user => {
it('finds normal lookups', async function() {
const user = await this.User.findOne({ where: { name: 'user' } });
expect(user.name).to.equal('user');
});
});
it.skip('should make aliased attributes available', function() {
return this.User.findOne({
it.skip('should make aliased attributes available', async function() { // eslint-disable-line mocha/no-skipped-tests
const user = await this.User.findOne({
where: { name: 'user' },
attributes: ['id', ['name', 'username']]
}).then(user => {
expect(user.username).to.equal('user');
});
expect(user.username).to.equal('user');
});
});
describe('.all', () => {
beforeEach(function() {
return this.User.bulkCreate([
beforeEach(async function() {
await this.User.bulkCreate([
{ name: 'user', bio: 'foobar' },
{ name: 'user', bio: 'foobar' }
]);
});
it('should return all users', function() {
return this.User.findAll().then(users => {
it('should return all users', async function() {
const users = await this.User.findAll();
expect(users).to.have.length(2);
});
});
});
describe('.min', () => {
it('should return the min value', function() {
it('should return the min value', async function() {
const users = [];
for (let i = 2; i < 5; i++) {
users[users.length] = { age: i };
}
return this.User.bulkCreate(users).then(() => {
return this.User.min('age').then(min => {
await this.User.bulkCreate(users);
const min = await this.User.min('age');
expect(min).to.equal(2);
});
});
});
});
describe('.max', () => {
it('should return the max value', function() {
it('should return the max value', async function() {
const users = [];
for (let i = 2; i <= 5; i++) {
users[users.length] = { age: i };
}
return this.User.bulkCreate(users).then(() => {
return this.User.max('age').then(min => {
await this.User.bulkCreate(users);
const min = await this.User.max('age');
expect(min).to.equal(5);
});
});
});
});
});
});
});
}
......@@ -10,7 +10,7 @@ const chai = require('chai'),
if (dialect === 'sqlite') {
describe('[SQLITE Specific] DAO', () => {
beforeEach(function() {
beforeEach(async function() {
this.User = this.sequelize.define('User', {
username: DataTypes.STRING,
emergency_contact: DataTypes.JSON,
......@@ -28,90 +28,90 @@ if (dialect === 'sqlite') {
});
this.User.hasMany(this.Project);
return this.sequelize.sync({ force: true });
await this.sequelize.sync({ force: true });
});
describe('findAll', () => {
it('handles dates correctly', function() {
it('handles dates correctly', async function() {
const user = this.User.build({ username: 'user' });
user.dataValues.createdAt = new Date(2011, 4, 4);
return user.save().then(() => {
return this.User.create({ username: 'new user' }).then(() => {
return this.User.findAll({
await user.save();
await this.User.create({ username: 'new user' });
const users = await this.User.findAll({
where: { createdAt: { [Op.gt]: new Date(2012, 1, 1) } }
}).then(users => {
expect(users).to.have.length(1);
});
});
});
expect(users).to.have.length(1);
});
it('handles dates with aliasses correctly #3611', function() {
return this.User.create({
it('handles dates with aliasses correctly #3611', async function() {
await this.User.create({
dateField: new Date(2010, 10, 10)
}).then(() => {
return this.User.findAll().then(obj => obj[0]);
}).then(user => {
});
const obj = await this.User.findAll();
const user = await obj[0];
expect(user.get('dateField')).to.be.an.instanceof(Date);
expect(user.get('dateField')).to.equalTime(new Date(2010, 10, 10));
});
});
it('handles dates in includes correctly #2644', function() {
return this.User.create({
it('handles dates in includes correctly #2644', async function() {
await this.User.create({
projects: [
{ dateField: new Date(1990, 5, 5) }
]
}, { include: [this.Project] }).then(() => {
return this.User.findAll({
}, { include: [this.Project] });
const obj = await this.User.findAll({
include: [this.Project]
}).then(obj => obj[0]);
}).then(user => {
});
const user = await obj[0];
expect(user.projects[0].get('dateField')).to.be.an.instanceof(Date);
expect(user.projects[0].get('dateField')).to.equalTime(new Date(1990, 5, 5));
});
});
});
describe('json', () => {
it('should be able to retrieve a row with json_extract function', function() {
return Promise.all([
it('should be able to retrieve a row with json_extract function', async function() {
await Promise.all([
this.User.create({ username: 'swen', emergency_contact: { name: 'kate' } }),
this.User.create({ username: 'anna', emergency_contact: { name: 'joe' } })
]).then(() => {
return this.User.findOne({
]);
const user = await this.User.findOne({
where: Sequelize.json('json_extract(emergency_contact, \'$.name\')', 'kate'),
attributes: ['username', 'emergency_contact']
});
}).then(user => {
expect(user.emergency_contact.name).to.equal('kate');
});
});
it('should be able to retrieve a row by json_type function', function() {
return Promise.all([
it('should be able to retrieve a row by json_type function', async function() {
await Promise.all([
this.User.create({ username: 'swen', emergency_contact: { name: 'kate' } }),
this.User.create({ username: 'anna', emergency_contact: ['kate', 'joe'] })
]).then(() => {
return this.User.findOne({
]);
const user = await this.User.findOne({
where: Sequelize.json('json_type(emergency_contact)', 'array'),
attributes: ['username', 'emergency_contact']
});
}).then(user => {
expect(user.username).to.equal('anna');
});
});
});
describe('regression tests', () => {
it('do not crash while parsing unique constraint errors', function() {
it('do not crash while parsing unique constraint errors', async function() {
const Payments = this.sequelize.define('payments', {});
return Payments.sync({ force: true }).then(() => {
return expect(Payments.bulkCreate([{ id: 1 }, { id: 1 }], { ignoreDuplicates: false })).to.eventually.be.rejected;
});
await Payments.sync({ force: true });
await expect(Payments.bulkCreate([{ id: 1 }, { id: 1 }], { ignoreDuplicates: false })).to.eventually.be.rejected;
});
});
});
......
......@@ -8,7 +8,7 @@ const chai = require('chai'),
if (dialect === 'sqlite') {
describe('[SQLITE Specific] sqlite_master raw queries', () => {
beforeEach(function() {
beforeEach(async function() {
this.sequelize.define('SomeTable', {
someColumn: DataTypes.INTEGER
}, {
......@@ -16,12 +16,11 @@ if (dialect === 'sqlite') {
timestamps: false
});
return this.sequelize.sync({ force: true });
await this.sequelize.sync({ force: true });
});
it('should be able to select with tbl_name filter', function() {
return this.sequelize.query('SELECT * FROM sqlite_master WHERE tbl_name=\'SomeTable\'')
.then(result => {
it('should be able to select with tbl_name filter', async function() {
const result = await this.sequelize.query('SELECT * FROM sqlite_master WHERE tbl_name=\'SomeTable\'');
const rows = result[0];
expect(rows).to.have.length(1);
const row = rows[0];
......@@ -30,11 +29,9 @@ if (dialect === 'sqlite') {
expect(row).to.have.property('tbl_name', 'SomeTable');
expect(row).to.have.property('sql');
});
});
it('should be able to select *', function() {
return this.sequelize.query('SELECT * FROM sqlite_master')
.then(result => {
it('should be able to select *', async function() {
const result = await this.sequelize.query('SELECT * FROM sqlite_master');
const rows = result[0];
expect(rows).to.have.length(2);
rows.forEach(row => {
......@@ -45,11 +42,9 @@ if (dialect === 'sqlite') {
expect(row).to.have.property('sql');
});
});
});
it('should be able to select just "sql" column and get rows back', function() {
return this.sequelize.query('SELECT sql FROM sqlite_master WHERE tbl_name=\'SomeTable\'')
.then(result => {
it('should be able to select just "sql" column and get rows back', async function() {
const result = await this.sequelize.query('SELECT sql FROM sqlite_master WHERE tbl_name=\'SomeTable\'');
const rows = result[0];
expect(rows).to.have.length(1);
const row = rows[0];
......@@ -57,5 +52,4 @@ if (dialect === 'sqlite') {
'CREATE TABLE `SomeTable` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `someColumn` INTEGER)');
});
});
});
}
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!