<commit_before>var chai = require('chai')
  , expect = require('chai').expect
  , sinon = require('sinon')
  , Dispatcher = require('../../lib/manager');

describe('Dispatcher#flow', function() {

  describe('resuming parent state from stored child state', function() {

    var request, response, err;
    before(function(done) {
      var dispatcher = new Dispatcher();

      dispatcher.use('foo', null, [
        function(req, res, next) {
          res.__text += ' ' + req.state.name + '(' + req.yieldState.name + ')';
          res.end(res.__text);
        },
        function(err, req, res, next) {
          res.__text += ' E:' + req.state.name + '(' + req.yieldState.name + ')';
          res.end(res.__text);
        }
      ]);

      function handler(req, res, next) {
        console.log(req.state)

        res.__text = req.state.name;
        next();
      }

      chai.express.handler(dispatcher.flow('bar', handler))
        .req(function(req) {
          request = req;
          request.body = { state: 'H2' };
          request.session = { state: {} };
          request.session.state['H1'] = { name: 'foo', x: 1 };
          request.session.state['H2'] = { name: 'bar', y: 2, prev: 'H1' };
        })
        .res(function(res) {
          //res.__text = 'bar'
        })
        .end(function(res) {
          response = res;
          done();
        })
        .dispatch();
    });

    it('should set state', function() {
      expect(request.state).to.be.an('object');
      expect(request.state).to.deep.equal({
        handle: 'H1',
        name: 'foo',
        x: 1
      });
    });

    it('should set yieldState', function() {
      expect(request.yieldState).to.be.an('object');
      expect(request.yieldState).to.deep.equal({
        handle: 'H2',
        name: 'bar',
        y: 2,
        prev: 'H1'
      });
    });

    it('should remove state from session', function() {
      expect(request.session).to.deep.equal({
        state: {
          'H1': {
            name: 'foo',
            x: 1
          }
        }
      });
    });

    it('should respond', function() {
      expect(response._data).to.equal('bar foo(bar)');
    });
  }); // resuming parent state from loaded, named state

  describe('resuming parent state after transition from loaded, named state', function() {

    var request, response, err;
    before(function(done) {
      var dispatcher = new Dispatcher();

      dispatcher.use('foo', null, [
        function(req, res, next) {
          res.__text += ' ' + req.state.name + '(' + req.yieldState.name + ')';
          res.end(res.__text);
        },
        function(err, req, res, next) {
          res.__text += ' E:' + req.state.name + '(' + req.yieldState.name + ')';
          res.end(res.__text);
        }
      ]);

      dispatcher.transition('foo', 'bar', [
        function(req, res, next) {
          req.state.y = req.yieldState.y;
          res.__text += ' --' + req.yieldState.name + '/' + req.state.name + '-->';
          next();
        },
        function(err, req, res, next) {
          res.__text += ' --E:' + req.yieldState.name + '/' + req.state.name + '-->';
          next();
        }
      ]);

      chai.express.handler(dispatcher.flow())
        .req(function(req) {
          request = req;
          request.state = { handle: '22345678', name: 'bar', y: 2, prev: '12345678' };
          request.session = { state: {} };
          request.session.state['12345678'] = { name: 'foo', x: 1 };
          request.session.state['22345678'] = { name: 'bar', y: 2, prev: '12345678' };
        })
        .res(function(res) {
          res.__text = 'bar'
        })
        .end(function(res) {
          response = res;
          done();
        })
        .dispatch();
    });

    it('should set state', function() {
      expect(request.state).to.be.an('object');
      expect(request.state).to.deep.equal({
        handle: '12345678',
        name: 'foo',
        x: 1,
        y: 2
      });
    });

    it('should set yieldState', function() {
      expect(request.yieldState).to.be.an('object');
      expect(request.yieldState).to.deep.equal({
        handle: '22345678',
        name: 'bar',
        y: 2,
        prev: '12345678'
      });
    });

    it('should remove state from session', function() {
      expect(request.session).to.deep.equal({
        state: {
          '12345678': {
            name: 'foo',
            x: 1
          }
        }
      });
    });

    it('should respond', function() {
      expect(response._data).to.equal('bar --bar/foo--> foo(bar)');
    });
  }); // resuming parent state after transition from loaded, named state

  describe('resuming parent state after transition through synthesized state with transition from specified, loaded, named state', function() {

    var request, response, err;
    before(function(done) {
      var dispatcher = new Dispatcher();

      // foo
      dispatcher.use('foo', null, [
        function(req, res, next) {
          res.__text += ' ' + req.state.name + '(' + req.yieldState.name + ')';
          res.end(res.__text);
        },
        function(err, req, res, next) {
          res.__text += ' E:' + req.state.name + '(' + req.yieldState.name + ')';
          res.end(res.__text);
        }
      ]);

      dispatcher.transition('foo', 'bar', [
        function(req, res, next) {
          req.state.y = req.yieldState.y;
          req.state.z = req.yieldState.z;
          res.__text += ' --' + req.yieldState.name + '/' + req.state.name + '-->';
          next();
        },
        function(err, req, res, next) {
          res.__text += ' --E:' + req.yieldState.name + '/' + req.state.name + '-->';
          next();
        }
      ]);

      // bar
      dispatcher.use('bar', null, [
        function(req, res, next) {
          res.__text += ' ' + req.state.name + '(' + req.yieldState.name + ')';
          res.completePrompt();
        },
        function(err, req, res, next) {
          res.__text += ' E:' + req.state.name + '(' + req.yieldState.name + ')';
          res.completePrompt(err);
        }
      ]);

      dispatcher.transition('bar', 'baz', [
        function(req, res, next) {
          req.state.z = req.yieldState.z;
          res.__text += ' --' + req.yieldState.name + '/' + req.state.name + '-->';
          next();
        },
        function(err, req, res, next) {
          res.__text += ' --E:' + req.yieldState.name + '/' + req.state.name + '-->';
          next();
        }
      ]);

      chai.express.handler(dispatcher.flow('baz', { through: 'bar' }))
        .req(function(req) {
          request = req;
          request.state = { handle: '22345678', name: 'baz', z: 3, prev: '12345678' };
          request.session = { state: {} };
          request.session.state['12345678'] = { name: 'foo', x: 1 };
          request.session.state['22345678'] = { name: 'baz', z: 3, prev: '12345678' };
        })
        .res(function(res) {
          res.__text = 'baz'
        })
        .end(function(res) {
          response = res;
          done();
        })
        .next(function(err) {
          console.log(err);
          done(err);
        })
        .dispatch();
    });

    it('should set state', function() {
      expect(request.state).to.be.an('object');
      expect(request.state).to.deep.equal({
        handle: '12345678',
        name: 'foo',
        x: 1,
        y: undefined,
        z: 3
      });
    });

    it('should set yieldState', function() {
      expect(request.yieldState).to.be.an('object');
      expect(request.yieldState).to.deep.equal({
        name: 'bar',
        z: 3,
        prev: '12345678'
      });
    });

    it('should remove state from session', function() {
      expect(request.session).to.deep.equal({
        state: {
          '12345678': {
            name: 'foo',
            x: 1
          }
        }
      });
    });

    it('should respond', function() {
      expect(response._data).to.equal('baz --baz/bar--> bar(baz) --bar/foo--> foo(bar)');
    });
  }); // resuming parent state after transition through synthesized state with transition from specified, loaded, named state

  describe('resuming parent state after transition through synthesized state without transition from specified, loaded, named state', function() {

    var request, response, err;
    before(function(done) {
      var dispatcher = new Dispatcher();

      // foo
      dispatcher.use('foo', null, [
        function(req, res, next) {
          res.__text += ' ' + req.state.name + '(' + req.yieldState.name + ')';
          res.end(res.__text);
        },
        function(err, req, res, next) {
          res.__text += ' E:' + req.state.name + '(' + req.yieldState.name + ')';
          res.end(res.__text);
        }
      ]);

      dispatcher.transition('foo', 'bar', [
        function(req, res, next) {
          req.state.y = req.yieldState.y;
          req.state.z = req.yieldState.z;
          res.__text += ' --' + req.yieldState.name + '/' + req.state.name + '-->';
          next();
        },
        function(err, req, res, next) {
          res.__text += ' --E:' + req.yieldState.name + '/' + req.state.name + '-->';
          next();
        }
      ]);

      // bar
      dispatcher.use('bar', null, [
        function(req, res, next) {
          res.__text += ' ' + req.state.name + '(' + req.yieldState.name + ')';
          res.completePrompt();
        },
        function(err, req, res, next) {
          res.__text += ' E:' + req.state.name + '(' + req.yieldState.name + ')';
          res.completePrompt(err);
        }
      ]);

      chai.express.handler(dispatcher.flow('baz', { through: 'bar' }))
        .req(function(req) {
          request = req;
          request.state = { handle: '22345678', name: 'baz', z: 3, prev: '12345678' };
          request.session = { state: {} };
          request.session.state['12345678'] = { name: 'foo', x: 1 };
          request.session.state['22345678'] = { name: 'baz', z: 3, prev: '12345678' };
        })
        .res(function(res) {
          res.__text = 'baz'
        })
        .end(function(res) {
          response = res;
          done();
        })
        .next(function(err) {
          console.log(err);
          done(err);
        })
        .dispatch();
    });

    it('should set state', function() {
      expect(request.state).to.be.an('object');
      expect(request.state).to.deep.equal({
        handle: '12345678',
        name: 'foo',
        x: 1,
        y: undefined,
        z: undefined
      });
    });

    it('should set yieldState', function() {
      expect(request.yieldState).to.be.an('object');
      expect(request.yieldState).to.deep.equal({
        name: 'bar',
        prev: '12345678'
      });
    });

    it('should remove state from session', function() {
      expect(request.session).to.deep.equal({
        state: {
          '12345678': {
            name: 'foo',
            x: 1
          }
        }
      });
    });

    it('should respond', function() {
      expect(response._data).to.equal('baz bar(baz) --bar/foo--> foo(bar)');
    });
  }); // resuming parent state after transition through synthesized state without transition from specified, loaded, named state

  // THIS IS AN ERROR SOMEWHERE
  describe.skip('resuming parent state after transition through synthesized state from loaded, named state', function() {

    var request, response, err;
    before(function(done) {
      var dispatcher = new Dispatcher();

      dispatcher.use('foo', null, [
        function(req, res, next) {
          if (req.state.name !== 'foo') { return next(new Error('incorrect state')); }
          if (req.yieldState.name !== 'bar') { return next(new Error('incorrect yield state')); }

          res.__text += 'foo';
          res.end(res.__text);
        },
        function(err, req, res, next) {
          if (req.state.name !== 'foo') { return next(new Error('incorrect state')); }
          if (req.yieldState.name !== 'bar') { return next(new Error('incorrect yield state')); }

          res.__text += 'EFOO';
          res.end(res.__text);
        }
      ]);

      dispatcher.transition('foo', 'bar', [
        function(req, res, next) {
          if (req.state.name !== 'foo') { return next(new Error('incorrect state')); }
          if (req.yieldState.name !== 'bar') { return next(new Error('incorrect yield state')); }

          req.state.y = req.yieldState.y;
          res.__text += ' --bar/foo--> ';
          next();
        },
        function(err, req, res, next) {
          if (req.state.name !== 'foo') { return next(new Error('incorrect state')); }
          if (req.yieldState.name !== 'bar') { return next(new Error('incorrect yield state')); }

          res.__text += ' --EBAR/EFOO--> ';
          next();
        }
      ]);

      chai.express.handler(dispatcher.flow())
        .req(function(req) {
          request = req;
          request.state = { handle: '22345678', name: 'baz', z: 3, prev: '12345678' };
          request.session = { state: {} };
          request.session.state['12345678'] = { name: 'foo', x: 1 };
          request.session.state['22345678'] = { name: 'baz', z: 3, prev: '12345678' };
        })
        .res(function(res) {
          res.__text = 'bar'
        })
        .end(function(res) {
          response = res;
          done();
        })
        .dispatch();
    });

    it('should set state', function() {
      expect(request.state).to.be.an('object');
      expect(request.state).to.deep.equal({
        handle: '12345678',
        name: 'foo',
        x: 1,
        y: 2
      });
    });

    it('should set yieldState', function() {
      expect(request.yieldState).to.be.an('object');
      expect(request.yieldState).to.deep.equal({
        handle: '22345678',
        name: 'bar',
        y: 2,
        prev: '12345678'
      });
    });

    it('should remove state from session', function() {
      expect(request.session).to.deep.equal({
        state: {
          '12345678': {
            name: 'foo',
            x: 1
          }
        }
      });
    });

    it('should respond', function() {
      expect(response._data).to.equal('bar --bar/foo--> foo');
    });
  }); // resuming parent state after transition through synthesized state from loaded, named state

});
<commit_msg>Update tests.<commit_after>var chai = require('chai')
  , expect = require('chai').expect
  , sinon = require('sinon')
  , Dispatcher = require('../../lib/manager');

describe('Dispatcher#flow', function() {

  describe('resuming parent state from stored child state', function() {

    var request, response, err;
    before(function(done) {
      var dispatcher = new Dispatcher();

      dispatcher.use('foo', null, [
        function(req, res, next) {
          res.__text += ' ' + req.state.name + '(' + req.yieldState.name + ')';
          res.end(res.__text);
        },
        function(err, req, res, next) {
          res.__text += ' E:' + req.state.name + '(' + req.yieldState.name + ')';
          res.end(res.__text);
        }
      ]);

      function handler(req, res, next) {
        res.__text = req.state.name;
        next();
      }

      chai.express.handler(dispatcher.flow('bar', handler))
        .req(function(req) {
          request = req;
          request.body = { state: 'H2' };
          request.session = { state: {} };
          request.session.state['H1'] = { name: 'foo', x: 1 };
          request.session.state['H2'] = { name: 'bar', y: 2, prev: 'H1' };
        })
        .end(function(res) {
          response = res;
          done();
        })
        .dispatch();
    });

    it('should set state', function() {
      expect(request.state).to.be.an('object');
      expect(request.state).to.deep.equal({
        handle: 'H1',
        name: 'foo',
        x: 1
      });
    });

    it('should set yieldState', function() {
      expect(request.yieldState).to.be.an('object');
      expect(request.yieldState).to.deep.equal({
        handle: 'H2',
        name: 'bar',
        y: 2,
        prev: 'H1'
      });
    });

    it('should remove state from session', function() {
      expect(request.session).to.deep.equal({
        state: {
          'H1': {
            name: 'foo',
            x: 1
          }
        }
      });
    });

    it('should respond', function() {
      expect(response._data).to.equal('bar foo(bar)');
    });
  }); // resuming parent state from stored child state

  describe('resuming parent state after transition from stored child state', function() {

    var request, response, err;
    before(function(done) {
      var dispatcher = new Dispatcher();

      dispatcher.use('foo', null, [
        function(req, res, next) {
          res.__text += ' ' + req.state.name + '(' + req.yieldState.name + ')';
          res.end(res.__text);
        },
        function(err, req, res, next) {
          res.__text += ' E:' + req.state.name + '(' + req.yieldState.name + ')';
          res.end(res.__text);
        }
      ]);

      dispatcher.transition('foo', 'bar', [
        function(req, res, next) {
          req.state.y = req.yieldState.y;
          res.__text += ' --' + req.yieldState.name + '/' + req.state.name + '-->';
          next();
        },
        function(err, req, res, next) {
          res.__text += ' --E:' + req.yieldState.name + '/' + req.state.name + '-->';
          next();
        }
      ]);

      function handler(req, res, next) {
        res.__text = req.state.name;
        next();
      }

      chai.express.handler(dispatcher.flow('bar', handler))
        .req(function(req) {
          request = req;
          request.body = { state: 'H2' };
          request.session = { state: {} };
          request.session.state['H1'] = { name: 'foo', x: 1 };
          request.session.state['H2'] = { name: 'bar', y: 2, prev: 'H1' };
        })
        .end(function(res) {
          response = res;
          done();
        })
        .dispatch();
    });

    it('should set state', function() {
      expect(request.state).to.be.an('object');
      expect(request.state).to.deep.equal({
        handle: 'H1',
        name: 'foo',
        x: 1,
        y: 2
      });
    });

    it('should set yieldState', function() {
      expect(request.yieldState).to.be.an('object');
      expect(request.yieldState).to.deep.equal({
        handle: 'H2',
        name: 'bar',
        y: 2,
        prev: 'H1'
      });
    });

    it('should remove state from session', function() {
      expect(request.session).to.deep.equal({
        state: {
          'H1': {
            name: 'foo',
            x: 1
          }
        }
      });
    });

    it('should respond', function() {
      expect(response._data).to.equal('bar --bar/foo--> foo(bar)');
    });
  }); // resuming parent state after transition from stored child state

  describe('resuming parent state after transition through synthesized state with transition from specified, loaded, named state', function() {

    var request, response, err;
    before(function(done) {
      var dispatcher = new Dispatcher();

      // foo
      dispatcher.use('foo', null, [
        function(req, res, next) {
          res.__text += ' ' + req.state.name + '(' + req.yieldState.name + ')';
          res.end(res.__text);
        },
        function(err, req, res, next) {
          res.__text += ' E:' + req.state.name + '(' + req.yieldState.name + ')';
          res.end(res.__text);
        }
      ]);

      dispatcher.transition('foo', 'bar', [
        function(req, res, next) {
          req.state.y = req.yieldState.y;
          req.state.z = req.yieldState.z;
          res.__text += ' --' + req.yieldState.name + '/' + req.state.name + '-->';
          next();
        },
        function(err, req, res, next) {
          res.__text += ' --E:' + req.yieldState.name + '/' + req.state.name + '-->';
          next();
        }
      ]);

      // bar
      dispatcher.use('bar', null, [
        function(req, res, next) {
          res.__text += ' ' + req.state.name + '(' + req.yieldState.name + ')';
          res.completePrompt();
        },
        function(err, req, res, next) {
          res.__text += ' E:' + req.state.name + '(' + req.yieldState.name + ')';
          res.completePrompt(err);
        }
      ]);

      dispatcher.transition('bar', 'baz', [
        function(req, res, next) {
          req.state.z = req.yieldState.z;
          res.__text += ' --' + req.yieldState.name + '/' + req.state.name + '-->';
          next();
        },
        function(err, req, res, next) {
          res.__text += ' --E:' + req.yieldState.name + '/' + req.state.name + '-->';
          next();
        }
      ]);

      chai.express.handler(dispatcher.flow('baz', { through: 'bar' }))
        .req(function(req) {
          request = req;
          request.state = { handle: '22345678', name: 'baz', z: 3, prev: '12345678' };
          request.session = { state: {} };
          request.session.state['12345678'] = { name: 'foo', x: 1 };
          request.session.state['22345678'] = { name: 'baz', z: 3, prev: '12345678' };
        })
        .res(function(res) {
          res.__text = 'baz'
        })
        .end(function(res) {
          response = res;
          done();
        })
        .next(function(err) {
          console.log(err);
          done(err);
        })
        .dispatch();
    });

    it('should set state', function() {
      expect(request.state).to.be.an('object');
      expect(request.state).to.deep.equal({
        handle: '12345678',
        name: 'foo',
        x: 1,
        y: undefined,
        z: 3
      });
    });

    it('should set yieldState', function() {
      expect(request.yieldState).to.be.an('object');
      expect(request.yieldState).to.deep.equal({
        name: 'bar',
        z: 3,
        prev: '12345678'
      });
    });

    it('should remove state from session', function() {
      expect(request.session).to.deep.equal({
        state: {
          '12345678': {
            name: 'foo',
            x: 1
          }
        }
      });
    });

    it('should respond', function() {
      expect(response._data).to.equal('baz --baz/bar--> bar(baz) --bar/foo--> foo(bar)');
    });
  }); // resuming parent state after transition through synthesized state with transition from specified, loaded, named state

  describe('resuming parent state after transition through synthesized state without transition from specified, loaded, named state', function() {

    var request, response, err;
    before(function(done) {
      var dispatcher = new Dispatcher();

      // foo
      dispatcher.use('foo', null, [
        function(req, res, next) {
          res.__text += ' ' + req.state.name + '(' + req.yieldState.name + ')';
          res.end(res.__text);
        },
        function(err, req, res, next) {
          res.__text += ' E:' + req.state.name + '(' + req.yieldState.name + ')';
          res.end(res.__text);
        }
      ]);

      dispatcher.transition('foo', 'bar', [
        function(req, res, next) {
          req.state.y = req.yieldState.y;
          req.state.z = req.yieldState.z;
          res.__text += ' --' + req.yieldState.name + '/' + req.state.name + '-->';
          next();
        },
        function(err, req, res, next) {
          res.__text += ' --E:' + req.yieldState.name + '/' + req.state.name + '-->';
          next();
        }
      ]);

      // bar
      dispatcher.use('bar', null, [
        function(req, res, next) {
          res.__text += ' ' + req.state.name + '(' + req.yieldState.name + ')';
          res.completePrompt();
        },
        function(err, req, res, next) {
          res.__text += ' E:' + req.state.name + '(' + req.yieldState.name + ')';
          res.completePrompt(err);
        }
      ]);

      chai.express.handler(dispatcher.flow('baz', { through: 'bar' }))
        .req(function(req) {
          request = req;
          request.state = { handle: '22345678', name: 'baz', z: 3, prev: '12345678' };
          request.session = { state: {} };
          request.session.state['12345678'] = { name: 'foo', x: 1 };
          request.session.state['22345678'] = { name: 'baz', z: 3, prev: '12345678' };
        })
        .res(function(res) {
          res.__text = 'baz'
        })
        .end(function(res) {
          response = res;
          done();
        })
        .next(function(err) {
          console.log(err);
          done(err);
        })
        .dispatch();
    });

    it('should set state', function() {
      expect(request.state).to.be.an('object');
      expect(request.state).to.deep.equal({
        handle: '12345678',
        name: 'foo',
        x: 1,
        y: undefined,
        z: undefined
      });
    });

    it('should set yieldState', function() {
      expect(request.yieldState).to.be.an('object');
      expect(request.yieldState).to.deep.equal({
        name: 'bar',
        prev: '12345678'
      });
    });

    it('should remove state from session', function() {
      expect(request.session).to.deep.equal({
        state: {
          '12345678': {
            name: 'foo',
            x: 1
          }
        }
      });
    });

    it('should respond', function() {
      expect(response._data).to.equal('baz bar(baz) --bar/foo--> foo(bar)');
    });
  }); // resuming parent state after transition through synthesized state without transition from specified, loaded, named state

  // THIS IS AN ERROR SOMEWHERE
  describe.skip('resuming parent state after transition through synthesized state from loaded, named state', function() {

    var request, response, err;
    before(function(done) {
      var dispatcher = new Dispatcher();

      dispatcher.use('foo', null, [
        function(req, res, next) {
          if (req.state.name !== 'foo') { return next(new Error('incorrect state')); }
          if (req.yieldState.name !== 'bar') { return next(new Error('incorrect yield state')); }

          res.__text += 'foo';
          res.end(res.__text);
        },
        function(err, req, res, next) {
          if (req.state.name !== 'foo') { return next(new Error('incorrect state')); }
          if (req.yieldState.name !== 'bar') { return next(new Error('incorrect yield state')); }

          res.__text += 'EFOO';
          res.end(res.__text);
        }
      ]);

      dispatcher.transition('foo', 'bar', [
        function(req, res, next) {
          if (req.state.name !== 'foo') { return next(new Error('incorrect state')); }
          if (req.yieldState.name !== 'bar') { return next(new Error('incorrect yield state')); }

          req.state.y = req.yieldState.y;
          res.__text += ' --bar/foo--> ';
          next();
        },
        function(err, req, res, next) {
          if (req.state.name !== 'foo') { return next(new Error('incorrect state')); }
          if (req.yieldState.name !== 'bar') { return next(new Error('incorrect yield state')); }

          res.__text += ' --EBAR/EFOO--> ';
          next();
        }
      ]);

      chai.express.handler(dispatcher.flow())
        .req(function(req) {
          request = req;
          request.state = { handle: '22345678', name: 'baz', z: 3, prev: '12345678' };
          request.session = { state: {} };
          request.session.state['12345678'] = { name: 'foo', x: 1 };
          request.session.state['22345678'] = { name: 'baz', z: 3, prev: '12345678' };
        })
        .res(function(res) {
          res.__text = 'bar'
        })
        .end(function(res) {
          response = res;
          done();
        })
        .dispatch();
    });

    it('should set state', function() {
      expect(request.state).to.be.an('object');
      expect(request.state).to.deep.equal({
        handle: '12345678',
        name: 'foo',
        x: 1,
        y: 2
      });
    });

    it('should set yieldState', function() {
      expect(request.yieldState).to.be.an('object');
      expect(request.yieldState).to.deep.equal({
        handle: '22345678',
        name: 'bar',
        y: 2,
        prev: '12345678'
      });
    });

    it('should remove state from session', function() {
      expect(request.session).to.deep.equal({
        state: {
          '12345678': {
            name: 'foo',
            x: 1
          }
        }
      });
    });

    it('should respond', function() {
      expect(response._data).to.equal('bar --bar/foo--> foo');
    });
  }); // resuming parent state after transition through synthesized state from loaded, named state

});
<|endoftext|>


<commit_before><commit_msg>Modernize datalist<commit_after><|endoftext|>


<commit_before>'use strict';

var mongoose = require('mongoose'),
    restify = require('restify'),
    Promise = require('bluebird'),
    aclManager = require('../lib/auth/acl-manager'),
    rHandler = require('../lib/util/response-handlers');

class CommonController {
    constructor() {

        function deleteProtected(req) {
            delete req.body.region_uuid;
            delete req.body.user_uuid;
            delete req.body.legacy_id;
        }

        this.coroutines = {
            findResource: {
                main: Promise.coroutine(function* (req, res, next, config) {
                    if (req.params.uuid === 'me' && req.user) {
                        req.params.uuid = req.user.uuid;
                    }
                    let query = require('../lib/util/query-mapping')({}, req, config);

                    let paths = mongoose.model(config.resource).schema.paths;
                    if (paths.hasOwnProperty('hidden')) {
                        query.hidden = false;
                    }

                    let limit = Math.abs(parseInt(req.query.limit) || 5),
                        skip = Math.abs(parseInt(req.query.skip) || 0),
                        q = mongoose.model(config.resource).find(query);

                    q = config.select ? q.select(config.select) : q;
                    q = req.query.skip ? q.skip(skip) : q;
                    q = req.query.limit ? q.limit(limit) : q;
                    q = req.query.sort ? q.sort(req.query.sort) : q;

                    var data = {page: Math.floor(skip / limit), pagesize: limit},
                        results = yield q.exec();
                    data.total = yield mongoose.model(config.resource).count(q._conditions);

                    data.results = yield Promise.map(results, Promise.coroutine(function* (result) {
                        result = result.toObject();
                        if (result.user_uuid) {
                            result.user = yield mongoose.model('User').findOne({uuid: result.user_uuid})
                                .select('uuid nickname').exec();
                            result.user = result.user ? result.user.toObject() : undefined;
                        }
                        if (result.subject_uuid) {
                            result.location = yield mongoose.model('Location')
                                .findOne({uuid:result.subject_uuid})
                                .select('uuid title city').exec();
                            result.location = result.location ? result.location.toObject() : undefined;
                        }
                        return result;
                    }));

                    rHandler.handleDataResponse(data, 200, res, next);
                }),
                pre: Promise.resolve
            },
            getResource: {
                main: Promise.coroutine(function* (req, res, next, config) {
                    let query = {$or: [{uuid: req.params.uuid}, {slug: req.params.uuid.toLowerCase()}]},
                        paths = mongoose.model(config.resource).schema.paths,
                        q = mongoose.model(config.resource).findOne(query);
                    q = config.select ? q.select(config.select) : q;
                    let result = yield q.exec();
                    if (!result) {
                        return rHandler.handleErrorResponse(new restify.NotFoundError(), res, next);
                    }
                    result = result.toObject();
                    if (paths.hasOwnProperty('hidden') && result.hidden) {
                        let region = yield mongoose.model('Region').findOne({uuid:result.region_uuid});
                        if (!region) {
                            return rHandler.handleErrorResponse(new restify.NotFoundError(), res, next);
                        }
                        // TODO: put this in lib
                        let isAdmin = req.api_key && (
                                req.api_key.scopes.indexOf('admin') ||
                                req.api_key.scopes.indexOf('region-' + region.uuid)
                            );
                        if (!isAdmin) {
                            return rHandler.handleErrorResponse(new restify.NotFoundError(), res, next);
                        }
                    }
                    if (result && result.user_uuid) {
                        result.user = yield mongoose.model('User')
                            .findOne({uuid:result.user_uuid})
                            .select('uuid nickname').exec();
                        result.user = result.user ? result.user.toObject() : undefined;
                    }
                    if (result && result.subject_uuid) {
                        result.location = yield mongoose.model('Location')
                            .findOne({uuid:result.subject_uuid})
                            .select('uuid title city').exec();
                        result.location = result.location ? result.location.toObject() : undefined;
                    }
                    rHandler.handleDataResponse(result, 200, res, next);
                }),
                pre: Promise.resolve
            },
            postResource: {
                main: Promise.coroutine(function* (req, res, next, config) {
                    if (req.user && req.user.uuid && !req.body.user_uuid) req.body.user_uuid = req.user.uuid;
                    let defaultAcl = [req.user.uuid, 'admin'];
                    if (req.body.hasOwnProperty('region_uuid')) {
                        let region = yield mongoose.model('Region').findOne({uuid: req.body.region_uuid});
                        if (region) {
                            req.body.hidden = region.moderate || false;
                            defaultAcl = defaultAcl.concat(['region-' + region.uuid]);
                        }
                    }
                    let result = yield mongoose.model(config.resource).create(req.body);
                    yield aclManager.setAclEntry(
                        req.url + '/' + result.uuid,
                        defaultAcl,
                        ['get', 'put', 'delete']
                    );
                    yield aclManager.setAclEntry(req.url + '/' + result.uuid, ['user'], ['get']);
                    rHandler.handleDataResponse(result, 201, res, next);
                }),
                pre: Promise.resolve
            },
            putResource: {
                main: Promise.coroutine(function* (req, res, next, config) {
                    deleteProtected(req);
                    let data = yield mongoose.model(config.resource).findOne({uuid: req.params.uuid}).exec();
                    if (data) {
                        for (var key in req.body) {
                            data[key] = req.body[key];
                        }
                        yield data.save();
                        rHandler.handleDataResponse(data, 200, res, next);
                    } else {
                        rHandler.handleErrorResponse(new restify.NotFoundError(), res, next);
                    }
                }),
                pre: Promise.resolve
            },
            deleteResource: {
                main: Promise.coroutine(function* (req, res, next, config) {
                    let result = yield mongoose.model(config.resource).findOneAndRemove({uuid: req.params.uuid});
                    if (result) {
                        yield aclManager.removeAclEntry(req.url, req.user.uuid, '*');
                        yield aclManager.removeAclEntry(req.url, 'admin', '*');
                        yield aclManager.removeAclEntry(req.url, 'user', '*');
                        rHandler.handleDataResponse(result, 200, res, next);
                    } else {
                        rHandler.handleErrorResponse(new restify.NotFoundError(), res, next);
                    }
                }),
                pre: Promise.resolve
            }
        };
    }

    map(verb, config) {
        let instance = this;
        return function executeRequest(req, res, next) {
            return Promise.resolve()
                .then(() => {
                    return instance.coroutines[`${verb}Resource`].pre(req, res, next, config);
                })
                .then(() => {
                    return instance.coroutines[`${verb}Resource`].main(req, res, next, config);
                })
                .catch(err => {
                    rHandler.handleErrorResponse(err, res, next);
                });
        };
    }
}

module.exports = CommonController;<commit_msg>Fix: hidden locations can be seen by normal users.... -1 is NOT false<commit_after>'use strict';

var mongoose = require('mongoose'),
    restify = require('restify'),
    Promise = require('bluebird'),
    aclManager = require('../lib/auth/acl-manager'),
    rHandler = require('../lib/util/response-handlers');

class CommonController {
    constructor() {

        function deleteProtected(req) {
            delete req.body.region_uuid;
            delete req.body.user_uuid;
            delete req.body.legacy_id;
        }

        this.coroutines = {
            findResource: {
                main: Promise.coroutine(function* (req, res, next, config) {
                    if (req.params.uuid === 'me' && req.user) {
                        req.params.uuid = req.user.uuid;
                    }
                    let query = require('../lib/util/query-mapping')({}, req, config);

                    let paths = mongoose.model(config.resource).schema.paths;
                    if (paths.hasOwnProperty('hidden')) {
                        query.hidden = false;
                    }

                    let limit = Math.abs(parseInt(req.query.limit) || 5),
                        skip = Math.abs(parseInt(req.query.skip) || 0),
                        q = mongoose.model(config.resource).find(query);

                    q = config.select ? q.select(config.select) : q;
                    q = req.query.skip ? q.skip(skip) : q;
                    q = req.query.limit ? q.limit(limit) : q;
                    q = req.query.sort ? q.sort(req.query.sort) : q;

                    var data = {page: Math.floor(skip / limit), pagesize: limit},
                        results = yield q.exec();
                    data.total = yield mongoose.model(config.resource).count(q._conditions);

                    data.results = yield Promise.map(results, Promise.coroutine(function* (result) {
                        result = result.toObject();
                        if (result.user_uuid) {
                            result.user = yield mongoose.model('User').findOne({uuid: result.user_uuid})
                                .select('uuid nickname').exec();
                            result.user = result.user ? result.user.toObject() : undefined;
                        }
                        if (result.subject_uuid) {
                            result.location = yield mongoose.model('Location')
                                .findOne({uuid:result.subject_uuid})
                                .select('uuid title city').exec();
                            result.location = result.location ? result.location.toObject() : undefined;
                        }
                        return result;
                    }));

                    rHandler.handleDataResponse(data, 200, res, next);
                }),
                pre: Promise.resolve
            },
            getResource: {
                main: Promise.coroutine(function* (req, res, next, config) {
                    let query = {$or: [{uuid: req.params.uuid}, {slug: req.params.uuid.toLowerCase()}]},
                        paths = mongoose.model(config.resource).schema.paths,
                        q = mongoose.model(config.resource).findOne(query);
                    q = config.select ? q.select(config.select) : q;
                    let result = yield q.exec();
                    if (!result) {
                        return rHandler.handleErrorResponse(new restify.NotFoundError(), res, next);
                    }
                    result = result.toObject();
                    if (paths.hasOwnProperty('hidden') && result.hidden) {
                        let region = yield mongoose.model('Region').findOne({uuid:result.region_uuid});
                        if (!region) {
                            return rHandler.handleErrorResponse(new restify.NotFoundError(), res, next);
                        }
                        // TODO: put this in lib
                        let isAdmin = req.api_key && (
                                req.api_key.scopes.indexOf('admin') ||
                                req.api_key.scopes.indexOf('region-' + region.uuid)
                            );
                            isAdmin = isAdmin == -1 || !isAdmin ? false: true;
                        if (!isAdmin) {
                            return rHandler.handleErrorResponse(new restify.NotFoundError(), res, next);
                        }
                    }
                    if (result && result.user_uuid) {
                        result.user = yield mongoose.model('User')
                            .findOne({uuid:result.user_uuid})
                            .select('uuid nickname').exec();
                        result.user = result.user ? result.user.toObject() : undefined;
                    }
                    if (result && result.subject_uuid) {
                        result.location = yield mongoose.model('Location')
                            .findOne({uuid:result.subject_uuid})
                            .select('uuid title city').exec();
                        result.location = result.location ? result.location.toObject() : undefined;
                    }
                    rHandler.handleDataResponse(result, 200, res, next);
                }),
                pre: Promise.resolve
            },
            postResource: {
                main: Promise.coroutine(function* (req, res, next, config) {
                    if (req.user && req.user.uuid && !req.body.user_uuid) req.body.user_uuid = req.user.uuid;
                    let defaultAcl = [req.user.uuid, 'admin'];
                    if (req.body.hasOwnProperty('region_uuid')) {
                        let region = yield mongoose.model('Region').findOne({uuid: req.body.region_uuid});
                        if (region) {
                            req.body.hidden = region.moderate || false;
                            defaultAcl = defaultAcl.concat(['region-' + region.uuid]);
                        }
                    }
                    let result = yield mongoose.model(config.resource).create(req.body);
                    yield aclManager.setAclEntry(
                        req.url + '/' + result.uuid,
                        defaultAcl,
                        ['get', 'put', 'delete']
                    );
                    yield aclManager.setAclEntry(req.url + '/' + result.uuid, ['user'], ['get']);
                    rHandler.handleDataResponse(result, 201, res, next);
                }),
                pre: Promise.resolve
            },
            putResource: {
                main: Promise.coroutine(function* (req, res, next, config) {
                    deleteProtected(req);
                    let data = yield mongoose.model(config.resource).findOne({uuid: req.params.uuid}).exec();
                    if (data) {
                        for (var key in req.body) {
                            data[key] = req.body[key];
                        }
                        yield data.save();
                        rHandler.handleDataResponse(data, 200, res, next);
                    } else {
                        rHandler.handleErrorResponse(new restify.NotFoundError(), res, next);
                    }
                }),
                pre: Promise.resolve
            },
            deleteResource: {
                main: Promise.coroutine(function* (req, res, next, config) {
                    let result = yield mongoose.model(config.resource).findOneAndRemove({uuid: req.params.uuid});
                    if (result) {
                        yield aclManager.removeAclEntry(req.url, req.user.uuid, '*');
                        yield aclManager.removeAclEntry(req.url, 'admin', '*');
                        yield aclManager.removeAclEntry(req.url, 'user', '*');
                        rHandler.handleDataResponse(result, 200, res, next);
                    } else {
                        rHandler.handleErrorResponse(new restify.NotFoundError(), res, next);
                    }
                }),
                pre: Promise.resolve
            }
        };
    }

    map(verb, config) {
        let instance = this;
        return function executeRequest(req, res, next) {
            return Promise.resolve()
                .then(() => {
                    return instance.coroutines[`${verb}Resource`].pre(req, res, next, config);
                })
                .then(() => {
                    return instance.coroutines[`${verb}Resource`].main(req, res, next, config);
                })
                .catch(err => {
                    rHandler.handleErrorResponse(err, res, next);
                });
        };
    }
}

module.exports = CommonController;<|endoftext|>


<commit_before>import { config } from '../config';
import { validators } from '../validators';

export default {
  render(h) {
    return h(
      'form', {
        on: {
          submit: (event) => {
            this.state.$submitted = true;
            this.state._cloneState();
            this.$emit('submit', event);
          }
        },
        attrs: {
          'novalidate': '',
          'class': this.className
        }
      }, [this.$slots.default]
    );
  },
  props: {
    state: Object
  },
  data() {
    return {};
  },
  created() {
    const controls = {};
    const state = this.state;
    const formstate = {
      $dirty: false,
      $pristine: true,
      $valid: true,
      $invalid: false,
      $submitted: false,
      $touched: false,
      $untouched: true,
      $pending: false,
      $error: {},
      $submittedState: {},
      _id: '',
      _cloneState: () => {
        const cloned = JSON.parse(JSON.stringify(state));
        delete cloned.$submittedState;
        Object.keys(cloned).forEach((key) => {
          this.$set(this.state.$submittedState, key, cloned[key]);
        });
      },
      _addControl: (ctrl) => {
        controls[ctrl.$name] = ctrl;
        this.$set(state, ctrl.$name, ctrl);
      },
      _removeControl: (ctrl) => {
        delete controls[ctrl.$name];
        this.$delete(this.state, ctrl.$name);
        this.$delete(this.state.$error, ctrl.$name);
      }
    }

    Object.keys(formstate).forEach((key) => {
      this.$set(this.state, key, formstate[key]);
    });

    this.$watch('state', () => {
      let isDirty = false;
      let isValid = true;
      let isTouched = false;
      let isPending = false;
      Object.keys(controls).forEach((key) => {
        const control = controls[key];

        control.$submitted = state.$submitted;

        if (control.$dirty) {
          isDirty = true;
        }
        if (control.$touched) {
          isTouched = true;
        }
        if (control.$pending) {
          isPending = true;
        }
        if (!control.$valid) {
          isValid = false;
          // add control to errors
          this.$set(state.$error, control.$name, control);
        } else {
          this.$delete(state.$error, control.$name);
        }
      });

      state.$dirty = isDirty;
      state.$pristine = !isDirty;
      state.$touched = isTouched;
      state.$untouched = !isTouched;
      state.$valid = isValid;
      state.$invalid = !isValid;
      state.$pending = isPending;

    }, {
      deep: true,
      immediate: true
    });

    /* watch pristine? if set to true, set all children to pristine
    Object.keys(controls).forEach((ctrl) => {
      controls[ctrl].setPristine();
    });*/

  },
  computed: {
    className() {
      const out = [];
      const c = config.classes.form;
      if (this.state.$dirty) {
        out.push(c.dirty);
      } else {
        out.push(c.pristine);
      }
      if (this.state.$valid) {
        out.push(c.valid);
      } else {
        out.push(c.invalid);
      }
      if (this.state.$touched) {
        out.push(c.touched);
      } else {
        out.push(c.untouched);
      }
      if (this.state.$submitted) {
        out.push(c.submitted);
      }
      if (this.state.$pending) {
        out.push(c.pending);
      }
      return out.join(' ');
    }
  }
}
<commit_msg>Pass classes through vue-form<commit_after>import { config } from '../config';
import { validators } from '../validators';

export default {
  render(h) {
    return h(
      'form', {
        on: {
          submit: (event) => {
            this.state.$submitted = true;
            this.state._cloneState();
            this.$emit('submit', event);
          }
        },
        class: this.className,
        attrs: {
          'novalidate': '',
        }
      }, [this.$slots.default]
    );
  },
  props: {
    state: Object
  },
  data() {
    return {};
  },
  created() {
    const controls = {};
    const state = this.state;
    const formstate = {
      $dirty: false,
      $pristine: true,
      $valid: true,
      $invalid: false,
      $submitted: false,
      $touched: false,
      $untouched: true,
      $pending: false,
      $error: {},
      $submittedState: {},
      _id: '',
      _cloneState: () => {
        const cloned = JSON.parse(JSON.stringify(state));
        delete cloned.$submittedState;
        Object.keys(cloned).forEach((key) => {
          this.$set(this.state.$submittedState, key, cloned[key]);
        });
      },
      _addControl: (ctrl) => {
        controls[ctrl.$name] = ctrl;
        this.$set(state, ctrl.$name, ctrl);
      },
      _removeControl: (ctrl) => {
        delete controls[ctrl.$name];
        this.$delete(this.state, ctrl.$name);
        this.$delete(this.state.$error, ctrl.$name);
      }
    }

    Object.keys(formstate).forEach((key) => {
      this.$set(this.state, key, formstate[key]);
    });

    this.$watch('state', () => {
      let isDirty = false;
      let isValid = true;
      let isTouched = false;
      let isPending = false;
      Object.keys(controls).forEach((key) => {
        const control = controls[key];

        control.$submitted = state.$submitted;

        if (control.$dirty) {
          isDirty = true;
        }
        if (control.$touched) {
          isTouched = true;
        }
        if (control.$pending) {
          isPending = true;
        }
        if (!control.$valid) {
          isValid = false;
          // add control to errors
          this.$set(state.$error, control.$name, control);
        } else {
          this.$delete(state.$error, control.$name);
        }
      });

      state.$dirty = isDirty;
      state.$pristine = !isDirty;
      state.$touched = isTouched;
      state.$untouched = !isTouched;
      state.$valid = isValid;
      state.$invalid = !isValid;
      state.$pending = isPending;

    }, {
      deep: true,
      immediate: true
    });

    /* watch pristine? if set to true, set all children to pristine
    Object.keys(controls).forEach((ctrl) => {
      controls[ctrl].setPristine();
    });*/

  },
  computed: {
    className() {
      const c = config.classes.form;
      const s = this.$state;
      return {
        [c.dirty]: s.$dirty,
        [c.pristine]: s.$pristine,
        [c.valid]: s.$valid,
        [c.invalid]: s.$invalid,
        [c.touched]: s.$touched,
        [c.untouched]: s.$untouched,
        [c.submitted]: s.$submitted,
        [c.pending]: s.$pending,
      };
    }
  }
}
<|endoftext|>


<commit_before>module.exports = function(config) {
  config.set({
    frameworks: ['jasmine'],

    files: [
      '*.js'
    ],

    autoWatch: true,

    browsers: ['sl_chrome_linux'],

    reporters: ['dots'],

    plugins: [
      'karma-jasmine',
      'karma-sauce-launcher'
    ],

    customLaunchers: {
      sl_chrome_linux: {
        base: 'SauceLabs',
        browserName: 'chrome',
        platform: 'linux'
      }
    }
  });
};
<commit_msg>tests(e2e.sauce): set logging to debug<commit_after>module.exports = function(config) {
  config.set({
    frameworks: ['jasmine'],

    files: [
      '*.js'
    ],

    autoWatch: true,

    browsers: ['sl_chrome_linux'],

    reporters: ['dots'],

    logLevel: config.LOG_DEBUG,

    plugins: [
      'karma-jasmine',
      'karma-sauce-launcher'
    ],

    customLaunchers: {
      sl_chrome_linux: {
        base: 'SauceLabs',
        browserName: 'chrome',
        platform: 'linux'
      }
    }
  });
};
<|endoftext|>


<commit_before>var async = require('async');
var crypto = require('crypto');
var nodemailer = require("nodemailer");
var User = require('../models/User');
var secrets = require('../config/secrets');

/**
 * GET /forgot
 * Forgot Password page.
 */

exports.getForgot = function(req, res) {
  if (req.isAuthenticated()) {
    return res.redirect('/');
  }
  res.render('account/forgot', {
    title: 'Forgot Password'
  });
};

/**
 * POST /forgot
 * Create a random token, then the send user an email with a reset link.
 * @param email
 */

exports.postForgot = function(req, res, next) {
  req.assert('email', 'Please enter a valid email address.').isEmail();

  var errors = req.validationErrors();

  if (errors) {
    req.flash('errors', errors);
    return res.redirect('/forgot');
  }

  async.waterfall([
    function(done) {
      crypto.randomBytes(20, function(err, buf) {
        var token = buf.toString('hex');
        done(err, token);
      });
    },
    function(token, done) {
      User.findOne({ email: req.body.email.toLowerCase() }, function(err, user) {
        if (!user) {
          req.flash('errors', { msg: 'No account with that email address exists.' });
          return res.redirect('/forgot');
        }

        user.resetPasswordToken = token;
        user.resetPasswordExpires = Date.now() + 3600000; // 1 hour

        user.save(function(err) {
          done(err, token, user);
        });
      });
    },
    function(token, user, done) {
      var smtpTransport = nodemailer.createTransport('SMTP', {
        service: 'SendGrid',
        auth: {
          user: secrets.sendgrid.user,
          pass: secrets.sendgrid.password
        }
      });
      var mailOptions = {
        to: user.profile.name + ' <' + user.email + '>',
        from: 'hackathon@starter.com',
        subject: 'Hackathon Starter Password Reset',
        text: 'You are receiving this because you (or someone else) have requested the reset of the password for your account.\n\n' +
          'Please click on the following link, or paste this into your browser to complete the process:\n\n' +
          'http://' + req.headers.host + '/reset/' + token + '\n\n' +
          'If you did not request this, please ignore this email and your password will remain unchanged.\n'
      };
      smtpTransport.sendMail(mailOptions, function(err) {
        req.flash('info', { msg: 'An e-mail has been sent to ' + user.email + ' with further instructions.' });
        done(err, 'done');
      });
    }
  ], function(err) {
    if (err) return next(err);
    res.redirect('/forgot');
  });
};
<commit_msg>Updated TO and SUBJECT nodemailer fields on forgot password controller<commit_after>var async = require('async');
var crypto = require('crypto');
var nodemailer = require("nodemailer");
var User = require('../models/User');
var secrets = require('../config/secrets');

/**
 * GET /forgot
 * Forgot Password page.
 */

exports.getForgot = function(req, res) {
  if (req.isAuthenticated()) {
    return res.redirect('/');
  }
  res.render('account/forgot', {
    title: 'Forgot Password'
  });
};

/**
 * POST /forgot
 * Create a random token, then the send user an email with a reset link.
 * @param email
 */

exports.postForgot = function(req, res, next) {
  req.assert('email', 'Please enter a valid email address.').isEmail();

  var errors = req.validationErrors();

  if (errors) {
    req.flash('errors', errors);
    return res.redirect('/forgot');
  }

  async.waterfall([
    function(done) {
      crypto.randomBytes(20, function(err, buf) {
        var token = buf.toString('hex');
        done(err, token);
      });
    },
    function(token, done) {
      User.findOne({ email: req.body.email.toLowerCase() }, function(err, user) {
        if (!user) {
          req.flash('errors', { msg: 'No account with that email address exists.' });
          return res.redirect('/forgot');
        }

        user.resetPasswordToken = token;
        user.resetPasswordExpires = Date.now() + 3600000; // 1 hour

        user.save(function(err) {
          done(err, token, user);
        });
      });
    },
    function(token, user, done) {
      var smtpTransport = nodemailer.createTransport('SMTP', {
        service: 'SendGrid',
        auth: {
          user: secrets.sendgrid.user,
          pass: secrets.sendgrid.password
        }
      });
      var mailOptions = {
        to: user.email,
        from: 'hackathon@starter.com',
        subject: 'Reset your password on Hackathon Starter',
        text: 'You are receiving this because you (or someone else) have requested the reset of the password for your account.\n\n' +
          'Please click on the following link, or paste this into your browser to complete the process:\n\n' +
          'http://' + req.headers.host + '/reset/' + token + '\n\n' +
          'If you did not request this, please ignore this email and your password will remain unchanged.\n'
      };
      smtpTransport.sendMail(mailOptions, function(err) {
        req.flash('info', { msg: 'An e-mail has been sent to ' + user.email + ' with further instructions.' });
        done(err, 'done');
      });
    }
  ], function(err) {
    if (err) return next(err);
    res.redirect('/forgot');
  });
};
<|endoftext|>


<commit_before>/*  checkforcode.js by David Jerome @GlassToeStudio - GlassToeStudio@gmail.com

    14 July, 2017
    https://github.com/GlassToeStudio
    http://glasstoestudio.weebly.com/
    https://twitter.com/GlassToeStudio

    ------------------------------------------------------------------------
    Systematically search through Discord comments to find unformatted Code.

        * Search is based in chars in codeElements array.
            * Default:  [';', '{', '}', ')']
        * Bot will parse the code line by line searchig for
        * code elements and keep track of which line are code
        * and which are plain text.
        * The bot will do his best to only format a true code
        * block, leaveing the plain text alone. One complte
        * the bot will add code block formattign aroind the
        * code block, with the current code lang 'csharp'.
        * The message will be posted anew as formatted code
        * and, if possible, the old message will be deleted.
        *
        * If the informatted code is posted in a channel with
        * 'help' in the tile, then the new messge is posted
        * there.
        * If the message is posted in any other chnannel, the
        * new message will be posted in #programing_help (if it exists)
        * If there is no programing_help channel, the message is
        * posted in the original channel.
        *
        * When a new message is posted in a new channel, the user
        * is notified that the post has been moved, with a link
        * to the channel. The new post in the new channel will
        * also mention the user, as an added bonus to help
        * the user navigate the newmessage.

    EXAMPLE-----------------------------------------------------------------

    THis is not code so it is not in the code block.

    ```csharp
    using UnityEngine;

    /// <summary>
    /// Class summary
    /// </summary>
    public class MyClass
    {
        /// <summary>   Summary of myFloat. </summary>
        public float myFloat;
        /// <summary>   Summary of myOtherFloat.</summary>
        public float myOtherFLoat;

        // Default constructor
        public MyClass(float _myFloat, float _myOtherFLoat)
        {
            this.myFloat = _myFloat;
            this.myOtherFLoat = _myOtherFLoat;
        }
    }
    ```

    THis is not code so it is not in the code block.

    ------------------------------------------------------------------------

    Discord Markdown 101 for more formatting guidelines:
    https://support.discordapp.com/hc/en-us/articles/210298617-Markdown-Text-101-Chat-Formatting-Bold-Italic-Underline-?page=4
*/

const Discord = require('discord.js');
const GlassBot = require('../bot.js')
const bot = GlassBot.bot
const config = GlassBot.config

// Salt to taste
const codeElements = [';', '{', '}', ')'] // Could be in config
const codeLang = 'csharp'
const repostThreshold = 4

// Variables
var isFormatted = false
var totalLinesOfCode = 0
var firstLine = false
var lastLine = 0

// Lets begin
bot.on('message', message => {
    if(message.author.bot){
        // If this is our reply to the user, delete after 3 seconds
        if(message.content.includes('Your unformatted code')){
            message.delete(300)
            .then(msg => console.log(`Deleted message from ${msg.author}`))
            .catch(console.error);
        }
        return
    }
    if(message.content.length > 1900) return
    InitVariables()

    let lines = message.content.split('\n')

    ParseMessage(lines)

    if(IsBadCode() && !isFormatted){

        lines[lastLine] = FormatLastLine(lines[lastLine])

        CreateNewMessage(lines, message)
    }
    return
});

// Loop through each line in message and check for
// code-like characters. If code formatting is found
// return, else keep checking.
function ParseMessage(lines){
    for(let i = 0; i < lines.length; i++){
        if(lines[i].search("```") >= 0){
            isFormatted = true
            return
        }else
            FindCodeElements(i, lines[i], lines)
    }
    return
}

// Checks the last character in a string to see of it machess a code-like character
function FindCodeElements(index, line, lines){
    let lineLength = line.length - 1
    for(let i = 0; i < codeElements.length; i++){
        if (line.charAt(lineLength).valueOf() == codeElements[i].valueOf()){
            if(!firstLine){
                lines[index] = FormatFirstLine(line)
                return
            }else{
                lastLine = index
                totalLinesOfCode += 1
                return
            }
        }
    }
    return
}

// Recreate the new message with code formatting included
function CreateNewMessage(lines, message){
    let newMessage = ""
    for(let j = 0; j < lines.length; j++)
       newMessage += lines[j] + '\n'

    PostNewMessage(message, newMessage)
}

// Post the formatted message in the appropriate channel
function PostNewMessage(message, newMessage){
    let channel = message.guild.channels.find("name", "programing_help")
    let isHelp = message.channel.name.indexOf('help') > 0

    if(channel != null && channel != message.channel && !isHelp){
        // TODO: Would like to add some color to this message
        message.reply(':nerd: __`Your unformatted code has been formatted and moved to`__ ' + channel + '. :nerd:')
        channel.send(message.author + ' **★★ I have formatted your code and placed it here. Good Luck! ★★** ')
        channel.send(newMessage);
    }else{
        message.reply(' **★★ I see you forgot to format your code... Let me help you. ★★** ')
        message.channel.send(newMessage)
    }

    DeleteOldMessage(message)
}

// Deletes the old unformatted messge if bot has permission
function DeleteOldMessage(message){
    let managePerms = message.guild.member(bot.user).hasPermission('MANAGE_MESSAGES')
    if(managePerms)
        message.delete()
    else
        message.channel.send('**`Tell the server\'s owner to grant me permission to delete your old message, thank\'s`** :wink:')
}

// Adds code formatting block start to the first line of code
function FormatFirstLine(inLine){
    firstLine = true
    return '```' + codeLang + '\n' + inLine
}

// Add formatting code bock end to the last line of code
function FormatLastLine(inLine){
    return inLine + '\n```'
}

// If total line of code is greater than repostThreshold return true
function IsBadCode(){
    return (totalLinesOfCode >= repostThreshold)
}

// Initalize variables
function InitVariables(){
    isFormatted = false
    totalLinesOfCode = 0;
    firstLine = false
    lastLine = 0
}<commit_msg>This message will self-destruct in 10 seconds<commit_after>/*  checkforcode.js by David Jerome @GlassToeStudio - GlassToeStudio@gmail.com

    14 July, 2017
    https://github.com/GlassToeStudio
    http://glasstoestudio.weebly.com/
    https://twitter.com/GlassToeStudio

    ------------------------------------------------------------------------
    Systematically search through Discord comments to find unformatted Code.

        * Search is based in chars in codeElements array.
            * Default:  [';', '{', '}', ')']
        * Bot will parse the code line by line searchig for
        * code elements and keep track of which line are code
        * and which are plain text.
        * The bot will do his best to only format a true code
        * block, leaveing the plain text alone. One complte
        * the bot will add code block formattign aroind the
        * code block, with the current code lang 'csharp'.
        * The message will be posted anew as formatted code
        * and, if possible, the old message will be deleted.
        *
        * If the informatted code is posted in a channel with
        * 'help' in the tile, then the new messge is posted
        * there.
        * If the message is posted in any other chnannel, the
        * new message will be posted in #programing_help (if it exists)
        * If there is no programing_help channel, the message is
        * posted in the original channel.
        *
        * When a new message is posted in a new channel, the user
        * is notified that the post has been moved, with a link
        * to the channel. The new post in the new channel will
        * also mention the user, as an added bonus to help
        * the user navigate the newmessage.

    EXAMPLE-----------------------------------------------------------------

    THis is not code so it is not in the code block.

    ```csharp
    using UnityEngine;

    /// <summary>
    /// Class summary
    /// </summary>
    public class MyClass
    {
        /// <summary>   Summary of myFloat. </summary>
        public float myFloat;
        /// <summary>   Summary of myOtherFloat.</summary>
        public float myOtherFLoat;

        // Default constructor
        public MyClass(float _myFloat, float _myOtherFLoat)
        {
            this.myFloat = _myFloat;
            this.myOtherFLoat = _myOtherFLoat;
        }
    }
    ```

    THis is not code so it is not in the code block.

    ------------------------------------------------------------------------

    Discord Markdown 101 for more formatting guidelines:
    https://support.discordapp.com/hc/en-us/articles/210298617-Markdown-Text-101-Chat-Formatting-Bold-Italic-Underline-?page=4
*/

const Discord = require('discord.js');
const GlassBot = require('../bot.js')
const bot = GlassBot.bot
const config = GlassBot.config

// Salt to taste
const codeElements = [';', '{', '}', ')'] // Could be in config
const codeLang = 'csharp'
const repostThreshold = 4

// Variables
var isFormatted = false
var totalLinesOfCode = 0
var firstLine = false
var lastLine = 0

// Lets begin
bot.on('message', message => {
    if(message.author.bot){
        // If this is our reply to the user, delete after 10 seconds
        if(message.content.includes('Your unformatted code')){
            message.delete(10000)
            .then(msg => console.log(`Deleted message from ${msg.author}`))
            .catch(console.error);
        }
        return
    }
    if(message.content.length > 1900) return
    InitVariables()

    let lines = message.content.split('\n')

    ParseMessage(lines)

    if(IsBadCode() && !isFormatted){

        lines[lastLine] = FormatLastLine(lines[lastLine])

        CreateNewMessage(lines, message)
    }
    return
});

// Loop through each line in message and check for
// code-like characters. If code formatting is found
// return, else keep checking.
function ParseMessage(lines){
    for(let i = 0; i < lines.length; i++){
        if(lines[i].search("```") >= 0){
            isFormatted = true
            return
        }else
            FindCodeElements(i, lines[i], lines)
    }
    return
}

// Checks the last character in a string to see of it machess a code-like character
function FindCodeElements(index, line, lines){
    let lineLength = line.length - 1
    for(let i = 0; i < codeElements.length; i++){
        if (line.charAt(lineLength).valueOf() == codeElements[i].valueOf()){
            if(!firstLine){
                lines[index] = FormatFirstLine(line)
                return
            }else{
                lastLine = index
                totalLinesOfCode += 1
                return
            }
        }
    }
    return
}

// Recreate the new message with code formatting included
function CreateNewMessage(lines, message){
    let newMessage = ""
    for(let j = 0; j < lines.length; j++)
       newMessage += lines[j] + '\n'

    PostNewMessage(message, newMessage)
}

// Post the formatted message in the appropriate channel
function PostNewMessage(message, newMessage){
    let channel = message.guild.channels.find("name", "programing_help")
    let isHelp = message.channel.name.indexOf('help') > 0

    if(channel != null && channel != message.channel && !isHelp){
        // TODO: Would like to add some color to this message
        message.reply(':nerd: __`Your unformatted code has been formatted and moved to`__ ' + channel + '. :nerd: \nThis message will self-destruct in 10 seconds')
        channel.send(message.author + ' **★★ I have formatted your code and placed it here. Good Luck! ★★** ')
        channel.send(newMessage);
    }else{
        message.reply(' **★★ I see you forgot to format your code... Let me help you. ★★** ')
        message.channel.send(newMessage)
    }

    DeleteOldMessage(message)
}

// Deletes the old unformatted messge if bot has permission
function DeleteOldMessage(message){
    let managePerms = message.guild.member(bot.user).hasPermission('MANAGE_MESSAGES')
    if(managePerms)
        message.delete()
    else
        message.channel.send('**`Tell the server\'s owner to grant me permission to delete your old message, thank\'s`** :wink:')
}

// Adds code formatting block start to the first line of code
function FormatFirstLine(inLine){
    firstLine = true
    return '```' + codeLang + '\n' + inLine
}

// Add formatting code bock end to the last line of code
function FormatLastLine(inLine){
    return inLine + '\n```'
}

// If total line of code is greater than repostThreshold return true
function IsBadCode(){
    return (totalLinesOfCode >= repostThreshold)
}

// Initalize variables
function InitVariables(){
    isFormatted = false
    totalLinesOfCode = 0;
    firstLine = false
    lastLine = 0
}<|endoftext|>


<commit_before>const { join } = require('path')
const { spawn } = require('child_process')

const defaultFixturePath = join(__dirname, '../../fixtures/app')

const npmRunner = process.platform === 'win32' ? 'npm.cmd' : 'npm'
const installArgs = ['install', '--progress=false', '--no-audit', '--no-optional', '--no-save']
const log = (msg, ...args) => console.log(`  [TestApp] ${msg}`, ...args)

class TestApp {
  constructor (pathToFixture = defaultFixturePath) {
    this.buildDir = pathToFixture
    this.appName = require(join(pathToFixture, 'package.json')).name
  }

  async packageApp (env) {
    await this._exec(npmRunner, ['run', 'package'], env)
  }

  async installDeps (bugsnagVersion, electronVersion = '^11.4.0') {
    // install this first. electron has a lengthy postinstall script, and doing
    // a bare `npm install` first will wildcard to the latest / last version
    // installed, doubling the install time
    await this._exec(npmRunner, [...installArgs, `electron@${electronVersion}`])
    await this._exec(npmRunner, [...installArgs], {}, 300)
    await this._exec(npmRunner, [...installArgs, '--registry', 'http://0.0.0.0:5539', `@bugsnag/electron@${bugsnagVersion}`])
  }

  packagedPath () {
    const platform = process.platform
    const name = this.appName
    const base = join(this.buildDir, 'out', `${name}-${platform}-${process.arch}`)
    switch (platform) {
      case 'darwin':
        return join(base, `${name}.app/Contents/MacOS/${name}`)
      case 'linux':
        return join(base, name)
      case 'win32':
        return join(base, `${name}.exe`)

      default:
        throw new Error(`No packaged app path configured for ${platform}`)
    }
  }

  launchArgs () {
    switch (process.platform) {
      case 'linux':
        // required for running chromium and friends in a root-y environment
        return ['--no-sandbox']

      default:
        return []
    }
  }

  async _exec (command, args = [], env = {}, timeout = 60, retries = 1) {
    log(`exec: ${command} ${args.join(' ')}`)
    let proc
    return Promise.race([
      new Promise((resolve, reject) => setTimeout(() => {
        if (proc) {
          proc.kill()
        }
        reject(new Error(`Command timed out (${timeout}s)`))
      }, timeout * 1000)),
      new Promise((resolve, reject) => {
        proc = spawn(command, args, { cwd: this.buildDir, env: { ...process.env, ...env } })
        // handy for debugging but otherwise annoying output
        if (process.env.VERBOSE) {
          proc.stderr.on('data', data => { process.stdout.write(data) })
        } else {
          // webpack will hang if *something* doesn't read from stderr, even when
          // everything is fine
          proc.stderr.on('data', () => {})
        }
        proc.stdout.on('data', () => {})
        proc.on('close', async (code) => {
          if (code !== 0) {
            reject(new Error(`Running '${command}' failed with code: ${code}`))
          } else {
            resolve()
          }
        })
      })
    ]).catch(async (err) => {
      if (retries > 0) {
        log(`retrying ${command} command - ${err}`)
        return await this._exec(command, args, env, timeout, retries - 1)
      } else {
        throw err
      }
    })
  }
}

module.exports = { TestApp }
<commit_msg>ci: increase timeout delay for installing test app deps<commit_after>const { join } = require('path')
const { spawn } = require('child_process')

const defaultFixturePath = join(__dirname, '../../fixtures/app')

const npmRunner = process.platform === 'win32' ? 'npm.cmd' : 'npm'
const installArgs = ['install', '--progress=false', '--no-audit', '--no-optional', '--no-save']
const log = (msg, ...args) => console.log(`  [TestApp] ${msg}`, ...args)

class TestApp {
  constructor (pathToFixture = defaultFixturePath) {
    this.buildDir = pathToFixture
    this.appName = require(join(pathToFixture, 'package.json')).name
  }

  async packageApp (env) {
    await this._exec(npmRunner, ['run', 'package'], env)
  }

  async installDeps (bugsnagVersion, electronVersion = '^11.4.0') {
    // install this first. electron has a lengthy postinstall script, and doing
    // a bare `npm install` first will wildcard to the latest / last version
    // installed, doubling the install time
    await this._exec(npmRunner, [...installArgs, `electron@${electronVersion}`])
    await this._exec(npmRunner, [...installArgs], {}, 500)
    await this._exec(npmRunner, [...installArgs, '--registry', 'http://0.0.0.0:5539', `@bugsnag/electron@${bugsnagVersion}`])
  }

  packagedPath () {
    const platform = process.platform
    const name = this.appName
    const base = join(this.buildDir, 'out', `${name}-${platform}-${process.arch}`)
    switch (platform) {
      case 'darwin':
        return join(base, `${name}.app/Contents/MacOS/${name}`)
      case 'linux':
        return join(base, name)
      case 'win32':
        return join(base, `${name}.exe`)

      default:
        throw new Error(`No packaged app path configured for ${platform}`)
    }
  }

  launchArgs () {
    switch (process.platform) {
      case 'linux':
        // required for running chromium and friends in a root-y environment
        return ['--no-sandbox']

      default:
        return []
    }
  }

  async _exec (command, args = [], env = {}, timeout = 60, retries = 1) {
    log(`exec: ${command} ${args.join(' ')}`)
    let proc
    return Promise.race([
      new Promise((resolve, reject) => setTimeout(() => {
        if (proc) {
          proc.kill()
        }
        reject(new Error(`Command timed out (${timeout}s)`))
      }, timeout * 1000)),
      new Promise((resolve, reject) => {
        proc = spawn(command, args, { cwd: this.buildDir, env: { ...process.env, ...env } })
        // handy for debugging but otherwise annoying output
        if (process.env.VERBOSE) {
          proc.stderr.on('data', data => { process.stdout.write(data) })
        } else {
          // webpack will hang if *something* doesn't read from stderr, even when
          // everything is fine
          proc.stderr.on('data', () => {})
        }
        proc.stdout.on('data', () => {})
        proc.on('close', async (code) => {
          if (code !== 0) {
            reject(new Error(`Running '${command}' failed with code: ${code}`))
          } else {
            resolve()
          }
        })
      })
    ]).catch(async (err) => {
      if (retries > 0) {
        log(`retrying ${command} command - ${err}`)
        return await this._exec(command, args, env, timeout, retries - 1)
      } else {
        throw err
      }
    })
  }
}

module.exports = { TestApp }
<|endoftext|>


<commit_before>/*
* Database schema.
* On this example we have the following schema on mongo:
* {"userId":"userIdValue",
* answers:[
* {"idUser":1111,"testNo":1,"answerNo":2,"answerValue":"answer1"},
* {"idUser":1111,"testNo":1,"answerNo":2,"answerValue":"answer1"}
* ]}
*/
var mongoose     = require('mongoose');
var Schema       = mongoose.Schema;

var NewUserSchema   = new Schema({
    idUser: Number,
    time:Date

});

module.exports = mongoose.model('NewUser', NewUserSchema);<commit_msg>update field name<commit_after>/*
* Database schema.
* On this example we have the following schema on mongo:
* {"userId":"userIdValue",
* answers:[
* {"idUser":1111,"testNo":1,"answerNo":2,"answerValue":"answer1"},
* {"idUser":1111,"testNo":1,"answerNo":2,"answerValue":"answer1"}
* ]}
*/
var mongoose     = require('mongoose');
var Schema       = mongoose.Schema;

var NewUserSchema   = new Schema({
    id: Number,
    time:Date

});

module.exports = mongoose.model('NewUser', NewUserSchema);<|endoftext|>


<commit_before>/**
 * @copyright Copyright (c) 2016 Joas Schilling <coding@schilljs.com>
 * @copyright Copyright (c) 2019 Gary Kim <gary@garykim.dev>
 *
 * @license GNU AGPL version 3 or any later version
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

(function() {
	if (!OCA.SystemTags) {
		/**
		 * @namespace
		 */
		OCA.SystemTags = {};
	}

	OCA.SystemTags.Admin = {

		collection: null,

		init: function() {
			var self = this;

			this.collection = OC.SystemTags.collection;
			this.collection.fetch({
				success: function() {
					$('#systemtag').select2(_.extend(self.select2));
				}
			});

			var self = this;
			$('#systemtag_name').on('keyup', function(e) {
				if (e.which === 13) {
					_.bind(self._onClickSubmit, self)();
				}
			});
			$('#systemtag_submit').on('click', _.bind(this._onClickSubmit, this));
			$('#systemtag_delete').on('click', _.bind(this._onClickDelete, this));
			$('#systemtag_reset').on('click', _.bind(this._onClickReset, this));
		},

		/**
		 * Selecting a systemtag in select2
		 *
		 * @param {OC.SystemTags.SystemTagModel} tag
		 */
		onSelectTag: function (tag) {
			var level = 0;
			if (tag.get('userVisible')) {
				level += 2;
				if (tag.get('userAssignable')) {
					level += 1;
				}
			}

			$('#systemtag_name').val(tag.get('name'));
			$('#systemtag_level').val(level);

			this._prepareForm(tag.get('id'));
		},

		/**
		 * Clicking the "Create"/"Update" button
		 */
		_onClickSubmit: function () {
			var level = parseInt($('#systemtag_level').val(), 10),
				tagId = $('#systemtags').attr('data-systemtag-id');
			var data = {
				name: $('#systemtag_name').val(),
				userVisible: level === 2 || level === 3,
				userAssignable: level === 3
			};

			if (!data.name) {
				OCP.Toast.error(t('systemtags_manager', 'Tag name is empty'));
				return;
			}

			if (tagId) {
				var model = this.collection.get(tagId);
				model.save(data);
			} else {
				this.collection.create(data);
			}

			this._onClickReset();
		},

		/**
		 * Clicking the "Delete" button
		 */
		_onClickDelete: function () {
			var tagId = $('#systemtags').attr('data-systemtag-id');
			var model = this.collection.get(tagId);
			model.destroy();

			this._onClickReset();
		},

		/**
		 * Clicking the "Reset" button
		 */
		_onClickReset: function () {
			$('#systemtag_name').val('');
			$('#systemtag_level').val(3);
			this._prepareForm(0);
		},

		/**
		 * Prepare the form for create/update
		 *
		 * @param {int} tagId
		 */
		_prepareForm: function (tagId) {
			if (tagId > 0) {
				$('#systemtags').attr('data-systemtag-id', tagId);
				$('#systemtag_delete').removeClass('hidden');
				$('#systemtag_submit span').text(t('systemtags_manager', 'Update'));
				$('#systemtag_create').addClass('hidden');
			} else {
				$('#systemtag').select2('val', '');
				$('#systemtags').attr('data-systemtag-id', '');
				$('#systemtag_delete').addClass('hidden');
				$('#systemtag_submit span').text(t('systemtags_manager', 'Create'));
				$('#systemtag_create').removeClass('hidden');
			}
		},

		/**
		 * Select2 options for the SystemTag dropdown
		 */
		select2: {
			allowClear: false,
			multiple: false,
			placeholder: t('systemtags_manager', 'Select tag…'),
			query: _.debounce(function(query) {
				query.callback({
					results: OCA.SystemTags.Admin.collection.filterByName(query.term)
				});
			}, 100, true),
			id: function(element) {
				return element;
			},
			initSelection: function(element, callback) {
				var selection = ($(element).val() || []).split('|').sort();
				callback(selection);
			},
			formatResult: function (tag) {
				return OC.SystemTags.getDescriptiveTag(tag);
			},
			formatSelection: function (tag) {
				OCA.SystemTags.Admin.onSelectTag(tag);
				return OC.SystemTags.getDescriptiveTag(tag);
			},
			escapeMarkup: function(m) {
				return m;
			},
			sortResults: function(results) {
				results.sort(function(a, b) {
					return OC.Util.naturalSortCompare(a.get('name'), b.get('name'));
				});
				return results;
			}
		}
	};
})();

window.addEventListener('DOMContentLoaded', function() {
	OCA.SystemTags.Admin.init();
});

<commit_msg>l10n: Separate ellipsis<commit_after>/**
 * @copyright Copyright (c) 2016 Joas Schilling <coding@schilljs.com>
 * @copyright Copyright (c) 2019 Gary Kim <gary@garykim.dev>
 *
 * @license GNU AGPL version 3 or any later version
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

(function() {
	if (!OCA.SystemTags) {
		/**
		 * @namespace
		 */
		OCA.SystemTags = {};
	}

	OCA.SystemTags.Admin = {

		collection: null,

		init: function() {
			var self = this;

			this.collection = OC.SystemTags.collection;
			this.collection.fetch({
				success: function() {
					$('#systemtag').select2(_.extend(self.select2));
				}
			});

			var self = this;
			$('#systemtag_name').on('keyup', function(e) {
				if (e.which === 13) {
					_.bind(self._onClickSubmit, self)();
				}
			});
			$('#systemtag_submit').on('click', _.bind(this._onClickSubmit, this));
			$('#systemtag_delete').on('click', _.bind(this._onClickDelete, this));
			$('#systemtag_reset').on('click', _.bind(this._onClickReset, this));
		},

		/**
		 * Selecting a systemtag in select2
		 *
		 * @param {OC.SystemTags.SystemTagModel} tag
		 */
		onSelectTag: function (tag) {
			var level = 0;
			if (tag.get('userVisible')) {
				level += 2;
				if (tag.get('userAssignable')) {
					level += 1;
				}
			}

			$('#systemtag_name').val(tag.get('name'));
			$('#systemtag_level').val(level);

			this._prepareForm(tag.get('id'));
		},

		/**
		 * Clicking the "Create"/"Update" button
		 */
		_onClickSubmit: function () {
			var level = parseInt($('#systemtag_level').val(), 10),
				tagId = $('#systemtags').attr('data-systemtag-id');
			var data = {
				name: $('#systemtag_name').val(),
				userVisible: level === 2 || level === 3,
				userAssignable: level === 3
			};

			if (!data.name) {
				OCP.Toast.error(t('systemtags_manager', 'Tag name is empty'));
				return;
			}

			if (tagId) {
				var model = this.collection.get(tagId);
				model.save(data);
			} else {
				this.collection.create(data);
			}

			this._onClickReset();
		},

		/**
		 * Clicking the "Delete" button
		 */
		_onClickDelete: function () {
			var tagId = $('#systemtags').attr('data-systemtag-id');
			var model = this.collection.get(tagId);
			model.destroy();

			this._onClickReset();
		},

		/**
		 * Clicking the "Reset" button
		 */
		_onClickReset: function () {
			$('#systemtag_name').val('');
			$('#systemtag_level').val(3);
			this._prepareForm(0);
		},

		/**
		 * Prepare the form for create/update
		 *
		 * @param {int} tagId
		 */
		_prepareForm: function (tagId) {
			if (tagId > 0) {
				$('#systemtags').attr('data-systemtag-id', tagId);
				$('#systemtag_delete').removeClass('hidden');
				$('#systemtag_submit span').text(t('systemtags_manager', 'Update'));
				$('#systemtag_create').addClass('hidden');
			} else {
				$('#systemtag').select2('val', '');
				$('#systemtags').attr('data-systemtag-id', '');
				$('#systemtag_delete').addClass('hidden');
				$('#systemtag_submit span').text(t('systemtags_manager', 'Create'));
				$('#systemtag_create').removeClass('hidden');
			}
		},

		/**
		 * Select2 options for the SystemTag dropdown
		 */
		select2: {
			allowClear: false,
			multiple: false,
			placeholder: t('systemtags_manager', 'Select tag …'),
			query: _.debounce(function(query) {
				query.callback({
					results: OCA.SystemTags.Admin.collection.filterByName(query.term)
				});
			}, 100, true),
			id: function(element) {
				return element;
			},
			initSelection: function(element, callback) {
				var selection = ($(element).val() || []).split('|').sort();
				callback(selection);
			},
			formatResult: function (tag) {
				return OC.SystemTags.getDescriptiveTag(tag);
			},
			formatSelection: function (tag) {
				OCA.SystemTags.Admin.onSelectTag(tag);
				return OC.SystemTags.getDescriptiveTag(tag);
			},
			escapeMarkup: function(m) {
				return m;
			},
			sortResults: function(results) {
				results.sort(function(a, b) {
					return OC.Util.naturalSortCompare(a.get('name'), b.get('name'));
				});
				return results;
			}
		}
	};
})();

window.addEventListener('DOMContentLoaded', function() {
	OCA.SystemTags.Admin.init();
});

<|endoftext|>


<commit_before>var _ = require('lodash'),
    options = require('../../lib/run/options');

describe('options', function () {
    describe('JSON with spaces', function () {
        it('should be handled correctly for collections', function (done) {
            var collection = require('../../test/fixtures/run/spaces/single-get-request.json');

            options({
                collection: './test/fixtures/run/spaces/single-get-request.json'
            }, function (err, result) {
                expect(err).to.be.null;

                // remove undefined properties
                result = JSON.parse(JSON.stringify(result.collection.toJSON()));
                expect(_.omit(result,
                    // eslint-disable-next-line max-len
                    ['event', 'info._postman_id', 'variable', 'item.0.id', 'item.0.response', 'item.0.event.0.script.id']))
                    .to.eql(collection);
                done();
            });
        });

        it('should be handled correctly for environments', function (done) {
            var environment = require('../../test/fixtures/run/spaces/simple-variables.json');

            options({
                environment: './test/fixtures/run/spaces/simple-variables.json'
            }, function (err, result) {
                expect(err).to.be.null;

                expect(_.omit(result.environment.toJSON(), 'id')).to.eql(environment);
                done();
            });
        });

        it('should apply directly specified env variables to environment list', function (done) {
            options({
                envVar: [{ key: 'test', value: 'data' }]
            }, function (err, result) {
                expect(err).to.be.null;
                expect(result).to.have.property('environment');
                expect(result.environment).to.be.an.instanceof(sdk.VariableScope);
                expect(result.environment.get('test')).to.equal('data');
                done();
            });
        });

        it('should be handled correctly for globals', function (done) {
            var globals = require('../../test/fixtures/run/spaces/simple-variables.json');

            options({
                globals: './test/fixtures/run/spaces/simple-variables.json'
            }, function (err, result) {
                expect(err).to.be.null;

                expect(_.omit(result.globals.toJSON(), 'id')).to.eql(globals);
                done();
            });
        });

        it('should apply directly specified global variables to globals list', function (done) {
            options({
                globalVar: [{ key: 'test', value: 'data' }]
            }, function (err, result) {
                expect(err).to.be.null;
                expect(result).to.have.nested.property('globals.values.reference.test.value', 'data');
                done();
            });
        });

        it('should be handled correctly for iterationData', function (done) {
            var data = require('../../test/fixtures/run/spaces/data.json');

            options({
                iterationData: './test/fixtures/run/spaces/data.json'
            }, function (err, result) {
                expect(err).to.be.null;
                expect(result.iterationData).to.eql(data);
                done();
            });
        });

        it('should be handled correctly for cookieJar', function (done) {
            var data = require('../../test/fixtures/run/spaces/simple-cookie-jar.json');

            options({
                cookieJar: './test/fixtures/run/spaces/simple-cookie-jar.json'
            }, function (err, result) {
                expect(err).to.be.null;
                expect(result.cookieJar.toJSON()).to.eql(data);
                done();
            });
        });
    });

    it('should have newmanVersion property by default', function (done) {
        var newmanVersion = require('../../package.json').version;

        options({}, function (err, result) {
            expect(err).to.be.null;
            expect(result).to.have.property('newmanVersion', newmanVersion);
            done();
        });
    });

    it('should set current directory as workingDir if not given', function (done) {
        options({}, function (err, result) {
            expect(err).to.be.null;
            expect(result).to.have.property('workingDir', process.cwd());
            done();
        });
    });

    it('should set insecureFileRead to true if not given', function (done) {
        options({}, function (err, result) {
            expect(err).to.be.null;
            expect(result).to.have.property('insecureFileRead', true);
            done();
        });
    });
});
<commit_msg>Fix unit test for options<commit_after>var _ = require('lodash'),
    { VariableScope } = require('postman-collection'),
    options = require('../../lib/run/options');

describe('options', function () {
    describe('JSON with spaces', function () {
        it('should be handled correctly for collections', function (done) {
            var collection = require('../../test/fixtures/run/spaces/single-get-request.json');

            options({
                collection: './test/fixtures/run/spaces/single-get-request.json'
            }, function (err, result) {
                expect(err).to.be.null;

                // remove undefined properties
                result = JSON.parse(JSON.stringify(result.collection.toJSON()));
                expect(_.omit(result,
                    // eslint-disable-next-line max-len
                    ['event', 'info._postman_id', 'variable', 'item.0.id', 'item.0.response', 'item.0.event.0.script.id']))
                    .to.eql(collection);
                done();
            });
        });

        it('should be handled correctly for environments', function (done) {
            var environment = require('../../test/fixtures/run/spaces/simple-variables.json');

            options({
                environment: './test/fixtures/run/spaces/simple-variables.json'
            }, function (err, result) {
                expect(err).to.be.null;

                expect(_.omit(result.environment.toJSON(), 'id')).to.eql(environment);
                done();
            });
        });

        it('should apply directly specified env variables to environment list', function (done) {
            options({
                envVar: [{ key: 'test', value: 'data' }]
            }, function (err, result) {
                expect(err).to.be.null;
                expect(result).to.have.property('environment');
                expect(result.environment).to.be.an.instanceof(VariableScope);
                expect(result.environment.get('test')).to.equal('data');
                done();
            });
        });

        it('should be handled correctly for globals', function (done) {
            var globals = require('../../test/fixtures/run/spaces/simple-variables.json');

            options({
                globals: './test/fixtures/run/spaces/simple-variables.json'
            }, function (err, result) {
                expect(err).to.be.null;

                expect(_.omit(result.globals.toJSON(), 'id')).to.eql(globals);
                done();
            });
        });

        it('should apply directly specified global variables to globals list', function (done) {
            options({
                globalVar: [{ key: 'test', value: 'data' }]
            }, function (err, result) {
                expect(err).to.be.null;
                expect(result).to.have.property('globals');
                expect(result.globals).to.be.an.instanceof(VariableScope);
                expect(result.globals.get('test')).to.equal('data');
                done();
            });
        });

        it('should be handled correctly for iterationData', function (done) {
            var data = require('../../test/fixtures/run/spaces/data.json');

            options({
                iterationData: './test/fixtures/run/spaces/data.json'
            }, function (err, result) {
                expect(err).to.be.null;
                expect(result.iterationData).to.eql(data);
                done();
            });
        });

        it('should be handled correctly for cookieJar', function (done) {
            var data = require('../../test/fixtures/run/spaces/simple-cookie-jar.json');

            options({
                cookieJar: './test/fixtures/run/spaces/simple-cookie-jar.json'
            }, function (err, result) {
                expect(err).to.be.null;
                expect(result.cookieJar.toJSON()).to.eql(data);
                done();
            });
        });
    });

    it('should have newmanVersion property by default', function (done) {
        var newmanVersion = require('../../package.json').version;

        options({}, function (err, result) {
            expect(err).to.be.null;
            expect(result).to.have.property('newmanVersion', newmanVersion);
            done();
        });
    });

    it('should set current directory as workingDir if not given', function (done) {
        options({}, function (err, result) {
            expect(err).to.be.null;
            expect(result).to.have.property('workingDir', process.cwd());
            done();
        });
    });

    it('should set insecureFileRead to true if not given', function (done) {
        options({}, function (err, result) {
            expect(err).to.be.null;
            expect(result).to.have.property('insecureFileRead', true);
            done();
        });
    });
});
<|endoftext|>