"use strict";

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

var JSONStream = reporters.JSONStream;
var createMockRunner = helpers.createMockRunner;
var makeExpectedTest = helpers.makeExpectedTest;
var makeRunReporter = helpers.createRunReporterFunction;

var EVENT_RUN_BEGIN = events.EVENT_RUN_BEGIN;
var EVENT_RUN_END = events.EVENT_RUN_END;
var EVENT_TEST_FAIL = events.EVENT_TEST_FAIL;
var EVENT_TEST_PASS = events.EVENT_TEST_PASS;

describe("JSON Stream reporter", function () {
  var runReporter = makeRunReporter(JSONStream);
  var expectedTitle = "some title";
  var expectedFullTitle = "full title";
  var expectedFile = "someTest.spec.js";
  var expectedDuration = 1000;
  var currentRetry = 1;
  var expectedSpeed = "fast";
  var expectedTest = makeExpectedTest(
    expectedTitle,
    expectedFullTitle,
    expectedFile,
    expectedDuration,
    currentRetry,
    expectedSpeed,
  );
  var expectedErrorMessage = "error message";
  var expectedErrorStack = "error stack";
  var expectedError = {
    message: expectedErrorMessage,
  };

  describe("event handlers", function () {
    describe("on 'start' event", function () {
      it("should write stringified start with expected total", async function () {
        var runner = createMockRunner("start", EVENT_RUN_BEGIN);
        var expectedTotal = 12;
        runner.total = expectedTotal;
        var options = {};
        var { stdout } = await runReporter({}, runner, options);

        expect(
          stdout[0],
          "to equal",
          '["start",{"total":' + expectedTotal + "}]\n",
        );
      });
    });

    describe("on 'pass' event", function () {
      it("should write stringified test data", async function () {
        var runner = createMockRunner(
          "pass",
          EVENT_TEST_PASS,
          null,
          null,
          expectedTest,
        );
        var options = {};
        var { stdout } = await runReporter({}, runner, options);

        expect(
          stdout[0],
          "to equal",
          '["pass",{"title":' +
            `"${expectedTitle}"` +
            ',"fullTitle":' +
            `"${expectedFullTitle}"` +
            ',"file":' +
            `"${expectedFile}"` +
            ',"duration":' +
            expectedDuration +
            ',"currentRetry":' +
            currentRetry +
            ',"speed":' +
            `"${expectedSpeed}"` +
            "}]\n",
        );
      });
    });

    describe("on 'fail' event", function () {
      describe("when error stack exists", function () {
        it("should write stringified test data with error data", async function () {
          expectedError.stack = expectedErrorStack;
          var runner = createMockRunner(
            "fail two args",
            EVENT_TEST_FAIL,
            null,
            null,
            expectedTest,
            expectedError,
          );
          var options = {};
          var { stdout } = await runReporter({}, runner, options);

          expect(
            stdout[0],
            "to equal",
            '["fail",{"title":' +
              `"${expectedTitle}"` +
              ',"fullTitle":' +
              `"${expectedFullTitle}"` +
              ',"file":' +
              `"${expectedFile}"` +
              ',"duration":' +
              expectedDuration +
              ',"currentRetry":' +
              currentRetry +
              ',"speed":' +
              `"${expectedSpeed}"` +
              ',"err":' +
              `"${expectedErrorMessage}"` +
              ',"stack":' +
              `"${expectedErrorStack}"` +
              "}]\n",
          );
        });
      });

      describe("when error stack does not exist", function () {
        it("should write stringified test data with error data", async function () {
          expectedError.stack = null;
          var runner = createMockRunner(
            "fail two args",
            EVENT_TEST_FAIL,
            null,
            null,
            expectedTest,
            expectedError,
          );
          var options = {};
          var { stdout } = await runReporter(this, runner, options);

          expect(
            stdout[0],
            "to equal",
            '["fail",{"title":' +
              `"${expectedTitle}"` +
              ',"fullTitle":' +
              `"${expectedFullTitle}"` +
              ',"file":' +
              `"${expectedFile}"` +
              ',"duration":' +
              expectedDuration +
              ',"currentRetry":' +
              currentRetry +
              ',"speed":' +
              `"${expectedSpeed}"` +
              ',"err":' +
              `"${expectedErrorMessage}"` +
              ',"stack":null}]\n',
          );
        });
      });
    });

    describe("on 'end' event", function () {
      it("should write summary statistics", async function () {
        var runner = createMockRunner("end", EVENT_RUN_END);
        var options = {};
        var { stdout } = await runReporter(this, runner, options);
        expect(stdout[0], "to match", /end/);
      });
    });
  });
});
