text: 'use strict';
  
  const Support = require('../support');
  const current = Support.sequelize;
  const expectsql = Support.expectsql;
  const sql = current.dialect.QueryGenerator;
  const Op = Support.Sequelize.Op;
  const expect = require('chai').expect;
  const sinon = require('sinon');
  
  if (current.dialect.supports.constraints.addConstraint) {
    describe(Support.getTestDialectTeaser('SQL'), () => {
      describe('addConstraint', () => {
        describe('unique', () => {
          it('naming', () => {
            expectsql(sql.addConstraintQuery('myTable', {
              name: 'unique_mytable_mycolumn',
              type: 'UNIQUE',
              fields: ['myColumn']
            }), {
              default: 'ALTER TABLE [myTable] ADD CONSTRAINT [unique_mytable_mycolumn] UNIQUE ([myColumn]);'
            });
          });
  
          it('should create constraint name if not passed', () => {
            expectsql(sql.addConstraintQuery('myTable', {
              type: 'UNIQUE',
              fields: ['myColumn']
            }), {
              default: 'ALTER TABLE [myTable] ADD CONSTRAINT [myTable_myColumn_uk] UNIQUE ([myColumn]);'
            });
          });
  
          it('should work with multiple columns', () => {
            expectsql(sql.addConstraintQuery('myTable', {
              type: 'UNIQUE',
              fields: ['myColumn1', 'myColumn2']
            }), {
              default: 'ALTER TABLE [myTable] ADD CONSTRAINT [myTable_myColumn1_myColumn2_uk] UNIQUE ([myColumn1], [myColumn2]);'
            });
          });
        });
  
        describe('check', () => {
          it('naming', () => {
            expectsql(sql.addConstraintQuery('myTable', {
              type: 'CHECK',
              fields: ['myColumn'],
              where: {
                myColumn: ['value1', 'value2', 'value3']
              }
            }), {
              mssql: "ALTER TABLE [myTable] ADD CONSTRAINT [myTable_myColumn_ck] CHECK ([myColumn] IN (N'value1', N'value2', N'value3'));",
              default: "ALTER TABLE [myTable] ADD CONSTRAINT [myTable_myColumn_ck] CHECK ([myColumn] IN ('value1', 'value2', 'value3'));"
            });
          });
  
          it('where', () => {
            expectsql(sql.addConstraintQuery('myTable', {
              type: 'CHECK',
              fields: ['myColumn'],
              name: 'check_mycolumn_where',
              where: {
                myColumn: {
                  [Op.and]: {
                    [Op.gt]: 50,
                    [Op.lt]: 100
                  }
                }
              }
            }), {
              default: 'ALTER TABLE [myTable] ADD CONSTRAINT [check_mycolumn_where] CHECK (([myColumn] > 50 AND [myColumn] < 100));'
            });
          });
  
        });
  
        if (current.dialect.supports.constraints.default) {
          describe('default', () => {
            it('naming', () => {
              expectsql(sql.addConstraintQuery('myTable', {
                type: 'default',
                fields: ['myColumn'],
                defaultValue: 0
              }), {
                mssql: 'ALTER TABLE [myTable] ADD CONSTRAINT [myTable_myColumn_df] DEFAULT (0) FOR [myColumn];'
              });
            });
  
            it('string', () => {
              expectsql(sql.addConstraintQuery('myTable', {
                type: 'default',
                fields: ['myColumn'],
                defaultValue: 'some default value',
                name: 'default_mytable_null'
              }), {
                mssql: "ALTER TABLE [myTable] ADD CONSTRAINT [default_mytable_null] DEFAULT (N'some default value') FOR [myColumn];"
              });
            });
  
            it('validation', () => {
              expect(sql.addConstraintQuery.bind(sql, {
                tableName: 'myTable',
                schema: 'mySchema'
              }, {
                type: 'default',
                fields: [{
                  attribute: 'myColumn'
                }]
              })).to.throw('Default value must be specifed for DEFAULT CONSTRAINT');
            });
  
          });
        }
        describe('primary key', () => {
          it('naming', () => {
            expectsql(sql.addConstraintQuery('myTable', {
              name: 'primary_mytable_mycolumn',
              type: 'primary key',
              fields: ['myColumn']
            }), {
              default: 'ALTER TABLE [myTable] ADD CONSTRAINT [primary_mytable_mycolumn] PRIMARY KEY ([myColumn]);'
            });
          });
  
          it('should create constraint name if not passed', () => {
            expectsql(sql.addConstraintQuery('myTable', {
              type: 'PRIMARY KEY',
              fields: ['myColumn']
            }), {
              default: 'ALTER TABLE [myTable] ADD CONSTRAINT [myTable_myColumn_pk] PRIMARY KEY ([myColumn]);'
            });
          });
  
          it('should work with multiple columns', () => {
            expectsql(sql.addConstraintQuery('myTable', {
              type: 'PRIMARY KEY',
              fields: ['myColumn1', 'myColumn2']
            }), {
              default: 'ALTER TABLE [myTable] ADD CONSTRAINT [myTable_myColumn1_myColumn2_pk] PRIMARY KEY ([myColumn1], [myColumn2]);'
            });
          });
        });
  
        describe('foreign key', () => {
          it('naming', () => {
            expectsql(sql.addConstraintQuery('myTable', {
              name: 'foreignkey_mytable_mycolumn',
              type: 'foreign key',
              fields: ['myColumn'],
              references: {
                table: 'myOtherTable',
                field: 'id'
              }
            }), {
              default: 'ALTER TABLE [myTable] ADD CONSTRAINT [foreignkey_mytable_mycolumn] FOREIGN KEY ([myColumn]) REFERENCES [myOtherTable] ([id]);'
            });
          });
  
          it('uses onDelete, onUpdate', () => {
            expectsql(sql.addConstraintQuery('myTable', {
              type: 'foreign key',
              fields: ['myColumn'],
              references: {
                table: 'myOtherTable',
                field: 'id'
              },
              onUpdate: 'cascade',
              onDelete: 'cascade'
            }), {
              default: 'ALTER TABLE [myTable] ADD CONSTRAINT [myTable_myColumn_myOtherTable_fk] FOREIGN KEY ([myColumn]) REFERENCES [myOtherTable] ([id]) ON UPDATE CASCADE ON DELETE CASCADE;'
            });
          });
  
          it('errors if references object is not passed', () => {
            expect(sql.addConstraintQuery.bind(sql, 'myTable', {
              type: 'foreign key',
              fields: ['myColumn']
            })).to.throw('references object with table and field must be specified');
          });
  
  
        });
  
        describe('validation', () => {
          it('throw error on invalid type', () => {
            expect(sql.addConstraintQuery.bind(sql, 'myTable', { type: 'some type', fields: [] })).to.throw('some type is invalid');
          });
  
          it('calls getConstraintSnippet function', () => {
            const options = { type: 'unique', fields: ['myColumn'] };
            const addConstraintQuerySpy = sinon.stub(sql, 'addConstraintQuery');
            sql.addConstraintQuery('myTable', options);
            expect(sql.addConstraintQuery).to.have.been.calledWith('myTable', options);
            addConstraintQuerySpy.restore();
          });
  
          if (!current.dialect.supports.constraints.default) {
            it('should throw error if default constraints are used in other dialects', () => {
              expect(sql.addConstraintQuery.bind(sql, 'myTable', { type: 'default', defaultValue: 0, fields: [] })).to.throw('Default constraints are supported only for MSSQL dialect.');
            });
          }
        });
      });
    });
  }
  