'use strict';

var sinon = require('sinon');
var mocha = require('../../lib/mocha');
var Test = mocha.Test;
var Runnable = mocha.Runnable;

describe('Test', function () {
  afterEach(function () {
    sinon.restore();
  });

  describe('.clone()', function () {
    beforeEach(function () {
      this._test = new Test('To be cloned', function () {});
      this._test._timeout = 3043;
      this._test._slow = 101;
      this._test._retries = 3;
      this._test._currentRetry = 1;
      this._test._allowedGlobals = ['foo'];
      this._test.parent = 'foo';
      this._test.file = 'bar';
    });

    it('should copy the title', function () {
      expect(this._test.clone().title, 'to be', 'To be cloned');
    });

    it('should copy the timeout value', function () {
      expect(this._test.clone().timeout(), 'to be', 3043);
    });

    it('should copy the slow value', function () {
      expect(this._test.clone().slow(), 'to be', 101);
    });

    it('should copy the retries value', function () {
      expect(this._test.clone().retries(), 'to be', 3);
    });

    it('should copy the currentRetry value', function () {
      expect(this._test.clone().currentRetry(), 'to be', 1);
    });

    it('should add/keep the retriedTest value', function () {
      var clone1 = this._test.clone();
      expect(clone1.retriedTest(), 'to be', this._test);
      expect(clone1.clone().retriedTest(), 'to be', this._test);
    });

    it('should copy the globals value', function () {
      expect(this._test.clone().globals(), 'not to be empty');
    });

    it('should copy the parent value', function () {
      expect(this._test.clone().parent, 'to be', 'foo');
    });

    it('should copy the file value', function () {
      expect(this._test.clone().file, 'to be', 'bar');
    });
  });

  describe('.reset()', function () {
    beforeEach(function () {
      this._test = new Test('Test to be reset', function () {});
    });

    it('should reset the run state', function () {
      this._test.pending = true;
      this._test.reset();
      expect(this._test.pending, 'to be', false);
    });

    it('should call Runnable.reset', function () {
      var runnableResetStub = sinon.stub(Runnable.prototype, 'reset');
      this._test.reset();
      expect(runnableResetStub, 'was called once');
    });
  });

  describe('.isPending()', function () {
    beforeEach(function () {
      this._test = new Test('Is it skipped', function () {});
    });

    it('should not be pending by default', function () {
      expect(this._test.isPending(), 'not to be', true);
    });

    it('should be pending when marked as such', function () {
      this._test.pending = true;
      expect(this._test.isPending(), 'to be', true);
    });

    it('should be pending when its parent is pending', function () {
      this._test.parent = {
        isPending: function () {
          return true;
        }
      };
      expect(this._test.isPending(), 'to be', true);
    });
  });

  describe('.markOnly()', function () {
    afterEach(function () {
      sinon.restore();
    });

    it('should call appendOnlyTest on parent', function () {
      var test = new Test('foo');
      var spy = sinon.spy();
      test.parent = {
        appendOnlyTest: spy
      };
      test.markOnly();

      expect(spy, 'to have a call exhaustively satisfying', [test]).and(
        'was called once'
      );
    });
  });
});
