"use strict";

const {
  validateLegacyPlugin,
  list,
} = require("../../../lib/cli/run-helpers.cjs");
const Mocha = require("../../../lib/mocha.cjs");

describe("helpers", function () {
  describe("validateLegacyPlugin()", function () {
    describe('when used with "reporter" key', function () {
      it("should disallow an array of names", function () {
        expect(
          () => validateLegacyPlugin({ reporter: ["bar"] }, "reporter"),
          "to throw",
          {
            code: "ERR_MOCHA_INVALID_REPORTER",
            message: /can only be specified once/i,
          },
        );
      });

      it("should fail to recognize an unknown reporter", function () {
        expect(
          () => validateLegacyPlugin({ reporter: "bar" }, "reporter"),
          "to throw",
          {
            code: "ERR_MOCHA_INVALID_REPORTER",
            message: /cannot find module/i,
          },
        );
      });
    });

    describe('when used with an "ui" key', function () {
      it("should disallow an array of names", function () {
        expect(() => validateLegacyPlugin({ ui: ["bar"] }, "ui"), "to throw", {
          code: "ERR_MOCHA_INVALID_INTERFACE",
          message: /can only be specified once/i,
        });
      });

      it("should fail to recognize an unknown interface", function () {
        expect(() => validateLegacyPlugin({ ui: "bar" }, "ui"), "to throw", {
          code: "ERR_MOCHA_INVALID_INTERFACE",
          message: /cannot find module/i,
        });
      });
    });

    describe("when used with an unknown plugin type", function () {
      it("should fail", function () {
        expect(
          () => validateLegacyPlugin({ frog: "bar" }, "frog"),
          "to throw",
          /unknown plugin/i,
        );
      });
    });

    describe("when used with a third-party interface", function () {
      // this test name is referenced in a comment in `lib/mocha.cjs`
      // don't change here without also changing there
      it('should add the interface to "Mocha.interfaces"', function () {
        // let's suppose that `glob` is an interface
        const opts = { ui: "glob" };
        validateLegacyPlugin(opts, "ui", Mocha.interfaces);
        expect(opts.ui, "to equal", "glob");
        expect(Mocha.interfaces, "to satisfy", { glob: require("glob") });
        delete Mocha.interfaces.glob;
      });
    });

    describe("when a plugin throws an exception upon load", function () {
      it("should fail and report the original error", function () {
        expect(
          () =>
            validateLegacyPlugin(
              {
                reporter: require.resolve("./fixtures/bad-module.fixture.js"),
              },
              "reporter",
            ),
          "to throw",
          { message: /wonky/, code: "ERR_MOCHA_INVALID_REPORTER" },
        );
      });

      it('should fail and report the original "MODULE_NOT_FOUND" error.message', function () {
        expect(
          () =>
            validateLegacyPlugin(
              {
                reporter: require.resolve("./fixtures/bad-require.fixture.cjs"),
              },
              "reporter",
            ),
          "to throw",
          {
            message: /Error: Cannot find module 'fake'/,
            code: "ERR_MOCHA_INVALID_REPORTER",
          },
        );
      });
    });
  });

  describe("list()", function () {
    describe("when provided a flat array", function () {
      it("should return a flat array", function () {
        expect(list(["foo", "bar"]), "to equal", ["foo", "bar"]);
      });
    });
    describe("when provided a nested array", function () {
      it("should return a flat array", function () {
        expect(list([["foo", "bar"], "baz"]), "to equal", [
          "foo",
          "bar",
          "baz",
        ]);
      });
    });
    describe("when given a comma-delimited string", function () {
      it("should return a flat array", function () {
        expect(list("foo,bar"), "to equal", ["foo", "bar"]);
      });
    });
  });
});
