text: const assert = require('assert');
  const Understudy = require('boring-understudy');
  
  describe('Understudy Promisified', function() {
  
    it('will return a promise from perform', (done) => {
  
      assert.ok(Understudy);
  
      const tester = new Understudy();
      assert.ok(tester);
  
      const options = {foo: 'bar'};
  
      tester.before('beep', function(localOptions) {
        localOptions.speak = 'meow';
  
        return new Promise(resolve => {
          setTimeout(resolve, 300);
        });
      });
  
      tester.before('beep', function(localOptions) {
  
        assert.equal(localOptions.speak, 'meow');
        localOptions.transport = 'walk';
  
        // does not need to return a promise, it will just be wrapped and returned sync
      });
  
      tester.after('beep', function(localOptions) {
  
        assert.equal(localOptions.transport, 'walk');
        localOptions.move = 'wiggle';
        return new Promise(resolve => resolve());
      });
  
      tester.perform('beep', options, function work() {
        assert.equal(Object.keys(options).length, 3);
        return new Promise(resolve => resolve(options));
      }).then((finalOptions) => {
        assert.equal(Object.keys(options).length, 4);
        assert.equal(finalOptions.foo, 'bar');
        assert.equal(finalOptions.speak, 'meow');
        assert.equal(finalOptions.transport, 'walk');
        assert.equal(finalOptions.move, 'wiggle');
  
        done();
      }).catch(e => {
        assert.fail(e);
      });
    });
  
    it('will call the catch if a before rejects', done => {
  
      const tester = new Understudy();
  
      tester.before('beep', () => {
        return Promise.reject(new Error('thrown from before'));
      });
  
      tester.perform('beep', function(next) {
        assert.fail('should not be hit');
      })
        .then(() => assert.fail('Should not be resolved'))
        .catch((e) => {
          assert.equal(e.message, 'thrown from before');
          done();
        });
    });
  
  
    it('will call the catch if a before rejects with no reject reason', done => {
  
      const tester = new Understudy();
  
      tester.before('beep', () => {
        return Promise.reject();
      });
  
      tester.perform('beep', function(next) {
        return Promise.reject('should not be hit');
      })
        .then(() => assert.fail('Should not be resolved'))
        .catch((e) => {
          assert.notStrictEqual(e, 'should not be hit');
          done();
        });
    });
  
  
    it('will call the catch if thrown on before', async () => {
  
      const tester = new Understudy();
      let caught = false;
  
      tester.before('beep', () => {
        throw new Error('thrown from before');
      });
  
      try {
        await tester.perform('beep', function(next) {
          assert.fail('should not be hit');
        });
        assert.fail('Should not be resolved');
      } catch (e) {
        caught = true;
        assert.equal(e.message, 'thrown from before');
      }
  
      assert.ok(caught, 'make sure caught was ran');
  
    });
  
  
    it('will call the catch if thrown on perform', async () => {
  
      const tester = new Understudy();
      let caught = false;
  
      try {
        await tester.perform('beep', function(next) {
          throw new Error('thrown from perform');
        });
        assert.fail('Should not be resolved');
      } catch (e) {
        caught = true;
        assert.equal(e.message, 'thrown from perform');
      }
  
      assert.ok(caught, 'make sure caught was ran');
  
    });
  
    it('will call the catch if thrown on after', (done) => {
  
      const tester = new Understudy();
      let caught = false;
  
      tester.after('beep', () => {
        throw new Error('thrown from after');
      });
  
      tester.perform('beep', function(next) {
        // no op
      }).then(() => assert.fail('Should not be resolved'))
        .catch((e) => {
          caught = true;
          assert.equal(e.message, 'thrown from after');
          done();
        });
  
    });
  
  
    it('will call the catch if the work fn in perform throws', done => {
  
      const tester = new Understudy();
  
      tester.before('beep', () => {
        return new Promise((resovle, reject) => {
          resovle();
        });
      });
  
      tester.perform('beep', function() {
        return new Promise((resolve, reject) => reject(new Error('thrown from peform')));
      })
        .then(() => assert.fail('Should not be resolved'))
        .catch((e) => {
          assert.equal(e.message, 'thrown from peform');
          done();
        });
    });
  
    it('can run a performSync', () => {
      const tester = new Understudy();
  
      const performVal = tester.performSync('test123', {foo: 'bar'}, () => {
        return 'testVal';
      });
  
      assert.equal(performVal, 'testVal', 'perform can run an whatever the work returns will be returned from `perform`');
  
      tester.beforeSync('testABC', (arg) => {
        arg.foo = arg.foo + 'zzz';
      });
  
      const argToMutate = {foo: 'bar'};
      tester.performSync('testABC', argToMutate, () => {});
  
      assert.equal(argToMutate.foo, 'barzzz');
  
      tester.beforeSync('testABC', (arg) => {
        arg.foo = arg.foo + '111';
      });
  
      tester.performSync('testABC', argToMutate, () => {});
      assert.equal(argToMutate.foo, 'barzzzzzz111');
  
    });
  
  });
  