<commit_before>'use strict';

module.exports = {
  setUp: function(callback) {
    var config = require('../config');

    // block console.log for cushion output
    this._console = console.log;
    console.log = function(){};

    this.cli = require('../../lib/cliRunner');
    this.cli.level = 'connection';
    this.cli.name = config.host;

    this.cli._setCushion(
      config.name,
      config.password,
      config.host,
      config.port
    );

    this.cPrompt = require('../../lib/prompt/prompt');
    this.cFile = require('../../lib/file/file');

    callback();
  },

  tearDown: function(callback) {
    console.log = this._console;

    callback();
  },

  config: {
    oneArgument: function(test) {
      var cli = this.cli,
          input = ['config'];

      this.cli.cushion.config = function() {
        test.strictEqual(arguments.length, 1);
        test.strictEqual(typeof arguments[0], 'function');
        test.done();
      };

      cli.connectionCommands._config(input, cli);
    },
    twoArguments: function(test) {
      var cli = this.cli,
          input = ['config', 'section'];

      this.cli.cushion.config = function() {
        test.strictEqual(arguments.length, 2);
        test.strictEqual(arguments[0], 'section');
        test.strictEqual(typeof arguments[1], 'function');
        test.done();
      };

      cli.connectionCommands._config(input, cli);
    },
    threeArguments: function(test) {
      var cli = this.cli,
          input = ['config', 'section', 'option'];

      this.cli.cushion.config = function() {
        test.strictEqual(arguments.length, 3);
        test.strictEqual(arguments[0], 'section');
        test.strictEqual(arguments[1], 'option');
        test.strictEqual(typeof arguments[2], 'function');
        test.done();
      };

      cli.connectionCommands._config(input, cli);
    },
    fourArguments: function(test) {
      var cli = this.cli,
          input = ['config', 'section', 'option', 'value'];

      this.cli.cushion.config = function() {
        test.strictEqual(arguments.length, 4);
        test.strictEqual(arguments[0], 'section');
        test.strictEqual(arguments[1], 'option');
        test.strictEqual(arguments[2], 'value');
        test.strictEqual(typeof arguments[3], 'function');
        test.done();
      };

      cli.connectionCommands._config(input, cli);
    },
    fiveArguments: function(test) {
      var cli = this.cli,
          input = ['config', 'section', 'option', 'value', 'invalidInput'];

      console.log = function() {
        test.strictEqual(arguments.length, 1);
        test.done();
      };

      cli.connectionCommands._config(input, cli);
    }
  },

  createAdmin: {
    oneArgument: function(test) {
      var cli = this.cli,
          input = ['createAdmin'];

      this.cPrompt._promptGetAdmin = function() {
        test.strictEqual(arguments.length, 2);
        test.done();
      };

      cli.connectionCommands._createAdmin(input, cli);
    },
    twoArguments: function(test) {
      var cli = this.cli,
          input = ['createAdmin', 'admin'];

      console.log = function() {
        test.strictEqual(arguments.length, 1);
        test.done();
      };

      cli.connectionCommands._createAdmin(input, cli);
    },
    threeArguments: function(test) {
      var cli = this.cli,
          input = ['createAdmin', 'admin', 'password'];

      this.cli.cushion.createAdmin = function() {
        test.strictEqual(arguments.length, 3);
        test.strictEqual(arguments[0], 'admin');
        test.strictEqual(arguments[1], 'password');
        test.strictEqual(typeof arguments[2], 'function');
        test.done();
      };

      cli.connectionCommands._createAdmin(input, cli);
    },
    fourArguments: function(test) {
      var cli = this.cli,
          input = ['createAdmin', 'admin', 'password', 'invalidInput'];

      console.log = function() {
        test.strictEqual(arguments.length, 1);
        test.done();
      };

      cli.connectionCommands._createAdmin(input, cli);
    }
  },

  deleteAdmin: {
    oneArgument: function(test) {
      var cli = this.cli,
          input = ['deleteAdmin'];

      this.cPrompt._promptDeleteAdmin = function(inputCli) {
        test.strictEqual(arguments.length, 1);
        test.strictEqual(inputCli, cli);
        test.done();
      };

      cli.connectionCommands._deleteAdmin(input, cli);
    },
    twoArguments: function(test) {
      var cli = this.cli,
          input = ['deleteAdmin', 'foo'];

      this.cli.cushion.deleteAdmin = function(name, callback) {
        test.strictEqual(arguments.length, 2);
        test.strictEqual(name, 'foo');
        test.strictEqual(callback, cli.connectionCallbacks.deleteAdmin);
        test.done();
      };

      cli.connectionCommands._deleteAdmin(input, cli);
    },
    threeArguments: function(test) {
      var cli = this.cli,
          input = ['deleteAdmin', 'foo', 'redundantInput'];

      console.log = function() {
        test.strictEqual(arguments.length, 1);
        test.done();
      };

      cli.connectionCommands._deleteAdmin(input, cli);
    }
  },

  deleteConnection: {
    oneArgument: function(test) {
      var cli = this.cli,
          input = ['deleteConnection'],
          cPrompt = this.cPrompt;

      cPrompt._showConnections = function(callback) {
        test.strictEqual(arguments.length, 1);
        test.strictEqual(typeof callback, 'function');
        test.strictEqual(callback instanceof Function, true);
        test.strictEqual(callback, cPrompt._setupDeleteSavedConnection);
        test.done();
      };

      cli.connectionCommands._deleteConnection(input, cli);
    },
    twoArguments: {
      inputIsName: {
        nameExists: function(test) {
          var cli = this.cli,
              input = ['deleteConnection', 'connection'];

          cli.connections = {};
          cli.connections.connection = 'foo';

          this.cFile._writeConnections = function(connections, callback) {
            test.strictEqual(typeof connections, 'object');
            test.strictEqual(connections instanceof Object, true);
            test.strictEqual(Object.keys(connections).length, 0);

            test.strictEqual(typeof callback, 'function');
            test.strictEqual(callback instanceof Function, true);

            test.done();
          };

          cli.connectionCommands._deleteConnection(input, cli);
        },
        nameDoesntExist: function(test) {
          var cli = this.cli,
              input = ['deleteConnection', 'noConnection'];

          cli.connections = {};
          cli.connections.connection = 'foo';

          console.log = function(message) {
            test.strictEqual(Object.keys(cli.connections).length, 1);

            test.strictEqual(arguments.length, 1);
            test.strictEqual(typeof message, 'string');
          };

          cli.prompt = function() {
            test.strictEqual(arguments.length, 0);

            test.done();
          };

          cli.connectionCommands._deleteConnection(input, cli);
        }
      },
      inputIsIndex: {
        indexExists: function(test) {
          var cli = this.cli,
              input = ['deleteConnection', '1'];

          cli.connections = {};
          cli.connections.connection = 'foo';

          this.cFile._writeConnections = function(connections, callback) {
            test.strictEqual(typeof connections, 'object');
            test.strictEqual(connections instanceof Object, true);
            test.strictEqual(Object.keys(connections).length, 0);

            test.strictEqual(typeof callback, 'function');
            test.strictEqual(callback instanceof Function, true);

            test.done();
          };

          cli.connectionCommands._deleteConnection(input, cli);
        },
        indexDoesntExist: function(test) {
          var cli = this.cli,
              input = ['deleteConnection', '2'];

          cli.connections = {};
          cli.connections.connection = 'foo';

          console.log = function(message) {
            test.strictEqual(Object.keys(cli.connections).length, 1);

            test.strictEqual(arguments.length, 1);
            test.strictEqual(typeof message, 'string');
          };

          cli.prompt = function() {
            test.strictEqual(arguments.length, 0);

            test.done();
          };

          cli.connectionCommands._deleteConnection(input, cli);
        }
      }
    }
  },

  listAdmins: function(test) {
    var cli = this.cli,
        input = ['listAdmins'];

    cli.cushion.config = function(section, callback) {
      test.strictEqual(typeof section, 'string');
      test.strictEqual(section, 'admins');

      test.strictEqual(typeof callback, 'function');
      test.strictEqual(callback instanceof Function, true);
      test.strictEqual(callback, cli.connectionCallbacks.listAdmins);

      test.done();
    };

    cli.connectionCommands._listAdmins(input, cli);
  },

  log: {
    oneArguments: function(test) {
      var cli = this.cli,
          input = ['log'];

      cli.cushion.log = function(callback) {
        test.strictEqual(arguments.length, 1);
        test.strictEqual(callback, cli.connectionCallbacks.log);
        test.done();
      };

      cli.connectionCommands._log(input, cli);
    },
    twoArguments: function(test) {
      var cli = this.cli,
          input = ['log', 8];

      cli.cushion.log = function(bytes, callback) {
        test.strictEqual(arguments.length, 2);
        test.strictEqual(bytes, 8);
        test.strictEqual(callback, cli.connectionCallbacks.log);
        test.done();
      };

      cli.connectionCommands._log(input, cli);
    },
    threeArguments: function(test) {
      var cli = this.cli,
          input = ['log', 12, 'redundantInput'];

      console.log = function() {
        test.strictEqual(arguments.length, 1);
        test.done();
      };

      cli.connectionCommands._log(input, cli);
    }
  },

  saveConnection: {
    oneArgument: function(test) {
      var cli = this.cli,
          input = ['saveConnection'];

      console.log = function() {
        test.strictEqual(arguments.length, 1);
      };

      cli.prompt = function() {
        test.done();
      };

      cli.connectionCommands._saveConnection(input, cli);
    },
    twoArguments: function(test) {
      var cli = this.cli,
          input = ['saveConnection', 'redundantInput'];

      this.cFile._writeConnections = function(connections, callback) {
        test.strictEqual(arguments.length, 2);
        test.strictEqual(typeof connections, 'object');
        test.strictEqual(connections instanceof Object, true);
        test.strictEqual(typeof callback, 'function' );
        test.strictEqual(callback instanceof Function, true);
        test.done();
      };

      cli.connectionCommands._saveConnection(input, cli);
    }
  },

  showConnection: function(test) {
    var cli = this.cli,
        input = ['showConnection'];

    cli.prompt = function() {
      test.done();
    };

    cli.connectionCommands._showConnection(input, cli);
  },

  simpleCommand: function(test) {
    var cli = this.cli,
        input = ['activeTasks'],
        activeTasks = cli.cushion.activeTasks;

    cli.cushion.activeTasks = function() {
      test.strictEqual(arguments.length, 1);
      test.strictEqual(typeof arguments[0], 'function');
      test.strictEqual(arguments[0], cli.connectionCallbacks.activeTasks);

      test.done();
    };

    cli.connectionCommands._simpleCommand(input, cli);

    cli.cushion.activeTasks = activeTasks;
  },

  uuids: {
    oneArgument: function(test) {
      var cli = this.cli,
          input = ['uuids'];

      cli.cushion.uuids = function(callback) {
        test.strictEqual(arguments.length, 1);
        test.strictEqual(callback, cli.connectionCallbacks.uuids);
        test.done();
      };

      cli.connectionCommands._uuids(input, cli);
    },
    twoArguments: function(test) {
      var cli = this.cli,
          input = ['uuids', 2];
      cli.cushion.uuids = function(nrOfUuids, callback) {
        test.strictEqual(arguments.length, 2);
        test.strictEqual(nrOfUuids, 2);
        test.strictEqual(callback, cli.connectionCallbacks.uuids);
        test.done();
      };

      cli.connectionCommands._uuids(input, cli);
    },
    threeArguments: function(test) {
      var cli = this.cli,
          input = ['uuids', 2, 'redundantInput'];

      console.log = function() {
        test.strictEqual(arguments.length, 1);
        test.done();
      };

      cli.connectionCommands._uuids(input, cli);
    }
  }
};
<commit_msg>stubbing wants to be learned - when you stub something asign it back afterwards<commit_after>'use strict';

module.exports = {
  setUp: function(callback) {
    var config = require('../config');

    // block console.log for cushion output
    this._console = console.log;
    console.log = function(){};

    this.cli = require('../../lib/cliRunner');
    this.cli.level = 'connection';
    this.cli.name = config.host;

    this.cli._setCushion(
      config.name,
      config.password,
      config.host,
      config.port
    );

    this.cPrompt = require('../../lib/prompt/prompt');
    this.cFile = require('../../lib/file/file');

    callback();
  },

  tearDown: function(callback) {
    console.log = this._console;

    callback();
  },

  config: {
    oneArgument: function(test) {
      var cli = this.cli,
          input = ['config'];

      this.cli.cushion.config = function() {
        test.strictEqual(arguments.length, 1);
        test.strictEqual(typeof arguments[0], 'function');
        test.done();
      };

      cli.connectionCommands._config(input, cli);
    },
    twoArguments: function(test) {
      var cli = this.cli,
          input = ['config', 'section'];

      this.cli.cushion.config = function() {
        test.strictEqual(arguments.length, 2);
        test.strictEqual(arguments[0], 'section');
        test.strictEqual(typeof arguments[1], 'function');
        test.done();
      };

      cli.connectionCommands._config(input, cli);
    },
    threeArguments: function(test) {
      var cli = this.cli,
          input = ['config', 'section', 'option'];

      this.cli.cushion.config = function() {
        test.strictEqual(arguments.length, 3);
        test.strictEqual(arguments[0], 'section');
        test.strictEqual(arguments[1], 'option');
        test.strictEqual(typeof arguments[2], 'function');
        test.done();
      };

      cli.connectionCommands._config(input, cli);
    },
    fourArguments: function(test) {
      var cli = this.cli,
          input = ['config', 'section', 'option', 'value'];

      this.cli.cushion.config = function() {
        test.strictEqual(arguments.length, 4);
        test.strictEqual(arguments[0], 'section');
        test.strictEqual(arguments[1], 'option');
        test.strictEqual(arguments[2], 'value');
        test.strictEqual(typeof arguments[3], 'function');
        test.done();
      };

      cli.connectionCommands._config(input, cli);
    },
    fiveArguments: function(test) {
      var cli = this.cli,
          input = ['config', 'section', 'option', 'value', 'invalidInput'];

      console.log = function() {
        test.strictEqual(arguments.length, 1);
        test.done();
      };

      cli.connectionCommands._config(input, cli);
    }
  },

  createAdmin: {
    oneArgument: function(test) {
      var cli = this.cli,
          input = ['createAdmin'];

      this.cPrompt._promptGetAdmin = function() {
        test.strictEqual(arguments.length, 2);
        test.done();
      };

      cli.connectionCommands._createAdmin(input, cli);
    },
    twoArguments: function(test) {
      var cli = this.cli,
          input = ['createAdmin', 'admin'];

      console.log = function() {
        test.strictEqual(arguments.length, 1);
        test.done();
      };

      cli.connectionCommands._createAdmin(input, cli);
    },
    threeArguments: function(test) {
      var cli = this.cli,
          input = ['createAdmin', 'admin', 'password'];

      this.cli.cushion.createAdmin = function() {
        test.strictEqual(arguments.length, 3);
        test.strictEqual(arguments[0], 'admin');
        test.strictEqual(arguments[1], 'password');
        test.strictEqual(typeof arguments[2], 'function');
        test.done();
      };

      cli.connectionCommands._createAdmin(input, cli);
    },
    fourArguments: function(test) {
      var cli = this.cli,
          input = ['createAdmin', 'admin', 'password', 'invalidInput'];

      console.log = function() {
        test.strictEqual(arguments.length, 1);
        test.done();
      };

      cli.connectionCommands._createAdmin(input, cli);
    }
  },

  deleteAdmin: {
    oneArgument: function(test) {
      var cli = this.cli,
          input = ['deleteAdmin'];

      this.cPrompt._promptDeleteAdmin = function(inputCli) {
        test.strictEqual(arguments.length, 1);
        test.strictEqual(inputCli, cli);
        test.done();
      };

      cli.connectionCommands._deleteAdmin(input, cli);
    },
    twoArguments: function(test) {
      var cli = this.cli,
          input = ['deleteAdmin', 'foo'];

      this.cli.cushion.deleteAdmin = function(name, callback) {
        test.strictEqual(arguments.length, 2);
        test.strictEqual(name, 'foo');
        test.strictEqual(callback, cli.connectionCallbacks.deleteAdmin);
        test.done();
      };

      cli.connectionCommands._deleteAdmin(input, cli);
    },
    threeArguments: function(test) {
      var cli = this.cli,
          input = ['deleteAdmin', 'foo', 'redundantInput'];

      console.log = function() {
        test.strictEqual(arguments.length, 1);
        test.done();
      };

      cli.connectionCommands._deleteAdmin(input, cli);
    }
  },

  deleteConnection: {
    oneArgument: function(test) {
      var cli = this.cli,
          input = ['deleteConnection'],
          cPrompt = this.cPrompt;

      cPrompt._showConnections = function(callback) {
        test.strictEqual(arguments.length, 1);
        test.strictEqual(typeof callback, 'function');
        test.strictEqual(callback instanceof Function, true);
        test.strictEqual(callback, cPrompt._setupDeleteSavedConnection);
        test.done();
      };

      cli.connectionCommands._deleteConnection(input, cli);
    },
    twoArguments: {
      inputIsName: {
        nameExists: function(test) {
          var cli = this.cli,
              input = ['deleteConnection', 'connection'],
              writeConnections = this.cFile._writeConnections;

          cli.connections = {};
          cli.connections.connection = 'foo';

          this.cFile._writeConnections = function(connections, callback) {
            test.strictEqual(typeof connections, 'object');
            test.strictEqual(connections instanceof Object, true);
            test.strictEqual(Object.keys(connections).length, 0);

            test.strictEqual(typeof callback, 'function');
            test.strictEqual(callback instanceof Function, true);

            test.done();
          };

          cli.connectionCommands._deleteConnection(input, cli);

          this.cFile._writeConnections = writeConnections;
        },
        nameDoesntExist: function(test) {
          var cli = this.cli,
              input = ['deleteConnection', 'noConnection'];

          cli.connections = {};
          cli.connections.connection = 'foo';

          console.log = function(message) {
            test.strictEqual(Object.keys(cli.connections).length, 1);

            test.strictEqual(arguments.length, 1);
            test.strictEqual(typeof message, 'string');
          };

          cli.prompt = function() {
            test.strictEqual(arguments.length, 0);

            test.done();
          };

          cli.connectionCommands._deleteConnection(input, cli);
        }
      },
      inputIsIndex: {
        indexExists: function(test) {
          var cli = this.cli,
              input = ['deleteConnection', '1'],
              writeConnections = this.cFile._writeConnections;

          cli.connections = {};
          cli.connections.connection = 'foo';

          this.cFile._writeConnections = function(connections, callback) {
            test.strictEqual(typeof connections, 'object');
            test.strictEqual(connections instanceof Object, true);
            test.strictEqual(Object.keys(connections).length, 0);

            test.strictEqual(typeof callback, 'function');
            test.strictEqual(callback instanceof Function, true);

            test.done();
          };

          cli.connectionCommands._deleteConnection(input, cli);

          this.cFile._writeConnections = writeConnections;
        },
        indexDoesntExist: function(test) {
          var cli = this.cli,
              input = ['deleteConnection', '2'];

          cli.connections = {};
          cli.connections.connection = 'foo';

          console.log = function(message) {
            test.strictEqual(Object.keys(cli.connections).length, 1);

            test.strictEqual(arguments.length, 1);
            test.strictEqual(typeof message, 'string');
          };

          cli.prompt = function() {
            test.strictEqual(arguments.length, 0);

            test.done();
          };

          cli.connectionCommands._deleteConnection(input, cli);
        }
      }
    }
  },

  listAdmins: function(test) {
    var cli = this.cli,
        input = ['listAdmins'];

    cli.cushion.config = function(section, callback) {
      test.strictEqual(typeof section, 'string');
      test.strictEqual(section, 'admins');

      test.strictEqual(typeof callback, 'function');
      test.strictEqual(callback instanceof Function, true);
      test.strictEqual(callback, cli.connectionCallbacks.listAdmins);

      test.done();
    };

    cli.connectionCommands._listAdmins(input, cli);
  },

  log: {
    oneArguments: function(test) {
      var cli = this.cli,
          input = ['log'];

      cli.cushion.log = function(callback) {
        test.strictEqual(arguments.length, 1);
        test.strictEqual(callback, cli.connectionCallbacks.log);
        test.done();
      };

      cli.connectionCommands._log(input, cli);
    },
    twoArguments: function(test) {
      var cli = this.cli,
          input = ['log', 8];

      cli.cushion.log = function(bytes, callback) {
        test.strictEqual(arguments.length, 2);
        test.strictEqual(bytes, 8);
        test.strictEqual(callback, cli.connectionCallbacks.log);
        test.done();
      };

      cli.connectionCommands._log(input, cli);
    },
    threeArguments: function(test) {
      var cli = this.cli,
          input = ['log', 12, 'redundantInput'];

      console.log = function() {
        test.strictEqual(arguments.length, 1);
        test.done();
      };

      cli.connectionCommands._log(input, cli);
    }
  },

  saveConnection: {
    oneArgument: function(test) {
      var cli = this.cli,
          input = ['saveConnection'];

      console.log = function() {
        test.strictEqual(arguments.length, 1);
      };

      cli.prompt = function() {
        test.done();
      };

      cli.connectionCommands._saveConnection(input, cli);
    },
    twoArguments: function(test) {
      var cli = this.cli,
          input = ['saveConnection', 'redundantInput'],
          writeConnections = this.cFile._writeConnections;

      this.cFile._writeConnections = function(connections, callback) {
        test.strictEqual(arguments.length, 2);
        test.strictEqual(typeof connections, 'object');
        test.strictEqual(connections instanceof Object, true);
        test.strictEqual(typeof callback, 'function' );
        test.strictEqual(callback instanceof Function, true);
        test.done();
      };

      cli.connectionCommands._saveConnection(input, cli);

      this.cFile._writeConnections = writeConnections;
    }
  },

  showConnection: function(test) {
    var cli = this.cli,
        input = ['showConnection'];

    cli.prompt = function() {
      test.done();
    };

    cli.connectionCommands._showConnection(input, cli);
  },

  simpleCommand: function(test) {
    var cli = this.cli,
        input = ['activeTasks'],
        activeTasks = cli.cushion.activeTasks;

    cli.cushion.activeTasks = function() {
      test.strictEqual(arguments.length, 1);
      test.strictEqual(typeof arguments[0], 'function');
      test.strictEqual(arguments[0], cli.connectionCallbacks.activeTasks);

      test.done();
    };

    cli.connectionCommands._simpleCommand(input, cli);

    cli.cushion.activeTasks = activeTasks;
  },

  uuids: {
    oneArgument: function(test) {
      var cli = this.cli,
          input = ['uuids'];

      cli.cushion.uuids = function(callback) {
        test.strictEqual(arguments.length, 1);
        test.strictEqual(callback, cli.connectionCallbacks.uuids);
        test.done();
      };

      cli.connectionCommands._uuids(input, cli);
    },
    twoArguments: function(test) {
      var cli = this.cli,
          input = ['uuids', 2];
      cli.cushion.uuids = function(nrOfUuids, callback) {
        test.strictEqual(arguments.length, 2);
        test.strictEqual(nrOfUuids, 2);
        test.strictEqual(callback, cli.connectionCallbacks.uuids);
        test.done();
      };

      cli.connectionCommands._uuids(input, cli);
    },
    threeArguments: function(test) {
      var cli = this.cli,
          input = ['uuids', 2, 'redundantInput'];

      console.log = function() {
        test.strictEqual(arguments.length, 1);
        test.done();
      };

      cli.connectionCommands._uuids(input, cli);
    }
  }
};
<|endoftext|>


<commit_before>'use strict';

var _ = require('lodash');
var util = require('util');
var expect = require('chai').expect;
var path = require('path');
var BluebirdPromise = require('bluebird');
var Condition = require('../../../lib/db/condition'),
  w = Condition.w;

module.exports.shouldRunMigrationsAndQueries = function() {
  var db; before(function() { db = this.db; });

  describe('with migrations applied', function() {
    before(function(done) {
      var migration =
        path.join(__dirname, '../../fixtures/migrations/blog');
      this.migrator = db.migrator(migration);
      this.migrator.migrate().then(function() { done(); }, done);
    });

    after(function(done) {
      this.migrator.rollback().then(function() { done(); }, done);
    });

    afterEach(function(done) {
      this.resetSequence('articles').then(function() { done(); }, done);
    });

    it('can insert, update, and delete data', function(done) {
      BluebirdPromise.bind({})
      .then(function() {
        return db
          .insert('articles', { title: 'Title 1', body: 'Contents 1'});
      }).get('rows').get('0')
      .then(function(article) { expect(article).to.not.exist; })
      .then(function() {
        return db
          .insert('articles', { title: 'Title 2', body: 'Contents 2'})
          .returning('id');
      }).get('rows').get('0')
      .then(function(article) { expect(article.id).to.eql(2); })
      .then(function() { return db.select('articles'); }).get('rows')
      .then(function(articles) {
        expect(_.sortBy(articles, 'id')).to.eql([
          { id: 1, title: 'Title 1', body: 'Contents 1'},
          { id: 2, title: 'Title 2', body: 'Contents 2'}
        ]);
      })
      .then(function() {
        return db.update('articles', { title: 'Updated' }).where({ id: 1 });
      })
      .then(function() { return db.select('articles'); }).get('rows')
      .then(function(articles) {
        expect(_.sortBy(articles, 'id')).to.eql([
          { id: 1, title: 'Updated', body: 'Contents 1'},
          { id: 2, title: 'Title 2', body: 'Contents 2'}
        ]);
      })
      .then(function() { return db.delete('articles'); })
      .then(function() { return db.select('articles'); }).get('rows')
      .then(function(articles) {
        expect(articles).to.eql([]);
      })
      .done(done, done);
    });
  });
};

module.exports.shouldSupportStandardTypes = function() {
  var db; before(function() { db = this.db; });

  // shared behavior for type tests
  var viaOptions = function(type, data, expected, options, equal, fn) {
    var table = util.format('azul_type_%s', type);
    var cast = function(result) {
      return this.castDatabaseValue(type, result, options);
    };
    equal = equal || 'equal';
    fn = fn || function() {};
    return function(done) {
      BluebirdPromise.bind(this)
      .then(function() {
        return db.schema.createTable(table, function(table) {
          fn(table[type]('column', options));
        });
      })
      .then(function() { return db.insert(table, { column: data }); })
      .then(function() { return db.select(table); })
      .get('rows')
      .get('0')
      .get('column')
      .then(cast)
      .then(function(result) {
        expect(result).to[equal](expected);
      })
      .finally(function() { return db.schema.dropTable(table).ifExists(); })
      .done(function() { done(); }, done);
    };
  };
  var via = function(type, data, equal) {
    return viaOptions(type, data, data, undefined, equal);
  };

  describe('types', function() {

    it('supports `auto`', via('auto', 1));
    it('supports `increments`', via('increments', 1));
    it('supports `serial`', via('serial', 1));
    it('supports `integer`', via('integer', 1));
    it('supports `integer64`', via('integer64', 1));
    it('supports `string`', via('string', 'hello world'));
    it('supports `text`', via('text', 'hello world'));
    it('supports `binary`', via('binary', new Buffer('hello world'), 'eql'));
    it('supports `bool`', via('bool', true));
    it('supports `date`', via('date', new Date(2014, 10-1, 31), 'eql'));
    it('supports `time`', via('time', '11:57:23'));
    it('supports `dateTime`', via('dateTime', new Date(2014, 10-1, 31), 'eql'));
    it('supports `float`', via('float', 3.14159));
    it('supports `decimal`', via('decimal', 3.14159));

    it('supports `string` length', viaOptions('string', 'val', 'val', {
      length: 3
    }));

    it('supports `decimal`', viaOptions('decimal', 3.14159, 3.14159));

    it('supports `decimal` precision', viaOptions('decimal', 3.14159, 3, {
      precision: 3
    }));

    it('supports `decimal` options', viaOptions('decimal', 3.14159, 3.14, {
      precision: 4,
      scale: 2
    }));

    it('supports `pk`', viaOptions('string', 'key', 'key', {}, null,
      function(col) { col.pk(); }));

    it('supports `primaryKey`', viaOptions('string', 'key', 'key', {}, null,
      function(col) { col.primaryKey(); }));

    it('supports `default`', function(done) {
      var table = 'azul_default';
      var value = 'azul\'s default\\\n\t\b\r\x1a"';
      BluebirdPromise.bind(this)
      .then(function() {
        return db.schema.createTable(table, function(table) {
          table.string('required');
          table.string('string').default(value);
          table.integer('integer').default(3);
        });
      })
      .then(function() { return db.insert(table, { required: '' }); })
      .then(function() { return db.select(table); })
      .get('rows')
      .get('0')
      .then(function(result) {
        expect(result).to.eql({ required: '', string: value, integer: 3 });
      })
      .finally(function() { return db.schema.dropTable(table).ifExists(); })
      .done(function() { done(); }, done);
    });

    it('supports `notNull`', function(done) {
      var table = 'azul_not_null';
      BluebirdPromise.bind(this)
      .then(function() {
        return db.schema.createTable(table, function(table) {
          table.string('column').notNull();
        });
      })
      .then(function() { return db.insert(table, { column: null }); })
      .throw(new Error('Expected insert error to occur.'))
      .catch(function(e) {
        expect(e.message).to.match(/(cannot|violates|constraint).*null/i);
      })
      .finally(function() { return db.schema.dropTable(table).ifExists(); })
      .done(function() { done(); }, done);
    });

    it('supports `unique`', function(done) {
      var table = 'azul_unique';
      BluebirdPromise.bind(this)
      .then(function() {
        return db.schema.createTable(table, function(table) {
          table.string('column').unique();
        });
      })
      .then(function() { return db.insert(table, { column: 'val' }); })
      .then(function() { return db.insert(table, { column: 'val' }); })
      .throw(new Error('Expected insert error to occur.'))
      .catch(function(e) {
        expect(e.message).to.match(/duplicate|unique constraint/i);
      })
      .finally(function() { return db.schema.dropTable(table).ifExists(); })
      .done(function() { done(); }, done);
    });
  });
};

module.exports.shouldSupportStandardConditions = function() {
  var db; before(function() { db = this.db; });

  describe('conditions', function() {
    beforeEach(function(done) {
      db.schema.createTable('people', function(table) {
        table.string('name');
        table.integer('height');
        table.date('dob');
      })
      .then(function() {
        return db.insert('people')
          .values({ name: 'Jim', height: 69, dob: new Date(1968, 2, 14) })
          .values({ name: 'Kristen', height: 65, dob: new Date(1982, 12, 20) })
          .values({ name: 'Sarah', height: 64, dob: new Date(1991, 9, 1) })
          .values({ name: 'Tim', height: 72, dob: new Date(1958, 4, 14) });
      })
      .then(function() { done(); }, done);
    });

    afterEach(function(done) {
      db.schema.dropTable('people').ifExists()
        .then(function() { done(); }, done);
    });

    it('supports `exact`', function(done) {
      db.select('people').where(w({
        'name[exact]': 'Jim',
        'height[exact]': 69,
        'dob[exact]': new Date(1968, 2, 14)
      }))
      .execute()
      .get('rows')
      .then(function(result) {
        expect(_.map(result, 'name')).to.eql(['Jim']);
      })
      .then(done, done);
    });

    it('supports `iexact`', function(done) {
      db.select('people').where(w({
        'name[iexact]': 'kristen'
      }))
      .execute()
      .get('rows')
      .then(function(result) {
        expect(_.map(result, 'name')).to.eql(['Kristen']);
      })
      .then(done, done);
    });

    it.skip('supports `in`', function(done) {
      db.select('people').where(w({
        'name[in]': ['Sarah', 'Tim']
      }))
      .orderBy('name')
      .execute()
      .get('rows')
      .then(function(result) {
        expect(_.map(result, 'name')).to.eql(['Sarah', 'Tim']);
      })
      .then(done, done);
    });

    it('supports `gt`', function(done) {
      db.select('people').where(w({
        'height[gt]': 64,
        'dob[gt]': new Date(1968, 2, 14)
      }))
      .execute()
      .get('rows')
      .then(function(result) {
        expect(_.map(result, 'name')).to.eql(['Kristen']);
      })
      .then(done, done);
    });

    it('supports `gte`', function(done) {
      db.select('people').where(w({
        'height[gte]': 69,
        'dob[gte]': new Date(1958, 4, 14)
      }))
      .order('name')
      .execute()
      .get('rows')
      .then(function(result) {
        expect(_.map(result, 'name')).to.eql(['Jim', 'Tim']);
      })
      .then(done, done);
    });

    it('supports `lt`');
    it('supports `lte`');
    it('supports `between`');
    it('supports `isull`');

    it('supports `contains`');
    it('supports `icontains`');
    it('supports `startsWith`');
    it('supports `istartsWith`');
    it('supports `endsWith`');
    it('supports `iendsWith`');
    it('supports `regex`');
    it('supports `iregex`');

    it('supports `year`');
    it('supports `month`');
    it('supports `day`');
    it('supports `weekday`');
    it('supports `hour`');
    it('supports `minute`');
    it('supports `second`');
  });
};
<commit_msg>Fixed pending `in` test.<commit_after>'use strict';

var _ = require('lodash');
var util = require('util');
var expect = require('chai').expect;
var path = require('path');
var BluebirdPromise = require('bluebird');
var Condition = require('../../../lib/db/condition'),
  w = Condition.w;

module.exports.shouldRunMigrationsAndQueries = function() {
  var db; before(function() { db = this.db; });

  describe('with migrations applied', function() {
    before(function(done) {
      var migration =
        path.join(__dirname, '../../fixtures/migrations/blog');
      this.migrator = db.migrator(migration);
      this.migrator.migrate().then(function() { done(); }, done);
    });

    after(function(done) {
      this.migrator.rollback().then(function() { done(); }, done);
    });

    afterEach(function(done) {
      this.resetSequence('articles').then(function() { done(); }, done);
    });

    it('can insert, update, and delete data', function(done) {
      BluebirdPromise.bind({})
      .then(function() {
        return db
          .insert('articles', { title: 'Title 1', body: 'Contents 1'});
      }).get('rows').get('0')
      .then(function(article) { expect(article).to.not.exist; })
      .then(function() {
        return db
          .insert('articles', { title: 'Title 2', body: 'Contents 2'})
          .returning('id');
      }).get('rows').get('0')
      .then(function(article) { expect(article.id).to.eql(2); })
      .then(function() { return db.select('articles'); }).get('rows')
      .then(function(articles) {
        expect(_.sortBy(articles, 'id')).to.eql([
          { id: 1, title: 'Title 1', body: 'Contents 1'},
          { id: 2, title: 'Title 2', body: 'Contents 2'}
        ]);
      })
      .then(function() {
        return db.update('articles', { title: 'Updated' }).where({ id: 1 });
      })
      .then(function() { return db.select('articles'); }).get('rows')
      .then(function(articles) {
        expect(_.sortBy(articles, 'id')).to.eql([
          { id: 1, title: 'Updated', body: 'Contents 1'},
          { id: 2, title: 'Title 2', body: 'Contents 2'}
        ]);
      })
      .then(function() { return db.delete('articles'); })
      .then(function() { return db.select('articles'); }).get('rows')
      .then(function(articles) {
        expect(articles).to.eql([]);
      })
      .done(done, done);
    });
  });
};

module.exports.shouldSupportStandardTypes = function() {
  var db; before(function() { db = this.db; });

  // shared behavior for type tests
  var viaOptions = function(type, data, expected, options, equal, fn) {
    var table = util.format('azul_type_%s', type);
    var cast = function(result) {
      return this.castDatabaseValue(type, result, options);
    };
    equal = equal || 'equal';
    fn = fn || function() {};
    return function(done) {
      BluebirdPromise.bind(this)
      .then(function() {
        return db.schema.createTable(table, function(table) {
          fn(table[type]('column', options));
        });
      })
      .then(function() { return db.insert(table, { column: data }); })
      .then(function() { return db.select(table); })
      .get('rows')
      .get('0')
      .get('column')
      .then(cast)
      .then(function(result) {
        expect(result).to[equal](expected);
      })
      .finally(function() { return db.schema.dropTable(table).ifExists(); })
      .done(function() { done(); }, done);
    };
  };
  var via = function(type, data, equal) {
    return viaOptions(type, data, data, undefined, equal);
  };

  describe('types', function() {

    it('supports `auto`', via('auto', 1));
    it('supports `increments`', via('increments', 1));
    it('supports `serial`', via('serial', 1));
    it('supports `integer`', via('integer', 1));
    it('supports `integer64`', via('integer64', 1));
    it('supports `string`', via('string', 'hello world'));
    it('supports `text`', via('text', 'hello world'));
    it('supports `binary`', via('binary', new Buffer('hello world'), 'eql'));
    it('supports `bool`', via('bool', true));
    it('supports `date`', via('date', new Date(2014, 10-1, 31), 'eql'));
    it('supports `time`', via('time', '11:57:23'));
    it('supports `dateTime`', via('dateTime', new Date(2014, 10-1, 31), 'eql'));
    it('supports `float`', via('float', 3.14159));
    it('supports `decimal`', via('decimal', 3.14159));

    it('supports `string` length', viaOptions('string', 'val', 'val', {
      length: 3
    }));

    it('supports `decimal`', viaOptions('decimal', 3.14159, 3.14159));

    it('supports `decimal` precision', viaOptions('decimal', 3.14159, 3, {
      precision: 3
    }));

    it('supports `decimal` options', viaOptions('decimal', 3.14159, 3.14, {
      precision: 4,
      scale: 2
    }));

    it('supports `pk`', viaOptions('string', 'key', 'key', {}, null,
      function(col) { col.pk(); }));

    it('supports `primaryKey`', viaOptions('string', 'key', 'key', {}, null,
      function(col) { col.primaryKey(); }));

    it('supports `default`', function(done) {
      var table = 'azul_default';
      var value = 'azul\'s default\\\n\t\b\r\x1a"';
      BluebirdPromise.bind(this)
      .then(function() {
        return db.schema.createTable(table, function(table) {
          table.string('required');
          table.string('string').default(value);
          table.integer('integer').default(3);
        });
      })
      .then(function() { return db.insert(table, { required: '' }); })
      .then(function() { return db.select(table); })
      .get('rows')
      .get('0')
      .then(function(result) {
        expect(result).to.eql({ required: '', string: value, integer: 3 });
      })
      .finally(function() { return db.schema.dropTable(table).ifExists(); })
      .done(function() { done(); }, done);
    });

    it('supports `notNull`', function(done) {
      var table = 'azul_not_null';
      BluebirdPromise.bind(this)
      .then(function() {
        return db.schema.createTable(table, function(table) {
          table.string('column').notNull();
        });
      })
      .then(function() { return db.insert(table, { column: null }); })
      .throw(new Error('Expected insert error to occur.'))
      .catch(function(e) {
        expect(e.message).to.match(/(cannot|violates|constraint).*null/i);
      })
      .finally(function() { return db.schema.dropTable(table).ifExists(); })
      .done(function() { done(); }, done);
    });

    it('supports `unique`', function(done) {
      var table = 'azul_unique';
      BluebirdPromise.bind(this)
      .then(function() {
        return db.schema.createTable(table, function(table) {
          table.string('column').unique();
        });
      })
      .then(function() { return db.insert(table, { column: 'val' }); })
      .then(function() { return db.insert(table, { column: 'val' }); })
      .throw(new Error('Expected insert error to occur.'))
      .catch(function(e) {
        expect(e.message).to.match(/duplicate|unique constraint/i);
      })
      .finally(function() { return db.schema.dropTable(table).ifExists(); })
      .done(function() { done(); }, done);
    });
  });
};

module.exports.shouldSupportStandardConditions = function() {
  var db; before(function() { db = this.db; });

  describe('conditions', function() {
    beforeEach(function(done) {
      db.schema.createTable('people', function(table) {
        table.string('name');
        table.integer('height');
        table.date('dob');
      })
      .then(function() {
        return db.insert('people')
          .values({ name: 'Jim', height: 69, dob: new Date(1968, 2, 14) })
          .values({ name: 'Kristen', height: 65, dob: new Date(1982, 12, 20) })
          .values({ name: 'Sarah', height: 64, dob: new Date(1991, 9, 1) })
          .values({ name: 'Tim', height: 72, dob: new Date(1958, 4, 14) });
      })
      .then(function() { done(); }, done);
    });

    afterEach(function(done) {
      db.schema.dropTable('people').ifExists()
        .then(function() { done(); }, done);
    });

    it('supports `exact`', function(done) {
      db.select('people').where(w({
        'name[exact]': 'Jim',
        'height[exact]': 69,
        'dob[exact]': new Date(1968, 2, 14)
      }))
      .execute()
      .get('rows')
      .then(function(result) {
        expect(_.map(result, 'name')).to.eql(['Jim']);
      })
      .then(done, done);
    });

    it('supports `iexact`', function(done) {
      db.select('people').where(w({
        'name[iexact]': 'kristen'
      }))
      .execute()
      .get('rows')
      .then(function(result) {
        expect(_.map(result, 'name')).to.eql(['Kristen']);
      })
      .then(done, done);
    });

    it.skip('supports `in`', function(done) {
      db.select('people').where(w({
        'name[in]': ['Sarah', 'Tim']
      }))
      .order('name')
      .execute()
      .get('rows')
      .then(function(result) {
        expect(_.map(result, 'name')).to.eql(['Sarah', 'Tim']);
      })
      .then(done, done);
    });

    it('supports `gt`', function(done) {
      db.select('people').where(w({
        'height[gt]': 64,
        'dob[gt]': new Date(1968, 2, 14)
      }))
      .execute()
      .get('rows')
      .then(function(result) {
        expect(_.map(result, 'name')).to.eql(['Kristen']);
      })
      .then(done, done);
    });

    it('supports `gte`', function(done) {
      db.select('people').where(w({
        'height[gte]': 69,
        'dob[gte]': new Date(1958, 4, 14)
      }))
      .order('name')
      .execute()
      .get('rows')
      .then(function(result) {
        expect(_.map(result, 'name')).to.eql(['Jim', 'Tim']);
      })
      .then(done, done);
    });

    it('supports `lt`');
    it('supports `lte`');
    it('supports `between`');
    it('supports `isull`');

    it('supports `contains`');
    it('supports `icontains`');
    it('supports `startsWith`');
    it('supports `istartsWith`');
    it('supports `endsWith`');
    it('supports `iendsWith`');
    it('supports `regex`');
    it('supports `iregex`');

    it('supports `year`');
    it('supports `month`');
    it('supports `day`');
    it('supports `weekday`');
    it('supports `hour`');
    it('supports `minute`');
    it('supports `second`');
  });
};
<|endoftext|>


<commit_before>// Copyright (c) 2015 - 2017 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

import {
  createElement,
  useRef,
  useState,
  useMemo,
  useEffect,
  useImperativeHandle,
  forwardRef
} from 'react';
import PropTypes from 'prop-types';
import {Deck} from '@deck.gl/core';
import useIsomorphicLayoutEffect from './utils/use-isomorphic-layout-effect';

import extractJSXLayers from './utils/extract-jsx-layers';
import positionChildrenUnderViews from './utils/position-children-under-views';
import extractStyles from './utils/extract-styles';

/* eslint-disable max-statements, accessor-pairs */

function getRefHandles(thisRef) {
  const handles = {
    pickObject: opts => thisRef.deck.pickObject(opts),
    pickMultipleObjects: opts => thisRef.deck.pickMultipleObjects(opts),
    pickObjects: opts => thisRef.deck.pickObjects(opts)
  };
  Object.defineProperty(handles, 'deck', {
    get: () => thisRef.deck
  });
  return handles;
}

function redrawDeck(thisRef) {
  if (thisRef.redrawReason) {
    // Only redraw if we have received a dirty flag
    thisRef.deck._drawLayers(thisRef.redrawReason);
    thisRef.redrawReason = null;
  }
}

function createDeckInstance(thisRef, props) {
  // Allows a subclass of Deck to be used
  // TODO - update propTypes / defaultProps?
  const DeckClass = props.Deck || Deck;
  const deck = new DeckClass({
    ...props,
    style: null,
    width: '100%',
    height: '100%',
    // The Deck's animation loop is independent from React's render cycle, causing potential
    // synchronization issues. We provide this custom render function to make sure that React
    // and Deck update on the same schedule.
    _customRender: redrawReason => {
      // Save the dirty flag for later
      thisRef.redrawReason = redrawReason;

      // Viewport/view state is passed to child components as props.
      // If they have changed, we need to trigger a React rerender to update children props.
      const viewports = deck.viewManager.getViewports();
      if (thisRef.lastRenderedViewports !== viewports) {
        // Viewports have changed, update children props first.
        // This will delay the Deck canvas redraw till after React update (in useLayoutEffect)
        // so that the canvas does not get rendered before the child components update.
        thisRef.forceUpdate(v => v + 1);
      } else {
        redrawDeck(thisRef);
      }
    }
  });
  return deck;
}

const DeckGL = forwardRef((props, ref) => {
  // A reference to persistent states
  const _thisRef = useRef({});
  const thisRef = _thisRef.current;
  // A mechanism to force redraw
  const [, setVersion] = useState(0);
  thisRef.forceUpdate = setVersion;
  // DOM refs
  const containerRef = useRef(null);
  const canvasRef = useRef(null);

  // extract any deck.gl layers masquerading as react elements from props.children
  const jsxProps = useMemo(() => extractJSXLayers(props), [
    props.layers,
    props.views,
    props.children
  ]);

  // Callbacks
  let inRender = true;
  let viewStateUpdateRequested;
  let interactionStateUpdateRequested;

  const handleViewStateChange = params => {
    if (inRender && props.viewState) {
      // Callback may invoke a state update. Defer callback to after render() to avoid React error
      viewStateUpdateRequested = params;
      return null;
    }
    return props.onViewStateChange(params);
  };

  const handleInteractionStateChange = params => {
    if (inRender) {
      // Callback may invoke a state update. Defer callback to after render() to avoid React error
      interactionStateUpdateRequested = params;
    } else {
      props.onInteractionStateChange(params);
    }
  };

  // Update Deck's props. If Deck needs redraw, this will trigger a call to `_customRender` in
  // the next animation frame.
  // Needs to be called both from initial mount, and when new props are received
  const updateFromProps = () => {
    if (!thisRef.deck) {
      return;
    }
    const deckProps = {
      ...props,
      // Override user styling props. We will set the canvas style in render()
      style: null,
      width: '100%',
      height: '100%',
      layers: jsxProps.layers,
      views: jsxProps.views,
      onViewStateChange: handleViewStateChange,
      onInteractionStateChange: handleInteractionStateChange
    };

    thisRef.deck.setProps(deckProps);
  };

  useEffect(() => {
    thisRef.deck = createDeckInstance(thisRef, {
      ...props,
      parent: containerRef.current,
      canvas: canvasRef.current
    });
    updateFromProps();

    return () => thisRef.deck.finalize();
  }, []);

  useIsomorphicLayoutEffect(() => {
    // render has just been called. The children are positioned based on the current view state.
    // Redraw Deck canvas immediately, if necessary, using the current view state, so that it
    // matches the child components.
    redrawDeck(thisRef);

    // Execute deferred callbacks
    if (viewStateUpdateRequested) {
      handleViewStateChange(viewStateUpdateRequested);
    }
    if (interactionStateUpdateRequested) {
      handleInteractionStateChange(interactionStateUpdateRequested);
    }
  });

  useImperativeHandle(ref, () => getRefHandles(thisRef), []);

  updateFromProps();

  const {viewManager} = thisRef.deck || {};
  const currentViewports = viewManager && viewManager.getViewports();

  const {ContextProvider, width, height, style} = props;

  const {containerStyle, canvasStyle} = useMemo(() => extractStyles({width, height, style}), [
    width,
    height,
    style
  ]);

  // Props changes may lead to 3 types of updates:
  // 1. Only the WebGL canvas - updated in Deck's render cycle (next animation frame)
  // 2. Only the DOM - updated in React's lifecycle (now)
  // 3. Both the WebGL canvas and the DOM - defer React rerender to next animation frame just
  //    before Deck redraw to ensure perfect synchronization & avoid excessive redraw
  //    This is because multiple changes may happen to Deck between two frames e.g. transition
  if (
    !thisRef.control || // initial mount
    (!viewStateUpdateRequested && thisRef.lastRenderedViewports === currentViewports) || // case 2
    thisRef.redrawReason // case 3 just before deck redraws
  ) {
    thisRef.lastRenderedViewports = currentViewports;

    // Render the background elements (typically react-map-gl instances)
    // using the view descriptors
    const childrenUnderViews = positionChildrenUnderViews({
      children: jsxProps.children,
      deck: thisRef.deck,
      ContextProvider
    });

    const canvas = createElement('canvas', {
      key: 'canvas',
      ref: canvasRef,
      style: canvasStyle
    });

    // Render deck.gl as the last child
    thisRef.control = createElement(
      'div',
      {id: 'deckgl-wrapper', ref: containerRef, style: containerStyle},
      [canvas, childrenUnderViews]
    );
  }

  inRender = false;
  return thisRef.control;
});

DeckGL.propTypes = Deck.getPropTypes(PropTypes);
DeckGL.defaultProps = Deck.defaultProps;

export default DeckGL;
<commit_msg>[react] Fix flickering in React.StrictMode (#5511)<commit_after>// Copyright (c) 2015 - 2017 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

import {
  createElement,
  useRef,
  useState,
  useMemo,
  useEffect,
  useImperativeHandle,
  forwardRef
} from 'react';
import PropTypes from 'prop-types';
import {Deck} from '@deck.gl/core';
import useIsomorphicLayoutEffect from './utils/use-isomorphic-layout-effect';

import extractJSXLayers from './utils/extract-jsx-layers';
import positionChildrenUnderViews from './utils/position-children-under-views';
import extractStyles from './utils/extract-styles';

/* eslint-disable max-statements, accessor-pairs */

function getRefHandles(thisRef) {
  const handles = {
    pickObject: opts => thisRef.deck.pickObject(opts),
    pickMultipleObjects: opts => thisRef.deck.pickMultipleObjects(opts),
    pickObjects: opts => thisRef.deck.pickObjects(opts)
  };
  Object.defineProperty(handles, 'deck', {
    get: () => thisRef.deck
  });
  return handles;
}

function redrawDeck(thisRef) {
  if (thisRef.redrawReason) {
    // Only redraw if we have received a dirty flag
    thisRef.deck._drawLayers(thisRef.redrawReason);
    thisRef.redrawReason = null;
  }
}

function createDeckInstance(thisRef, props) {
  // Allows a subclass of Deck to be used
  // TODO - update propTypes / defaultProps?
  const DeckClass = props.Deck || Deck;
  const deck = new DeckClass({
    ...props,
    style: null,
    width: '100%',
    height: '100%',
    // The Deck's animation loop is independent from React's render cycle, causing potential
    // synchronization issues. We provide this custom render function to make sure that React
    // and Deck update on the same schedule.
    _customRender: redrawReason => {
      // Save the dirty flag for later
      thisRef.redrawReason = redrawReason;

      // Viewport/view state is passed to child components as props.
      // If they have changed, we need to trigger a React rerender to update children props.
      const viewports = deck.viewManager.getViewports();
      if (thisRef.lastRenderedViewports !== viewports) {
        // Viewports have changed, update children props first.
        // This will delay the Deck canvas redraw till after React update (in useLayoutEffect)
        // so that the canvas does not get rendered before the child components update.
        thisRef.forceUpdate(v => v + 1);
      } else {
        redrawDeck(thisRef);
      }
    }
  });
  return deck;
}

const DeckGL = forwardRef((props, ref) => {
  // A reference to persistent states
  const _thisRef = useRef({});
  const thisRef = _thisRef.current;
  // A mechanism to force redraw
  const [, setVersion] = useState(0);
  thisRef.forceUpdate = setVersion;
  // DOM refs
  const containerRef = useRef(null);
  const canvasRef = useRef(null);

  // extract any deck.gl layers masquerading as react elements from props.children
  const jsxProps = useMemo(() => extractJSXLayers(props), [
    props.layers,
    props.views,
    props.children
  ]);

  // Callbacks
  let inRender = true;

  const handleViewStateChange = params => {
    if (inRender && props.viewState) {
      // Callback may invoke a state update. Defer callback to after render() to avoid React error
      // In React StrictMode, render is executed twice and useEffect/useLayoutEffect is executed once
      // Store deferred parameters in ref so that we can access it in another render
      thisRef.viewStateUpdateRequested = params;
      return null;
    }
    thisRef.viewStateUpdateRequested = null;
    return props.onViewStateChange(params);
  };

  const handleInteractionStateChange = params => {
    if (inRender) {
      // Callback may invoke a state update. Defer callback to after render() to avoid React error
      // In React StrictMode, render is executed twice and useEffect/useLayoutEffect is executed once
      // Store deferred parameters in ref so that we can access it in another render
      thisRef.interactionStateUpdateRequested = params;
    } else {
      thisRef.interactionStateUpdateRequested = null;
      props.onInteractionStateChange(params);
    }
  };

  // Update Deck's props. If Deck needs redraw, this will trigger a call to `_customRender` in
  // the next animation frame.
  // Needs to be called both from initial mount, and when new props are received
  const updateFromProps = () => {
    if (!thisRef.deck) {
      return;
    }
    const deckProps = {
      ...props,
      // Override user styling props. We will set the canvas style in render()
      style: null,
      width: '100%',
      height: '100%',
      layers: jsxProps.layers,
      views: jsxProps.views,
      onViewStateChange: handleViewStateChange,
      onInteractionStateChange: handleInteractionStateChange
    };

    thisRef.deck.setProps(deckProps);
  };

  useEffect(() => {
    thisRef.deck = createDeckInstance(thisRef, {
      ...props,
      parent: containerRef.current,
      canvas: canvasRef.current
    });
    updateFromProps();

    return () => thisRef.deck.finalize();
  }, []);

  useIsomorphicLayoutEffect(() => {
    // render has just been called. The children are positioned based on the current view state.
    // Redraw Deck canvas immediately, if necessary, using the current view state, so that it
    // matches the child components.
    redrawDeck(thisRef);

    // Execute deferred callbacks
    const {viewStateUpdateRequested, interactionStateUpdateRequested} = thisRef;
    if (viewStateUpdateRequested) {
      handleViewStateChange(viewStateUpdateRequested);
    }
    if (interactionStateUpdateRequested) {
      handleInteractionStateChange(interactionStateUpdateRequested);
    }
  });

  useImperativeHandle(ref, () => getRefHandles(thisRef), []);

  updateFromProps();

  const {viewManager} = thisRef.deck || {};
  const currentViewports = viewManager && viewManager.getViewports();

  const {ContextProvider, width, height, style} = props;

  const {containerStyle, canvasStyle} = useMemo(() => extractStyles({width, height, style}), [
    width,
    height,
    style
  ]);

  // Props changes may lead to 3 types of updates:
  // 1. Only the WebGL canvas - updated in Deck's render cycle (next animation frame)
  // 2. Only the DOM - updated in React's lifecycle (now)
  // 3. Both the WebGL canvas and the DOM - defer React rerender to next animation frame just
  //    before Deck redraw to ensure perfect synchronization & avoid excessive redraw
  //    This is because multiple changes may happen to Deck between two frames e.g. transition
  if (
    !thisRef.control || // initial mount
    (!thisRef.viewStateUpdateRequested && thisRef.lastRenderedViewports === currentViewports) || // case 2
    thisRef.redrawReason // case 3 just before deck redraws
  ) {
    thisRef.lastRenderedViewports = currentViewports;

    // Render the background elements (typically react-map-gl instances)
    // using the view descriptors
    const childrenUnderViews = positionChildrenUnderViews({
      children: jsxProps.children,
      deck: thisRef.deck,
      ContextProvider
    });

    const canvas = createElement('canvas', {
      key: 'canvas',
      ref: canvasRef,
      style: canvasStyle
    });

    // Render deck.gl as the last child
    thisRef.control = createElement(
      'div',
      {id: 'deckgl-wrapper', ref: containerRef, style: containerStyle},
      [canvas, childrenUnderViews]
    );
  }

  inRender = false;
  return thisRef.control;
});

DeckGL.propTypes = Deck.getPropTypes(PropTypes);
DeckGL.defaultProps = Deck.defaultProps;

export default DeckGL;
<|endoftext|>


<commit_before>'use strict';

var reporter = require('../../../index');
var assertHtmlReports = require('../../assert/assertHtmlReports');
var path = require('path');

var hooks = function() {
    this.Before(function(scenario, callback) {
        console.log('console logs should not break the report');
        this.scenario = scenario;
        callback();
    });

    this.registerHandler('AfterFeatures', function(features, callback) {

        var theme = {
            bootstrap: 'bootstrap',
            foundation: 'foundation',
            simple: 'simple'
        };

        var outputDirectory = 'test/report/';
        var jsonFile = 'test/report/cucumber_report.json';
        var jsonDir = 'test/report/multi';

        function getOptions(theme) {
            return {
                theme: theme,
                output: path.join(outputDirectory, 'cucumber_report_' + theme + '.html'),
                reportSuiteAsScenarios: true
            };
        }

        function getJsonFileOptions(theme) {
            var options = getOptions(theme);
            options.jsonFile = jsonFile;
            return options;
        }

        function getJsonDirOptions(theme) {
            var options = getOptions(theme);
            options.jsonDir = jsonDir;
            return options;
        }

        function assertJsonFile() {

            //Generate Bootstrap theme report
            reporter.generate(getJsonFileOptions(theme.bootstrap));

            //Generate Foundation theme report
            reporter.generate(getJsonFileOptions(theme.foundation));

            //Generate Simple theme report
            reporter.generate(getJsonFileOptions(theme.simple));

            //assert reports
            assertHtmlReports(outputDirectory);
        }

        function assertJsonDir() {
            //Generate Bootstrap theme report
            reporter.generate(getJsonDirOptions(theme.bootstrap));

            //Generate Foundation theme report
            reporter.generate(getJsonDirOptions(theme.foundation));

            //Generate Simple theme report
            reporter.generate(getJsonDirOptions(theme.simple));

            //assert reports
            assertHtmlReports(outputDirectory);
        }

        // assertJsonFile();

        assertJsonDir();

        callback();
    });
};

module.exports = hooks;<commit_msg>unlink reports - unit tests for jsonDir<commit_after>'use strict';

var reporter = require('../../../index');
var assertHtmlReports = require('../../assert/assertHtmlReports');
var path = require('path');
var fs = require('fs');
var find = require('find');

var hooks = function() {
    this.Before(function(scenario, callback) {
        console.log('console logs should not break the report');
        this.scenario = scenario;
        callback();
    });

    this.registerHandler('AfterFeatures', function(features, callback) {

        var theme = {
            bootstrap: 'bootstrap',
            foundation: 'foundation',
            simple: 'simple'
        };

        var outputDirectory = 'test/report/';
        var jsonFile = 'test/report/cucumber_report.json';
        var jsonDir = 'test/report/multi';

        function removeReports() {
            var files = find.fileSync(/\.html/, outputDirectory);
            files.map(function(file) {
                fs.unlinkSync(file);
            });
        }

        function getOptions(theme) {
            return {
                theme: theme,
                output: path.join(outputDirectory, 'cucumber_report_' + theme + '.html'),
                reportSuiteAsScenarios: true
            };
        }

        function getJsonFileOptions(theme) {
            var options = getOptions(theme);
            options.jsonFile = jsonFile;
            return options;
        }

        function getJsonDirOptions(theme) {
            var options = getOptions(theme);
            options.jsonDir = jsonDir;

            return options;
        }

        function assertJsonFile() {

            //Generate Bootstrap theme report
            reporter.generate(getJsonFileOptions(theme.bootstrap));

            //Generate Foundation theme report
            reporter.generate(getJsonFileOptions(theme.foundation));

            //Generate Simple theme report
            reporter.generate(getJsonFileOptions(theme.simple));

            //assert reports
            assertHtmlReports(outputDirectory);
        }

        function assertJsonDir() {
            //Generate Bootstrap theme report
            reporter.generate(getJsonDirOptions(theme.bootstrap));

            //Generate Foundation theme report
            reporter.generate(getJsonDirOptions(theme.foundation));

            //Generate Simple theme report
            reporter.generate(getJsonDirOptions(theme.simple));

            //assert reports
            assertHtmlReports(outputDirectory);
        }

        assertJsonFile();

        removeReports();

        assertJsonDir();

        callback();
    });
};

module.exports = hooks;<|endoftext|>


<commit_before>/*

CommentaryLayout

filters – queryParams relations explanation:
“queryParams” represent state of truth
“filters” are a friendly object representation of “queryParams” passed to children components

To change the commentary filtering,
call the “this._updateRoute(filters)” method
with new “filters” object passed as first attribute.

*/

import React, { Component } from 'react';
import PropTypes from 'prop-types';
import autoBind from 'react-autobind';
import { connect } from 'react-redux';
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';
import getMuiTheme from 'material-ui/styles/getMuiTheme';
import { compose } from 'react-apollo';
import qs from 'qs-lite';

// components
import CommentaryContainer from '../../containers/CommentaryContainer';
import Header from '../../../../components/navigation/Header';

// auth
import AuthModalContainer from '../../../../modules/auth/containers/AuthModalContainer';
import { login, register, logoutUser, verifyToken } from '../../../../lib/auth';

// graphql
import referenceWorksQuery from '../../../referenceWorks/graphql/queries/referenceWorksQuery';
import { editionsQuery } from '../../../textNodes/graphql/queries/editions';

// lib
import muiTheme from '../../../../lib/muiTheme';
import {
	createFilterFromQueryParams,
	createQueryParamsFromFilters,
	updateFilterOnChangeLineEvent,
	updateFilterOnChangeTextSearchEvent,
	updateFilterOnKeyAndValueChangeEvent,
	createFilterFromURL
} from '../../lib/queryFilterHelpers';

class CommentaryLayout extends Component {
	constructor(props) {
		super(props);

		this.state = {
			modalLoginLowered: false,
			skip: 0,
			limit: 10,
			queryParams: qs.parse(window.location.search.substr(1)),
			params: this.props.match,
			referenceWorks: [],
			works: [],
			filters: []
		};

		// TODO: move refetch to container
		this.props.referenceWorksQuery.refetch({
			tenantId: props.tenantId,
		});

		autoBind(this);
	}

	getFilterValue(filters, key) {
		let value = {};
		if (filters) {
			const filterKey = filters.find(filter => filter.key === key);
			if (filterKey) {
				value = filterKey.values[0];
			}
		}
		return value;
	}

	_updateRoute(filters) {
		let queryParams = {};
		const { referenceWorks, history } = this.props;
		if (filters) {
			queryParams = createQueryParamsFromFilters(filters, referenceWorks);
		} else {
			queryParams = this.props.queryParams;
		}

		// update route
		const urlParams = qs.stringify(queryParams);

		history.push(`/commentary/?${urlParams}`);
	}

	_toggleSearchTerm(key, value) {
		const { queryParams } = this.state;
		const oldFilters = createFilterFromQueryParams(queryParams);

		// update filter based on the key and value
		const filters = updateFilterOnKeyAndValueChangeEvent(oldFilters, key, value);

		this.setState({
			skip: 0,
			limit: 10,
		});

		this._updateRoute(filters);
	}

	_handleChangeTextsearch(e, textsearch) {
		const { queryParams } = this.state;
		const oldFilters = createFilterFromQueryParams(queryParams);

		// update filter based on the textsearch
		const filters = updateFilterOnChangeTextSearchEvent(oldFilters, e, textsearch);

		this._updateRoute(filters);
	}

	_handleChangeLineN(e) {
		const { queryParams } = this.state;
		const oldFilters = createFilterFromQueryParams(queryParams);

		// update filter based on the 'e' attribute
		const filters = updateFilterOnChangeLineEvent(oldFilters, e);

		this.setState({
			skip: 0,
			limit: 10,
		});
		this._updateRoute(filters);
	}

	loadMoreComments() {
		if (
			!this.props.isOnHomeView
			&& this.props.commentsMoreQuery
			&& this.props.commentsMoreQuery.commentsMore
		) {
			this.setState({
				limit: this.state.limit + 10,
			});
		}
	}

	componentWillReceiveProps(nextProps) {
		const referenceWorks = nextProps.referenceWorksQuery.loading ? [] : nextProps.referenceWorksQuery.referenceWorks;
		const works = nextProps.editionsQuery.loading ? [] : nextProps.editionsQuery.works
		this.setState({
			referenceWorks: referenceWorks,
			works: works,
			filters: createFilterFromURL(this.state.params, this.state.queryParams, this.state.works, this.state.referenceWorks)
		});
	}

	render() {
		const { skip, limit, queryParams, filters } = this.state;

		// create filters object based on the queryParams or params
		return (
			<MuiThemeProvider muiTheme={getMuiTheme(muiTheme)}>

						<CommentaryContainer
							filters={filters}
							toggleSearchTerm={this._toggleSearchTerm}
							showLoginModal={this.showLoginModal}
							loadMoreComments={this.loadMoreComments}
							skip={skip}
							limit={limit}
							queryParams={queryParams}
						/>

					<AuthModalContainer
						loginMethod={login}
						signupMethod={register}
						logoutMethod={logoutUser}
						getUserFromServer={verifyToken}
					/>

			</MuiThemeProvider>
		);
	}
}

CommentaryLayout.defaultProps = {
	queryParams: {
		lineTo: 611,
	}
};

CommentaryLayout.propTypes = {
	queryParams: PropTypes.object,
	referenceWorks: PropTypes.array,
	works: PropTypes.array,
	history: PropTypes.any,
	editionsQuery: PropTypes.object,
	referenceWorksQuery: PropTypes.object,
	match: PropTypes.object
};

const mapStateToProps = (state, props) => ({
	tenantId: state.tenant.tenantId,
});

export default compose(
	referenceWorksQuery,
	editionsQuery,
	connect(mapStateToProps),
)(CommentaryLayout);
<commit_msg>add tenantId to commentary layout comments query<commit_after>/*

CommentaryLayout

filters – queryParams relations explanation:
“queryParams” represent state of truth
“filters” are a friendly object representation of “queryParams” passed to children components

To change the commentary filtering,
call the “this._updateRoute(filters)” method
with new “filters” object passed as first attribute.

*/

import React, { Component } from 'react';
import PropTypes from 'prop-types';
import autoBind from 'react-autobind';
import { connect } from 'react-redux';
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';
import getMuiTheme from 'material-ui/styles/getMuiTheme';
import { compose } from 'react-apollo';
import qs from 'qs-lite';

// components
import CommentaryContainer from '../../containers/CommentaryContainer';
import Header from '../../../../components/navigation/Header';

// auth
import AuthModalContainer from '../../../../modules/auth/containers/AuthModalContainer';
import { login, register, logoutUser, verifyToken } from '../../../../lib/auth';

// graphql
import referenceWorksQuery from '../../../referenceWorks/graphql/queries/referenceWorksQuery';
import { editionsQuery } from '../../../textNodes/graphql/queries/editions';

// lib
import muiTheme from '../../../../lib/muiTheme';
import {
	createFilterFromQueryParams,
	createQueryParamsFromFilters,
	updateFilterOnChangeLineEvent,
	updateFilterOnChangeTextSearchEvent,
	updateFilterOnKeyAndValueChangeEvent,
	createFilterFromURL
} from '../../lib/queryFilterHelpers';

class CommentaryLayout extends Component {
	constructor(props) {
		super(props);

		this.state = {
			modalLoginLowered: false,
			skip: 0,
			limit: 10,
			queryParams: qs.parse(window.location.search.substr(1)),
			params: this.props.match,
			filters: []
		};

		autoBind(this);
	}

	getFilterValue(filters, key) {
		let value = {};
		if (filters) {
			const filterKey = filters.find(filter => filter.key === key);
			if (filterKey) {
				value = filterKey.values[0];
			}
		}
		return value;
	}

	_updateRoute(filters) {
		let queryParams = {};
		const { referenceWorks, history } = this.props;
		if (filters) {
			queryParams = createQueryParamsFromFilters(filters, referenceWorks);
		} else {
			queryParams = this.props.queryParams;
		}

		// update route
		const urlParams = qs.stringify(queryParams);

		history.push(`/commentary/?${urlParams}`);
	}

	_toggleSearchTerm(key, value) {
		const { queryParams } = this.state;
		const oldFilters = createFilterFromQueryParams(queryParams);

		// update filter based on the key and value
		const filters = updateFilterOnKeyAndValueChangeEvent(oldFilters, key, value);

		this.setState({
			skip: 0,
			limit: 10,
		});

		this._updateRoute(filters);
	}

	_handleChangeTextsearch(e, textsearch) {
		const { queryParams } = this.state;
		const oldFilters = createFilterFromQueryParams(queryParams);

		// update filter based on the textsearch
		const filters = updateFilterOnChangeTextSearchEvent(oldFilters, e, textsearch);

		this._updateRoute(filters);
	}

	_handleChangeLineN(e) {
		const { queryParams } = this.state;
		const oldFilters = createFilterFromQueryParams(queryParams);

		// update filter based on the 'e' attribute
		const filters = updateFilterOnChangeLineEvent(oldFilters, e);

		this.setState({
			skip: 0,
			limit: 10,
		});
		this._updateRoute(filters);
	}

	loadMoreComments() {
		if (
			!this.props.isOnHomeView
			&& this.props.commentsMoreQuery
			&& this.props.commentsMoreQuery.commentsMore
		) {
			this.setState({
				limit: this.state.limit + 10,
			});
		}
	}

	componentWillReceiveProps(nextProps) {
		const referenceWorks = nextProps.referenceWorksQuery.loading ? [] : nextProps.referenceWorksQuery.referenceWorks;
		const works = nextProps.editionsQuery.loading ? [] : nextProps.editionsQuery.works
		this.setState({
			referenceWorks: referenceWorks,
			works: works,
			filters: createFilterFromURL(this.state.params, this.state.queryParams, this.state.works, this.props.referenceWorks)
		});
	}

	render() {
		const { tenantId } = this.props;
		const { skip, limit, queryParams, filters } = this.state;

		// create filters object based on the queryParams or params
		return (
			<MuiThemeProvider muiTheme={getMuiTheme(muiTheme)}>

						<CommentaryContainer
							filters={filters}
							toggleSearchTerm={this._toggleSearchTerm}
							showLoginModal={this.showLoginModal}
							loadMoreComments={this.loadMoreComments}
							tenantId={tenantId}
							skip={skip}
							limit={limit}
							queryParams={queryParams}
						/>

					<AuthModalContainer
						loginMethod={login}
						signupMethod={register}
						logoutMethod={logoutUser}
						getUserFromServer={verifyToken}
					/>

			</MuiThemeProvider>
		);
	}
}

CommentaryLayout.defaultProps = {
	queryParams: {},
};

CommentaryLayout.propTypes = {
	queryParams: PropTypes.object,
	referenceWorks: PropTypes.array,
	works: PropTypes.array,
	history: PropTypes.any,
	editionsQuery: PropTypes.object,
	referenceWorksQuery: PropTypes.object,
	match: PropTypes.object
};

const mapStateToProps = (state, props) => ({
	tenantId: state.tenant.tenantId,
});

export default compose(
	referenceWorksQuery,
	editionsQuery,
	connect(mapStateToProps),
)(CommentaryLayout);
<|endoftext|>


<commit_before>module('lively.ide.codeeditor.TextOverlay').requires('lively.DOMAbstraction').toRun(function() {

(function setupCSS() {
    var css = ".text-overlay {\n"
            + "    font-family: Monaco, monospace;\n"
            + "    font-size: 11px;\n"
            + "    position: absolute;\n"
            + "    color: white;\n"
            + "    background: darkviolet;\n"
            + "    padding: 1px;\n"
            + "    border-radius: 4px;\n"
            + "    box-shadow: 0px 0px 5px 3px rgb(160, 100, 210);\n"
         // + "    text-shadow: 0px 0px 5px rgba(0,0,200, 0.7);\n"
         // + "    text-shadow: 0px 0px 5px blue;\n"
         // + "    text-shadow: 0px 0px 5px white;\n"
            + "    white-space: pre;\n"
            + "}\n"
            + ".text-overlay.hidden {\n"
            + "    display: none;\n"
            + "}"
    XHTMLNS.addCSSDef(css, 'lively.ide.CodeEditorTextOverlay');
})();

Object.subclass("lively.ide.CodeEditorTextOverlay.Overlay",
"properties", {
    baseClassName: "text-overlay",
    overlays: null,
    id: null
},
"initializing", {
    initialize: function()  {
        this.overlays = [];
        this.$redraw = this.redraw.bind(this);
        this.$onDocumentChange = this.onDocumentChange.bind(this)
    },
    attach: function(session) {
        var isInstalled = this.id && this.id in session.$frontMarkers;
        if (isInstalled) this.detach(session);
        session.addDynamicMarker(this, true);
        session.on('change', this.$onDocumentChange);
        var overlays = this.overlays.clone();
        this.redraw(session);
    },
    detach: function(session) {
        var id = this.id;
        session.removeMarker(id);
        session.removeEventListener('change', this.$onDocumentChange);
        delete this.id;
    }
},
"updating", {
    onChange: function(evt, session) {
        this.redraw(session);
        lively.bindings.signal(this, 'changed');
    },
    onDocumentChange: function(evt, session) {
        this.onChange(evt,session);
    },
    update: function(html, markerLayer, session, config) {
        var startRow = config.firstRowScreen,
            endRow = config.lastRow,
            overlays = this.overlays || [],
            classNames = [this.baseClassName];
        overlays.forEach(function(overlay) {
            if (overlay.start.row < startRow || overlay.start.row > endRow) return;
            var x = config.padding + (config.characterWidth * overlay.start.column),
                y = config.lineHeight * (overlay.start.row-config.firstRowScreen),
                classes = classNames.concat(overlay.classNames).join(" ");
            html.pushAll([
                "",
                overlay.text,
                ""])
        });
    },
    redraw: function(session) {
        session._emit('changeFrontMarker');
    }
},
"accessing", {
    add: function(overlay, session) {
        if (!overlay.classNames) overlay.classNames = [];
        this.overlays.push(overlay);
        if (session.$textOverlay !== this) this.attach(session);
        this.onChange({type: 'overlayAdded', data: overlay}, session);
    },
    remove: function(overlay, session) {
        this.overlays.remove(overlay);
        this.onChange({type: 'overlayRemoved', data: overlay}, session);
    },
    removeAllOverlays: function(session) {
        this.overlays.clone().forEach(function(overlay) {
            this.remove(overlay, session); }, this);
    },
    getElements: function(editor) {
        return Array.from(editor.renderer.container.getElementsByClassName(this.baseClassName));
    }
});

(function extendCodeEditor() {
require('lively.ide.CodeEditor').toRun(function() {

    lively.morphic.CodeEditor.addMethods(
    'text overlay', {
        setupOverlaySupport: function(ed) {
            var session = ed.session;
            var $overlay = session.$textOverlay;
            if ($overlay) $overlay.detach(session)
            session.$textOverlay = new lively.ide.CodeEditorTextOverlay.Overlay()
            session.$textOverlay.attach(session);
            return session.$textOverlay;
        },

        withOverlaySupport: function(func) {
            this.withAceDo(function(ed) {
                func.call(this, ed.session.$textOverlay || this.setupOverlaySupport(ed), ed);
            });
        },

        addTextOverlay: function(overlay) {
            if (!this.getTextOverlaysEnabled()) return;
            this.withOverlaySupport(function($overlay, ed) {
                $overlay.add(overlay, ed.session); });
        },

        removeTextOverlay: function() {
            this.withOverlaySupport(function($overlay, ed) {
                $overlay.detach(ed.session);
                delete ed.session.$textOverlay;
            });
        },

        hideTextOverlays: function() {
            this.jQuery().find('.text-overlay').addClass('hidden');
        },

        unhideTextOverlays: function() {
            this.jQuery().find('.text-overlay').removeClass('hidden');
        },

        setTextOverlaysEnabled: function(bool) {
            if (!bool) this.removeTextOverlay();
            return this._TextOverlaysEnabled = bool;
        },
        getTextOverlaysEnabled: function() {
            return this._TextOverlaysEnabled === undefined || this._TextOverlaysEnabled;
        }
    });
});
})();

}) // end of module<commit_msg>codeeditor: command to switch overlays on/off now works better<commit_after>module('lively.ide.codeeditor.TextOverlay').requires('lively.DOMAbstraction').toRun(function() {

(function setupCSS() {
    var css = ".text-overlay {\n"
            + "    font-family: Monaco, monospace;\n"
            + "    font-size: 11px;\n"
            + "    position: absolute;\n"
            + "    color: white;\n"
            + "    background: darkviolet;\n"
            + "    padding: 1px;\n"
            + "    border-radius: 4px;\n"
            + "    box-shadow: 0px 0px 5px 3px rgb(160, 100, 210);\n"
         // + "    text-shadow: 0px 0px 5px rgba(0,0,200, 0.7);\n"
         // + "    text-shadow: 0px 0px 5px blue;\n"
         // + "    text-shadow: 0px 0px 5px white;\n"
            + "    white-space: pre;\n"
            + "}\n"
            + ".text-overlay.hidden {\n"
            + "    display: none;\n"
            + "}"
    XHTMLNS.addCSSDef(css, 'lively.ide.CodeEditorTextOverlay');
})();

Object.subclass("lively.ide.CodeEditorTextOverlay.Overlay",
"properties", {
    baseClassName: "text-overlay",
    overlays: null,
    id: null
},
"initializing", {
    initialize: function()  {
        this.overlays = [];
        this.$redraw = this.redraw.bind(this);
        this.$onDocumentChange = this.onDocumentChange.bind(this)
    },
    attach: function(session) {
        var isInstalled = this.id && this.id in session.$frontMarkers;
        if (isInstalled) this.detach(session);
        session.addDynamicMarker(this, true);
        session.on('change', this.$onDocumentChange);
        var overlays = this.overlays.clone();
        this.redraw(session);
    },
    detach: function(session) {
        var id = this.id;
        session.removeMarker(id);
        session.removeEventListener('change', this.$onDocumentChange);
        delete this.id;
    }
},
"updating", {
    onChange: function(evt, session) {
        this.redraw(session);
        lively.bindings.signal(this, 'changed');
    },
    onDocumentChange: function(evt, session) {
        this.onChange(evt,session);
    },
    update: function(html, markerLayer, session, config) {
        var startRow = config.firstRowScreen,
            endRow = config.lastRow,
            overlays = this.overlays || [],
            classNames = [this.baseClassName];
        overlays.forEach(function(overlay) {
            if (overlay.start.row < startRow || overlay.start.row > endRow) return;
            var x = config.padding + (config.characterWidth * overlay.start.column),
                y = config.lineHeight * (overlay.start.row-config.firstRowScreen),
                classes = classNames.concat(overlay.classNames).join(" ");
            html.pushAll([
                "",
                overlay.text,
                ""])
        });
    },
    redraw: function(session) {
        session._emit('changeFrontMarker');
    }
},
"accessing", {
    add: function(overlay, session) {
        if (!overlay.classNames) overlay.classNames = [];
        this.overlays.push(overlay);
        if (session.$textOverlay !== this) this.attach(session);
        this.onChange({type: 'overlayAdded', data: overlay}, session);
    },
    remove: function(overlay, session) {
        this.overlays.remove(overlay);
        this.onChange({type: 'overlayRemoved', data: overlay}, session);
    },
    removeAllOverlays: function(session) {
        this.overlays.clone().forEach(function(overlay) {
            this.remove(overlay, session); }, this);
    },
    getElements: function(editor) {
        return Array.from(editor.renderer.container.getElementsByClassName(this.baseClassName));
    }
});

(function extendCodeEditor() {
require('lively.ide.CodeEditor').toRun(function() {

    lively.morphic.CodeEditor.addMethods(
    'text overlay', {
        setupOverlaySupport: function(ed) {
            var session = ed.session;
            var $overlay = session.$textOverlay;
            if ($overlay) $overlay.detach(session)
            session.$textOverlay = new lively.ide.CodeEditorTextOverlay.Overlay()
            session.$textOverlay.attach(session);
            return session.$textOverlay;
        },

        withOverlaySupport: function(func) {
            this.withAceDo(function(ed) {
                func.call(this, ed.session.$textOverlay || this.setupOverlaySupport(ed), ed);
            });
        },

        addTextOverlay: function(overlay) {
            if (!this.getTextOverlaysEnabled()) return;
            this.withOverlaySupport(function($overlay, ed) {
                $overlay.add(overlay, ed.session); });
        },

        redrawTextOverlays: function() {
            this.withOverlaySupport(function(overlay, ed) {
                overlay.redraw(ed.session);
            });
        },
        removeTextOverlay: function() {
            this.withOverlaySupport(function($overlay, ed) {
                $overlay.detach(ed.session);
                delete ed.session.$textOverlay;
            });
        },

        hideTextOverlays: function() {
            this.jQuery().find('.text-overlay').addClass('hidden');
        },

        unhideTextOverlays: function() {
            this.jQuery().find('.text-overlay').removeClass('hidden');
        },

        setTextOverlaysEnabled: function(bool) {
            if (bool) this.textString += ''; // force redraw
            else this.removeTextOverlay();
            return this._TextOverlaysEnabled = bool;
        },
        getTextOverlaysEnabled: function() {
            return this._TextOverlaysEnabled === undefined || this._TextOverlaysEnabled;
        }
    });
});
})();

}) // end of module<|endoftext|>


<commit_before>import { types, getEnv } from 'mobx-state-tree';
import * as actionTypes from '../actionTypes';

export default types
  .model('Sticky')
  .props({
    isOpen: false,
    timeout: null,
    closedByUser: false,
  })
  .actions(self => {
    const { store, isClient } = getEnv(self);
    return {
      [actionTypes.STICKY_HAS_SHOWN]: ({ timeout }) => {
        self.isOpen = true;
        self.timeout = timeout;
      },
      [actionTypes.STICKY_HAS_HIDDEN]: () => {
        self.isOpen = false;
        self.timeout = null;
        self.closedByUser = true;
      },
      [actionTypes.STICKY_UPDATE_TIMEOUT]: ({ timeout }) => {
        self.timeout = timeout;
      },
      afterCreate: () => {
        if (isClient) {
          if (store)
            store.subscribe(() => {
              const action = store.getState().lastAction;

              if (self[action.type]) {
                self[action.type](action);
              }
            });
        }
      },
    };
  });
<commit_msg>Fixes in sticky's store<commit_after>import { types, getEnv } from 'mobx-state-tree';
import * as actionTypes from '../actionTypes';

export default types
  .model('Sticky')
  .props({
    isOpen: false,
    timeout: types.maybe(types.number),
    closedByUser: false,
  })
  .actions(self => {
    const { store, isClient } = getEnv(self);
    return {
      [actionTypes.STICKY_HAS_SHOWN]: ({ timeout }) => {
        self.isOpen = true;
        self.timeout = timeout;
      },
      [actionTypes.STICKY_HAS_HIDDEN]: ({ closedByUser }) => {
        self.isOpen = false;
        self.timeout = null;
        self.closedByUser = closedByUser;
      },
      [actionTypes.STICKY_UPDATE_TIMEOUT]: ({ timeout }) => {
        self.timeout = timeout;
      },
      afterCreate: () => {
        if (isClient) {
          if (store) {
            store.subscribe(() => {
              const action = store.getState().lastAction;

              if (self[action.type]) {
                self[action.type](action);
              }
            });
          }
        }
      },
    };
  });
<|endoftext|>


<commit_before>Hangout = new Meteor.Collection( 'hangout' );

let HangoutSchema = new SimpleSchema({
  "hangout_id": {
    type: Number,
    label: "The ID of the hangout/event."
  },
  "users": {
    type: [Number],
    label: "Array of users in the hangout."
  },
  "chat_id": {
  	type: [Number],
  	label: "Id of the chat associated with this hangout."
  },
  "time": {
    type: [Date],
    label: "Time of the hangout."
  },
  "location":  {
    type: Object,
    index: '2dsphere',
    label: 'Mongo 2dsphere coordinates'
  },
  'location.type': {
    type: String,
    allowedValues: ['Point'],
    label: 'Typeof coordinates - Point'
  },
  'location.coordinates': {
    type: [Number],
    decimal: true,
    label: 'Array of coordinates in MongoDB style\[Lng, Lat\]'
  }
});

Hangout.attachSchema( HangoutSchema );<commit_msg>fix chat id<commit_after>Hangout = new Meteor.Collection( 'hangout' );

let HangoutSchema = new SimpleSchema({
  "hangout_id": {
    type: Number,
    label: "The ID of the hangout/event."
  },
  "users": {
    type: [Number],
    label: "Array of users in the hangout."
  },
  "chat_id": {
  	type: Number,
  	label: "Id of the chat associated with this hangout."
  },
  "time": {
    type: [Date],
    label: "Time of the hangout."
  },
  "location":  {
    type: Object,
    index: '2dsphere',
    label: 'Mongo 2dsphere coordinates'
  },
  'location.type': {
    type: String,
    allowedValues: ['Point'],
    label: 'Typeof coordinates - Point'
  },
  'location.coordinates': {
    type: [Number],
    decimal: true,
    label: 'Array of coordinates in MongoDB style\[Lng, Lat\]'
  }
});

Hangout.attachSchema( HangoutSchema );<|endoftext|>


<commit_before>describe("Check webapp assign countries.", function() {
	var webappName = "WebAppCountriesApp",
		appCreated = undefined;

	var MAX_TIMEOUT = BCAPI.Config.MAX_TIMEOUT;

	function createApp() {
		var webapp = new BCAPI.Models.WebApp.App({"name": webappName});

		webapp.save({
			success: function(webapp) {
				webapp.fetch({
					success: function() {
						appCreated = webapp;
					}
				});
			}
		});
	}

    beforeEach(function() {
        BCAPI.Helper.Test.runTestServer();

        runs(createApp);

        waitsFor(function() {
        	return appCreated;
        }, "Webapp " + webappName + " not created correctly.", MAX_TIMEOUT);
    });

    afterEach(function() {
  		appCreated.destroy();
    });

	it("Check webapp countries update.", function() {
		var expectedCountries = ["RO", "US", "GB"];

		_checkEmptyCountries();
		_updateCountries(expectedCountries);
		_checkCountries(expectedCountries);
	});

	function _checkEmptyCountries() {
		var webappCountries = new BCAPI.Models.WebApp.Country(webappName),
			countriesRetrievedEmpty = false;

		runs(function() {
			webappCountries.fetch({
				success: function() {
					countriesRetrievedEmpty = true;
				}
			});
		});

		waitsFor(function() {
			return countriesRetrievedEmpty;
		}, "Webapp " + webappName + " countries not fetched correctly.", MAX_TIMEOUT);

		runs(function() {
			expect(webappCountries.get("items").length).toBe(0);
		});
	};

	function _updateCountries(expectedCountries) {
		var webappCountries = new BCAPI.Models.WebApp.Country(webappName, {"items": expectedCountries}),
			countriesUpdated = false;

		runs(function() {
			webappCountries.save({
				success: function() {
					countriesUpdated = true;
				}
			});
		});

		waitsFor(function() {
			return countriesUpdated;
		}, "Webapp " + webappName + " countries not updated correctly.", MAX_TIMEOUT);
	};

	function _checkCountries(expectedCountries) {
		var webappCountries = new BCAPI.Models.WebApp.Country(webappName),
			countriesFetched = undefined;

		runs(function() {
			webappCountries.fetch({
				success: function(countries) {
					countriesFetched = countries;
				}
			});
		});

		waitsFor(function() {
			return countriesFetched;
		}, "Webapp " + webappName + " countries not fetched correctly.", MAX_TIMEOUT);

		runs(function() {
			var idx = 0;

			_.each(countriesFetched.get("items"), function(item) {
				expect(expectedCountries[idx++]).toBe(item);
			});
		});
	};
});<commit_msg>I fixed the webapp country integration tests: now webapp is always deleted before creation.<commit_after>describe("Check webapp assign countries.", function() {
	var webappName = "WebAppCountriesApp",
		appCreated = undefined;

	var MAX_TIMEOUT = BCAPI.Config.MAX_TIMEOUT;

	function createApp() {
		var webapp = new BCAPI.Models.WebApp.App({"name": webappName});

		webapp.destroy().always(function() {
			webapp = new BCAPI.Models.WebApp.App({"name": webappName});

			webapp.save({
				success: function(webapp) {
					webapp.fetch({
						success: function() {
							appCreated = webapp;
						}
					});
				}
			});
		});
	}

    beforeEach(function() {
        BCAPI.Helper.Test.runTestServer();

        runs(createApp);

        waitsFor(function() {
        	return appCreated;
        }, "Webapp " + webappName + " not created correctly.", MAX_TIMEOUT);
    });

    afterEach(function() {
  		appCreated.destroy();
    });

	it("Check webapp countries update.", function() {
		var expectedCountries = ["RO", "US", "GB"];

		_checkEmptyCountries();
		_updateCountries(expectedCountries);
		_checkCountries(expectedCountries);
	});

	function _checkEmptyCountries() {
		var webappCountries = new BCAPI.Models.WebApp.Country(webappName),
			countriesRetrievedEmpty = false;

		runs(function() {
			webappCountries.fetch({
				success: function() {
					countriesRetrievedEmpty = true;
				}
			});
		});

		waitsFor(function() {
			return countriesRetrievedEmpty;
		}, "Webapp " + webappName + " countries not fetched correctly.", MAX_TIMEOUT);

		runs(function() {
			expect(webappCountries.get("items").length).toBe(0);
		});
	};

	function _updateCountries(expectedCountries) {
		var webappCountries = new BCAPI.Models.WebApp.Country(webappName, {"items": expectedCountries}),
			countriesUpdated = false;

		runs(function() {
			webappCountries.save({
				success: function() {
					countriesUpdated = true;
				}
			});
		});

		waitsFor(function() {
			return countriesUpdated;
		}, "Webapp " + webappName + " countries not updated correctly.", MAX_TIMEOUT);
	};

	function _checkCountries(expectedCountries) {
		var webappCountries = new BCAPI.Models.WebApp.Country(webappName),
			countriesFetched = undefined;

		runs(function() {
			webappCountries.fetch({
				success: function(countries) {
					countriesFetched = countries;
				}
			});
		});

		waitsFor(function() {
			return countriesFetched;
		}, "Webapp " + webappName + " countries not fetched correctly.", MAX_TIMEOUT);

		runs(function() {
			var idx = 0;

			_.each(countriesFetched.get("items"), function(item) {
				expect(expectedCountries[idx++]).toBe(item);
			});
		});
	};
});<|endoftext|>


<commit_before>import React, {Component} from 'react'
import Modal from '../Modal'

export default class State extends Component {
  render() {
    const redux = localStorage.getItem("redux")
    return(

            <button type="button" className="btn btn-danger" data-toggle="modal" data-target="#myModal">
              Nollställ tillståndet
            </button>
            <Modal title="Nollställ tillståndet" body="Nollställ kommer att rensa allt du har matat in någonsin" okLabel="Nollställ tillståndet" okAction={() => localStorage.removeItem('redux')}/>

Nuvarande tillstånd

            {redux}

    )
  }
}
<commit_msg>fixed state<commit_after>import React, {Component} from 'react'
import Modal from '../Modal'

export default class State extends Component {
  render() {
    const redux = JSON.parse(localStorage.getItem("redux"))
    return(

            <button type="button" className="btn btn-danger" data-toggle="modal" data-target="#myModal">
              Nollställ data
            </button>
            <Modal title="Nollställ data" body="Nollställ kommer att rensa allt data du har matat in någonsin" okLabel="Nollställ data" okAction={() => localStorage.removeItem('redux')}/>

Nuvarande data

              {JSON.stringify(redux, null, 2)}

    )
  }
}
<|endoftext|>