"use strict";

var sinon = require("sinon");
var events = require("../../").Runner.constants;
var helpers = require("./helpers.cjs");
var reporters = require("../../").reporters;

var Base = reporters.Base;
var Progress = reporters.Progress;
var createMockRunner = helpers.createMockRunner;
var makeRunReporter = helpers.createRunReporterFunction;

var EVENT_RUN_BEGIN = events.EVENT_RUN_BEGIN;
var EVENT_RUN_END = events.EVENT_RUN_END;
var EVENT_TEST_END = events.EVENT_TEST_END;

describe("Progress reporter", function () {
  var runReporter = makeRunReporter(Progress);
  var noop = function () {};

  afterEach(function () {
    sinon.restore();
  });

  describe("event handlers", function () {
    describe("on 'start' event", function () {
      it("should call cursor hide", async function () {
        var hideCursorStub = sinon.stub(Base.cursor, "hide");

        var runner = createMockRunner("start", EVENT_RUN_BEGIN);
        var options = {};
        await runReporter({}, runner, options);
        sinon.restore();

        expect(hideCursorStub.called, "to be true");
      });
    });

    describe("on 'test end' event", function () {
      describe("when line has changed", function () {
        it("should write expected progress of open and close options", async function () {
          var crCursorStub = sinon.stub(Base.cursor, "CR").callsFake(noop);
          sinon.stub(Base, "useColors").value(false);
          sinon.stub(Base.window, "width").value(5);

          var expectedTotal = 12;
          var expectedOpen = "OpEn";
          var expectedClose = "cLoSe";
          var expectedIncomplete = "iNcOmPlEtE";
          var expectedOptions = {
            open: expectedOpen,
            complete: "cOmPlEtE",
            incomplete: expectedIncomplete,
            close: expectedClose,
          };

          var runner = createMockRunner("test end", EVENT_TEST_END);
          runner.total = expectedTotal;
          var options = {
            reporterOptions: expectedOptions,
          };
          var { stdout } = await runReporter({}, runner, options);
          sinon.restore();

          var expectedArray = [
            "\u001b[J",
            "  " + expectedOpen,
            "",
            expectedIncomplete,
            expectedClose,
          ];

          expect(crCursorStub.called, "to be true");
          expect(stdout, "to equal", expectedArray);
        });
      });

      describe("when line has not changed", function () {
        it("should not write anything", async function () {
          sinon.stub(Base, "useColors").value(false);
          sinon.stub(Base.cursor, "CR").callsFake(noop);
          sinon.stub(Base.window, "width").value(-3);

          var expectedTotal = 1;
          var runner = createMockRunner("test end", EVENT_TEST_END);
          runner.total = expectedTotal;
          var options = {};
          var { stdout } = await runReporter({}, runner, options);
          sinon.restore();

          expect(stdout, "to equal", []);
        });
      });
    });

    describe("on 'end' event", function () {
      it("should call cursor show and epilogue", async function () {
        var showCursorStub = sinon.stub(Base.cursor, "show");
        var fakeThis = {
          epilogue: sinon.spy(),
        };
        var runner = createMockRunner("end", EVENT_RUN_END);
        var options = {};
        await runReporter(fakeThis, runner, options);
        sinon.restore();

        expect(fakeThis.epilogue.calledOnce, "to be true");
        expect(showCursorStub.called, "to be true");
      });
    });
  });
});
