text: 'use strict';
  
  const expect = require('chai').expect;
  const mock = require('../tools/mock');
  
  describe('bypass document validation', function () {
    const test = {};
    beforeEach(() => {
      return mock.createServer().then(server => {
        test.server = server;
      });
    });
    afterEach(() => mock.cleanup());
  
    // general test for aggregate function
    function testAggregate(testConfiguration, config, done) {
      const client = testConfiguration.newClient(`mongodb://${test.server.uri()}/test`);
      let close = e => {
        close = () => {};
        client.close(() => done(e));
      };
  
      test.server.setMessageHandler(request => {
        const doc = request.document;
        if (doc.aggregate) {
          try {
            expect(doc.bypassDocumentValidation).equal(config.expected);
            request.reply({
              ok: 1,
              cursor: {
                firstBatch: [{}],
                id: 23,
                ns: 'test.test'
              }
            });
          } catch (e) {
            close(e);
          }
        }
  
        if (doc.ismaster) {
          request.reply(Object.assign({}, mock.DEFAULT_ISMASTER));
        } else if (doc.endSessions) {
          request.reply({ ok: 1 });
        }
      });
  
      client.connect(function (err, client) {
        expect(err).to.not.exist;
        const db = client.db('test');
        const collection = db.collection('test_c');
  
        const options = { bypassDocumentValidation: config.actual };
  
        const pipeline = [
          {
            $project: {}
          }
        ];
        collection.aggregate(pipeline, options).next(() => close());
      });
    }
    // aggregate
    it('should only set bypass document validation if strictly true in aggregate', function (done) {
      testAggregate(this.configuration, { expected: true, actual: true }, done);
    });
  
    it('should not set bypass document validation if not strictly true in aggregate', function (done) {
      testAggregate(this.configuration, { expected: undefined, actual: false }, done);
    });
  
    // general test for mapReduce function
    function testMapReduce(testConfiguration, config, done) {
      const client = testConfiguration.newClient(`mongodb://${test.server.uri()}/test`);
      let close = e => {
        close = () => {};
        client.close(() => done(e));
      };
  
      test.server.setMessageHandler(request => {
        const doc = request.document;
        if (doc.mapReduce) {
          try {
            expect(doc.bypassDocumentValidation).equal(config.expected);
            request.reply({
              results: 't',
              ok: 1
            });
          } catch (e) {
            close(e);
          }
        }
  
        if (doc.ismaster) {
          request.reply(Object.assign({}, mock.DEFAULT_ISMASTER));
        } else if (doc.endSessions) {
          request.reply({ ok: 1 });
        }
      });
  
      client.connect(function (err, client) {
        expect(err).to.not.exist;
        const db = client.db('test');
        const collection = db.collection('test_c');
  
        const options = {
          out: 'test_c',
          bypassDocumentValidation: config.actual
        };
  
        collection.mapReduce(
          function map() {},
          function reduce() {},
          options,
          e => {
            close(e);
          }
        );
      });
    }
    // map reduce
    it('should only set bypass document validation if strictly true in mapReduce', function (done) {
      testMapReduce(this.configuration, { expected: true, actual: true }, done);
    });
  
    it('should not set bypass document validation if not strictly true in mapReduce', function (done) {
      testMapReduce(this.configuration, { expected: undefined, actual: false }, done);
    });
  
    // general test for findAndModify function
    function testFindAndModify(testConfiguration, config, done) {
      const client = testConfiguration.newClient(`mongodb://${test.server.uri()}/test`);
      let close = e => {
        close = () => {};
        client.close(() => done(e));
      };
  
      test.server.setMessageHandler(request => {
        const doc = request.document;
        if (doc.findAndModify) {
          try {
            expect(doc.bypassDocumentValidation).equal(config.expected);
            request.reply({
              ok: 1
            });
          } catch (e) {
            close(e);
          }
        }
  
        if (doc.ismaster) {
          request.reply(Object.assign({}, mock.DEFAULT_ISMASTER));
        } else if (doc.endSessions) {
          request.reply({ ok: 1 });
        }
      });
  
      client.connect(function (err, client) {
        expect(err).to.not.exist;
        const db = client.db('test');
        const collection = db.collection('test_c');
  
        const options = { bypassDocumentValidation: config.actual };
  
        collection.findAndModify(
          { name: 'Andy' },
          { rating: 1 },
          { $inc: { score: 1 } },
          options,
          e => {
            close(e);
          }
        );
      });
    }
    // find and modify
    it('should only set bypass document validation if strictly true in findAndModify', function (done) {
      testFindAndModify(this.configuration, { expected: true, actual: true }, done);
    });
  
    it('should not set bypass document validation if not strictly true in findAndModify', function (done) {
      testFindAndModify(this.configuration, { expected: undefined, actual: false }, done);
    });
  
    // general test for BlukWrite to test changes made in ordered.js and unordered.js
    function testBulkWrite(testConfiguration, config, done) {
      const client = testConfiguration.newClient(`mongodb://${test.server.uri()}/test`);
      let close = e => {
        close = () => {};
        client.close(() => done(e));
      };
  
      test.server.setMessageHandler(request => {
        const doc = request.document;
        if (doc.insert) {
          try {
            expect(doc.bypassDocumentValidation).equal(config.expected);
            request.reply({
              ok: 1
            });
          } catch (e) {
            close(e);
          }
        }
  
        if (doc.ismaster) {
          request.reply(Object.assign({}, mock.DEFAULT_ISMASTER));
        } else if (doc.endSessions) {
          request.reply({ ok: 1 });
        }
      });
  
      client.connect(function (err, client) {
        expect(err).to.not.exist;
        const db = client.db('test');
        const collection = db.collection('test_c');
  
        const options = {
          bypassDocumentValidation: config.actual,
          ordered: config.ordered
        };
  
        collection.bulkWrite([{ insertOne: { document: { a: 1 } } }], options, () => close());
      });
    }
    // ordered bulk write, testing change in ordered.js
    it('should only set bypass document validation if strictly true in ordered bulkWrite', function (done) {
      testBulkWrite(this.configuration, { expected: true, actual: true, ordered: true }, done);
    });
  
    it('should not set bypass document validation if not strictly true in ordered bulkWrite', function (done) {
      testBulkWrite(this.configuration, { expected: undefined, actual: false, ordered: true }, done);
    });
  
    // unordered bulk write, testing change in ordered.js
    it('should only set bypass document validation if strictly true in unordered bulkWrite', function (done) {
      testBulkWrite(this.configuration, { expected: true, actual: true, ordered: false }, done);
    });
  
    it('should not set bypass document validation if not strictly true in unordered bulkWrite', function (done) {
      testBulkWrite(this.configuration, { expected: undefined, actual: false, ordered: false }, done);
    });
  });
  