text: /**
   * @fileoverview Tests for options.
   * @author Sindre Sorhus
   */
  
  "use strict";
  
  //------------------------------------------------------------------------------
  // Requirements
  //------------------------------------------------------------------------------
  
  const assert = require("chai").assert,
      chalk = require("chalk"),
      proxyquire = require("proxyquire"),
      sinon = require("sinon");
  
  /*
   * Chalk protects its methods so we need to inherit from it
   * for Sinon to work.
   */
  const chalkStub = Object.create(chalk, {
      reset: {
          value(str) {
              return chalk.reset(str);
          },
          writable: true
      },
      yellow: {
          value(str) {
              return chalk.yellow(str);
          },
          writable: true
      },
      red: {
          value(str) {
              return chalk.red(str);
          },
          writable: true
      }
  });
  
  chalkStub.yellow.bold = chalk.yellow.bold;
  chalkStub.red.bold = chalk.red.bold;
  
  const formatter = proxyquire("../../../../lib/cli-engine/formatters/stylish", { chalk: chalkStub });
  
  //------------------------------------------------------------------------------
  // Tests
  //------------------------------------------------------------------------------
  
  describe("formatter:stylish", () => {
      const originalColorLevel = chalk.level;
  
      beforeEach(() => {
          chalk.level = 0;
          sinon.spy(chalkStub, "reset");
          sinon.spy(chalkStub.yellow, "bold");
          sinon.spy(chalkStub.red, "bold");
      });
  
      afterEach(() => {
          sinon.verifyAndRestore();
          chalk.level = originalColorLevel;
      });
  
      describe("when passed no messages", () => {
          const code = [{
              filePath: "foo.js",
              messages: [],
              errorCount: 0,
              warningCount: 0
          }];
  
          it("should not return message", () => {
              const result = formatter(code);
  
              assert.strictEqual(result, "");
              assert.strictEqual(chalkStub.reset.callCount, 0);
              assert.strictEqual(chalkStub.yellow.bold.callCount, 0);
              assert.strictEqual(chalkStub.red.bold.callCount, 0);
          });
      });
  
      describe("when passed a single error message", () => {
          const code = [{
              filePath: "foo.js",
              errorCount: 1,
              warningCount: 0,
              fixableErrorCount: 0,
              fixableWarningCount: 0,
              messages: [{
                  message: "Unexpected foo.",
                  severity: 2,
                  line: 5,
                  column: 10,
                  ruleId: "foo"
              }]
          }];
  
          it("should return a string in the correct format", () => {
              const result = formatter(code);
  
              assert.strictEqual(result, "\nfoo.js\n  5:10  error  Unexpected foo  foo\n\n\u2716 1 problem (1 error, 0 warnings)\n");
              assert.strictEqual(chalkStub.reset.callCount, 1);
              assert.strictEqual(chalkStub.yellow.bold.callCount, 0);
              assert.strictEqual(chalkStub.red.bold.callCount, 1);
  
          });
  
          describe("when the error is fixable", () => {
              beforeEach(() => {
                  code[0].fixableErrorCount = 1;
              });
  
              it("should return a string in the correct format", () => {
                  const result = formatter(code);
  
                  assert.strictEqual(result, "\nfoo.js\n  5:10  error  Unexpected foo  foo\n\n\u2716 1 problem (1 error, 0 warnings)\n  1 error and 0 warnings potentially fixable with the `--fix` option.\n");
                  assert.strictEqual(chalkStub.reset.callCount, 1);
                  assert.strictEqual(chalkStub.yellow.bold.callCount, 0);
                  assert.strictEqual(chalkStub.red.bold.callCount, 2);
              });
          });
      });
  
      describe("when passed a single warning message", () => {
          const code = [{
              filePath: "foo.js",
              errorCount: 0,
              warningCount: 1,
              fixableErrorCount: 0,
              fixableWarningCount: 0,
              messages: [{
                  message: "Unexpected foo.",
                  severity: 1,
                  line: 5,
                  column: 10,
                  ruleId: "foo"
              }]
          }];
  
          it("should return a string in the correct format", () => {
              const result = formatter(code);
  
              assert.strictEqual(result, "\nfoo.js\n  5:10  warning  Unexpected foo  foo\n\n\u2716 1 problem (0 errors, 1 warning)\n");
              assert.strictEqual(chalkStub.reset.callCount, 1);
              assert.strictEqual(chalkStub.yellow.bold.callCount, 1);
              assert.strictEqual(chalkStub.red.bold.callCount, 0);
          });
  
          describe("when the error is fixable", () => {
              beforeEach(() => {
                  code[0].fixableWarningCount = 1;
              });
  
              it("should return a string in the correct format", () => {
                  const result = formatter(code);
  
                  assert.strictEqual(result, "\nfoo.js\n  5:10  warning  Unexpected foo  foo\n\n\u2716 1 problem (0 errors, 1 warning)\n  0 errors and 1 warning potentially fixable with the `--fix` option.\n");
                  assert.strictEqual(chalkStub.reset.callCount, 1);
                  assert.strictEqual(chalkStub.yellow.bold.callCount, 2);
                  assert.strictEqual(chalkStub.red.bold.callCount, 0);
              });
  
          });
      });
  
      describe("when passed a message that ends with ' .'", () => {
          const code = [{
              filePath: "foo.js",
              errorCount: 0,
              warningCount: 1,
              fixableErrorCount: 0,
              fixableWarningCount: 0,
              messages: [{
                  message: "Unexpected .",
                  severity: 1,
                  line: 5,
                  column: 10,
                  ruleId: "foo"
              }]
          }];
  
          it("should return a string in the correct format (retaining the ' .')", () => {
              const result = formatter(code);
  
              assert.strictEqual(result, "\nfoo.js\n  5:10  warning  Unexpected .  foo\n\n\u2716 1 problem (0 errors, 1 warning)\n");
              assert.strictEqual(chalkStub.reset.callCount, 1);
              assert.strictEqual(chalkStub.yellow.bold.callCount, 1);
              assert.strictEqual(chalkStub.red.bold.callCount, 0);
          });
      });
  
      describe("when passed a fatal error message", () => {
          const code = [{
              filePath: "foo.js",
              errorCount: 1,
              warningCount: 0,
              messages: [{
                  fatal: true,
                  message: "Unexpected foo.",
                  line: 5,
                  column: 10,
                  ruleId: "foo"
              }]
          }];
  
          it("should return a string in the correct format", () => {
              const result = formatter(code);
  
              assert.strictEqual(result, "\nfoo.js\n  5:10  error  Unexpected foo  foo\n\n\u2716 1 problem (1 error, 0 warnings)\n");
              assert.strictEqual(chalkStub.reset.callCount, 1);
              assert.strictEqual(chalkStub.yellow.bold.callCount, 0);
              assert.strictEqual(chalkStub.red.bold.callCount, 1);
          });
      });
  
      describe("when passed multiple messages", () => {
          const code = [{
              filePath: "foo.js",
              errorCount: 1,
              warningCount: 1,
              messages: [{
                  message: "Unexpected foo.",
                  severity: 2,
                  line: 5,
                  column: 10,
                  ruleId: "foo"
              }, {
                  message: "Unexpected bar.",
                  severity: 1,
                  line: 6,
                  column: 11,
                  ruleId: "bar"
              }]
          }];
  
          it("should return a string with multiple entries", () => {
              const result = formatter(code);
  
              assert.strictEqual(result, "\nfoo.js\n  5:10  error    Unexpected foo  foo\n  6:11  warning  Unexpected bar  bar\n\n\u2716 2 problems (1 error, 1 warning)\n");
              assert.strictEqual(chalkStub.reset.callCount, 1);
              assert.strictEqual(chalkStub.yellow.bold.callCount, 0);
              assert.strictEqual(chalkStub.red.bold.callCount, 1);
          });
      });
  
      describe("when passed multiple files with 1 message each", () => {
          const code = [{
              filePath: "foo.js",
              errorCount: 1,
              warningCount: 0,
              messages: [{
                  message: "Unexpected foo.",
                  severity: 2,
                  line: 5,
                  column: 10,
                  ruleId: "foo"
              }]
          }, {
              errorCount: 0,
              warningCount: 1,
              filePath: "bar.js",
              messages: [{
                  message: "Unexpected bar.",
                  severity: 1,
                  line: 6,
                  column: 11,
                  ruleId: "bar"
              }]
          }];
  
          it("should return a string with multiple entries", () => {
              const result = formatter(code);
  
              assert.strictEqual(result, "\nfoo.js\n  5:10  error  Unexpected foo  foo\n\nbar.js\n  6:11  warning  Unexpected bar  bar\n\n\u2716 2 problems (1 error, 1 warning)\n");
              assert.strictEqual(chalkStub.reset.callCount, 1);
              assert.strictEqual(chalkStub.yellow.bold.callCount, 0);
              assert.strictEqual(chalkStub.red.bold.callCount, 1);
          });
  
          it("should add errorCount", () => {
              code.forEach(c => {
                  c.errorCount = 1;
                  c.warningCount = 0;
              });
  
              const result = formatter(code);
  
              assert.strictEqual(result, "\nfoo.js\n  5:10  error  Unexpected foo  foo\n\nbar.js\n  6:11  warning  Unexpected bar  bar\n\n\u2716 2 problems (2 errors, 0 warnings)\n");
              assert.strictEqual(chalkStub.reset.callCount, 1);
              assert.strictEqual(chalkStub.yellow.bold.callCount, 0);
              assert.strictEqual(chalkStub.red.bold.callCount, 1);
          });
  
          it("should add warningCount", () => {
              code.forEach(c => {
                  c.errorCount = 0;
                  c.warningCount = 1;
              });
  
              const result = formatter(code);
  
              assert.strictEqual(result, "\nfoo.js\n  5:10  error  Unexpected foo  foo\n\nbar.js\n  6:11  warning  Unexpected bar  bar\n\n\u2716 2 problems (0 errors, 2 warnings)\n");
              assert.strictEqual(chalkStub.reset.callCount, 1);
              assert.strictEqual(chalkStub.yellow.bold.callCount, 0);
              assert.strictEqual(chalkStub.red.bold.callCount, 1);
          });
      });
  
      describe("when passed one file not found message", () => {
          const code = [{
              filePath: "foo.js",
              errorCount: 1,
              warningCount: 0,
              messages: [{
                  fatal: true,
                  message: "Couldn't find foo.js."
              }]
          }];
  
          it("should return a string without line and column", () => {
              const result = formatter(code);
  
              assert.strictEqual(result, "\nfoo.js\n  0:0  error  Couldn't find foo.js\n\n\u2716 1 problem (1 error, 0 warnings)\n");
              assert.strictEqual(chalkStub.reset.callCount, 1);
              assert.strictEqual(chalkStub.yellow.bold.callCount, 0);
              assert.strictEqual(chalkStub.red.bold.callCount, 1);
          });
      });
  
      describe("fixable problems", () => {
          it("should not output fixable problems message when no errors or warnings are fixable", () => {
              const code = [{
                  filePath: "foo.js",
                  errorCount: 1,
                  warningCount: 0,
                  fixableErrorCount: 0,
                  fixableWarningCount: 0,
                  messages: [{
                      message: "Unexpected foo.",
                      severity: 2,
                      line: 5,
                      column: 10,
                      ruleId: "foo"
                  }]
              }];
  
              const result = formatter(code);
  
              assert.notInclude(result, "potentially fixable");
          });
  
          it("should output the fixable problems message when errors are fixable", () => {
              const code = [{
                  filePath: "foo.js",
                  errorCount: 1,
                  warningCount: 0,
                  fixableErrorCount: 1,
                  fixableWarningCount: 0,
                  messages: [{
                      message: "Unexpected foo.",
                      severity: 2,
                      line: 5,
                      column: 10,
                      ruleId: "foo"
                  }]
              }];
  
              const result = formatter(code);
  
              assert.include(result, "  1 error and 0 warnings potentially fixable with the `--fix` option.\n");
          });
  
          it("should output fixable problems message when warnings are fixable", () => {
              const code = [{
                  filePath: "foo.js",
                  errorCount: 0,
                  warningCount: 3,
                  fixableErrorCount: 0,
                  fixableWarningCount: 2,
                  messages: [{
                      message: "Unexpected foo."
                  }]
              }];
  
              const result = formatter(code);
  
              assert.include(result, "  0 errors and 2 warnings potentially fixable with the `--fix` option.\n");
          });
  
          it("should output the total number of fixable errors and warnings", () => {
              const code = [{
                  filePath: "foo.js",
                  errorCount: 5,
                  warningCount: 3,
                  fixableErrorCount: 5,
                  fixableWarningCount: 2,
                  messages: [{
                      message: "Unexpected foo."
                  }]
              }, {
                  filePath: "bar.js",
                  errorCount: 4,
                  warningCount: 2,
                  fixableErrorCount: 4,
                  fixableWarningCount: 1,
                  messages: [{
                      message: "Unexpected bar."
                  }]
              }];
  
              const result = formatter(code);
  
              assert.include(result, "  9 errors and 3 warnings potentially fixable with the `--fix` option.\n");
          });
      });
  });
  