/** * @fileoverview Tests for HTML reporter. * @author Julian Laval */ "use strict"; //------------------------------------------------------------------------------ // Requirements //------------------------------------------------------------------------------ const assert = require("chai").assert; const formatter = require("../../../../lib/cli-engine/formatters/html"); const cheerio = require("cheerio"); //------------------------------------------------------------------------------ // Helpers //------------------------------------------------------------------------------ /** * Run unit tests on the overview section * @param {Object} $ Cheerio instance * @param {Object} args Array of relevant info to be tested * @returns {void} */ function checkOverview($, args) { assert($("#overview").hasClass(args.bgColor), "Check if color is correct"); assert.strictEqual($("#overview span").text(), args.problems, "Check if correct problem totals"); } /** * Run unit tests on the header section * @param {Object} $ Cheerio instance * @param {Object} rowObject Header row being tested * @param {Object} args Array of relevant info to be tested * @returns {void} */ function checkHeaderRow($, rowObject, args) { const row = $(rowObject); assert(row.hasClass(args.bgColor), "Check that background color is correct"); assert.strictEqual(row.attr("data-group"), args.group, "Check that header group is correct"); assert.strictEqual(row.find("th span").text(), args.problems, "Check if correct totals"); assert.strictEqual(row.find("th").html().trim().match(/ [^<]*/u)[0].trim(), args.file, "Check if correctly displays filePath"); } /** * Run unit tests on the content section * @param {Object} $ Cheerio instance * @param {Object} rowObject Content row being tested * @param {Object} args Array of relevant info to be tested * @returns {void} */ function checkContentRow($, rowObject, args) { const row = $(rowObject); assert(row.hasClass(args.group), "Check that linked to correct header"); assert.strictEqual($(row.find("td")[0]).text(), args.lineCol, "Check that line:column is correct"); assert($(row.find("td")[1]).hasClass(args.color), "Check that severity color is correct"); assert.strictEqual($(row.find("td")[2]).html(), args.message, "Check that message is correct"); assert.strictEqual($(row.find("td")[3]).find("a").text(), args.ruleId, "Check that ruleId is correct"); } //------------------------------------------------------------------------------ // Tests //------------------------------------------------------------------------------ describe("formatter:html", () => { describe("when passed a single error message", () => { const rulesMeta = { foo: { type: "problem", docs: { description: "This is rule 'foo'", category: "error", recommended: true, url: "https://eslint.org/docs/rules/foo" }, fixable: "code", messages: { message1: "This is a message for rule 'foo'." } } }; const code = { results: [{ filePath: "foo.js", errorCount: 1, warningCount: 0, messages: [{ message: "Unexpected foo.", severity: 2, line: 5, column: 10, ruleId: "foo", source: "foo" }] }], rulesMeta }; it("should return a string in HTML format with 1 issue in 1 file and styled accordingly", () => { const result = formatter(code.results, { rulesMeta }); const $ = cheerio.load(result); // Check overview checkOverview($, { bgColor: "bg-2", problems: "1 problem (1 error, 0 warnings)" }); // Check rows assert.strictEqual($("tr").length, 2, "Check that there are two (1 header, 1 content)"); assert.strictEqual($("tr[data-group|=\"f\"]").length, 1, "Check that is 1 header row (implying 1 content row)"); checkHeaderRow($, $("tr")[0], { bgColor: "bg-2", group: "f-0", file: "foo.js", problems: "1 problem (1 error, 0 warnings)" }); checkContentRow($, $("tr")[1], { group: "f-0", lineCol: "5:10", color: "clr-2", message: "Unexpected foo.", ruleId: "foo" }); }); it("should not fail if metadata is not available", () => { const result = formatter(code.results); const $ = cheerio.load(result); // Check overview checkOverview($, { bgColor: "bg-2", problems: "1 problem (1 error, 0 warnings)" }); // Check rows assert.strictEqual($("tr").length, 2, "Check that there are two (1 header, 1 content)"); assert.strictEqual($("tr[data-group|=\"f\"]").length, 1, "Check that is 1 header row (implying 1 content row)"); checkHeaderRow($, $("tr")[0], { bgColor: "bg-2", group: "f-0", file: "foo.js", problems: "1 problem (1 error, 0 warnings)" }); checkContentRow($, $("tr")[1], { group: "f-0", lineCol: "5:10", color: "clr-2", message: "Unexpected foo.", ruleId: "foo" }); }); }); describe("when passed a single warning message", () => { const rulesMeta = { foo: { type: "problem", docs: { description: "This is rule 'foo'", category: "error", recommended: true, url: "https://eslint.org/docs/rules/foo" }, fixable: "code", messages: { message1: "This is a message for rule 'foo'." } } }; const code = { results: [{ filePath: "foo.js", errorCount: 0, warningCount: 1, messages: [{ message: "Unexpected foo.", severity: 1, line: 5, column: 10, ruleId: "foo", source: "foo" }] }], rulesMeta }; it("should return a string in HTML format with 1 issue in 1 file and styled accordingly", () => { const result = formatter(code.results, { rulesMeta }); const $ = cheerio.load(result); // Check overview checkOverview($, { bgColor: "bg-1", problems: "1 problem (0 errors, 1 warning)" }); // Check rows assert.strictEqual($("tr").length, 2, "Check that there are two (1 header, 1 content)"); assert.strictEqual($("tr[data-group|=\"f\"]").length, 1, "Check that is 1 header row (implying 1 content row)"); checkHeaderRow($, $("tr")[0], { bgColor: "bg-1", group: "f-0", file: "foo.js", problems: "1 problem (0 errors, 1 warning)" }); checkContentRow($, $("tr")[1], { group: "f-0", lineCol: "5:10", color: "clr-1", message: "Unexpected foo.", ruleId: "foo" }); }); }); describe("when passed a single error message", () => { const rulesMeta = { foo: { type: "problem", docs: { description: "This is rule 'foo'", category: "error", recommended: true, url: "https://eslint.org/docs/rules/foo" }, fixable: "code", messages: { message1: "This is a message for rule 'foo'." } } }; const code = { results: [{ filePath: "foo.js", errorCount: 1, warningCount: 0, messages: [{ message: "Unexpected foo.", severity: 2, line: 5, column: 10, ruleId: "foo", source: "foo" }] }], rulesMeta }; it("should return a string in HTML format with 1 issue in 1 file and styled accordingly", () => { const result = formatter(code.results, { rulesMeta }); const $ = cheerio.load(result); // Check overview checkOverview($, { bgColor: "bg-2", problems: "1 problem (1 error, 0 warnings)" }); // Check rows assert.strictEqual($("tr").length, 2, "Check that there are two (1 header, 1 content)"); assert.strictEqual($("tr[data-group|=\"f\"]").length, 1, "Check that is 1 header row (implying 1 content row)"); checkHeaderRow($, $("tr")[0], { bgColor: "bg-2", group: "f-0", file: "foo.js", problems: "1 problem (1 error, 0 warnings)" }); checkContentRow($, $("tr")[1], { group: "f-0", lineCol: "5:10", color: "clr-2", message: "Unexpected foo.", ruleId: "foo" }); }); }); describe("when passed no error/warning messages", () => { const code = { results: [{ filePath: "foo.js", errorCount: 0, warningCount: 0, messages: [] }] }; it("should return a string in HTML format with 0 issues in 1 file and styled accordingly", () => { const result = formatter(code.results, {}); const $ = cheerio.load(result); // Check overview checkOverview($, { bgColor: "bg-0", problems: "0 problems" }); // Check rows assert.strictEqual($("tr").length, 1, "Check that there is 1 row (header)"); checkHeaderRow($, $("tr")[0], { bgColor: "bg-0", group: "f-0", file: "foo.js", problems: "0 problems" }); }); }); describe("when passed multiple messages", () => { const rulesMeta = { foo: { type: "problem", docs: { description: "This is rule 'foo'", category: "error", recommended: true, url: "https://eslint.org/docs/rules/foo" }, fixable: "code", messages: { message1: "This is a message for rule 'foo'." } }, bar: { type: "suggestion", docs: { description: "This is rule 'bar'", category: "error", recommended: false }, messages: { message1: "This is a message for rule 'bar'." } } }; const code = { results: [{ filePath: "foo.js", errorCount: 1, warningCount: 1, messages: [{ message: "Unexpected foo.", severity: 2, line: 5, column: 10, ruleId: "foo", source: "foo" }, { message: "Unexpected bar.", severity: 1, line: 6, column: 11, ruleId: "bar", source: "bar" }] }], rulesMeta }; it("should return a string in HTML format with 2 issues in 1 file and styled accordingly", () => { const result = formatter(code.results, { rulesMeta }); const $ = cheerio.load(result); // Check overview checkOverview($, { bgColor: "bg-2", problems: "2 problems (1 error, 1 warning)" }); // Check rows assert.strictEqual($("tr").length, 3, "Check that there are two (1 header, 2 content)"); assert.strictEqual($("tr[data-group|=\"f\"]").length, 1, "Check that is 1 header row (implying 2 content row)"); checkHeaderRow($, $("tr")[0], { bgColor: "bg-2", group: "f-0", file: "foo.js", problems: "2 problems (1 error, 1 warning)" }); checkContentRow($, $("tr")[1], { group: "f-0", lineCol: "5:10", color: "clr-2", message: "Unexpected foo.", ruleId: "foo" }); checkContentRow($, $("tr")[2], { group: "f-0", lineCol: "6:11", color: "clr-1", message: "Unexpected bar.", ruleId: "bar" }); }); }); describe("when passed multiple files with 1 error & warning message respectively", () => { const rulesMeta = { foo: { type: "problem", docs: { description: "This is rule 'foo'", category: "error", recommended: true, url: "https://eslint.org/docs/rules/foo" }, fixable: "code", messages: { message1: "This is a message for rule 'foo'." } }, bar: { type: "suggestion", docs: { description: "This is rule 'bar'", category: "error", recommended: false }, messages: { message1: "This is a message for rule 'bar'." } } }; const code = { results: [{ filePath: "foo.js", errorCount: 1, warningCount: 0, messages: [{ message: "Unexpected foo.", severity: 2, line: 5, column: 10, ruleId: "foo", source: "foo" }] }, { filePath: "bar.js", errorCount: 0, warningCount: 1, messages: [{ message: "Unexpected bar.", severity: 1, line: 6, column: 11, ruleId: "bar", source: "bar" }] }], rulesMeta }; it("should return a string in HTML format with 2 issues in 2 files and styled accordingly", () => { const result = formatter(code.results, { rulesMeta }); const $ = cheerio.load(result); // Check overview checkOverview($, { bgColor: "bg-2", problems: "2 problems (1 error, 1 warning)" }); // Check rows assert.strictEqual($("tr").length, 4, "Check that there are two (2 header, 2 content)"); assert.strictEqual($("tr[data-group|=\"f\"]").length, 2, "Check that is 2 header row (implying 2 content row)"); checkHeaderRow($, $("tr")[0], { bgColor: "bg-2", group: "f-0", file: "foo.js", problems: "1 problem (1 error, 0 warnings)" }); checkContentRow($, $("tr")[1], { group: "f-0", lineCol: "5:10", color: "clr-2", message: "Unexpected foo.", ruleId: "foo" }); checkHeaderRow($, $("tr")[2], { bgColor: "bg-1", group: "f-1", file: "bar.js", problems: "1 problem (0 errors, 1 warning)" }); checkContentRow($, $("tr")[3], { group: "f-1", lineCol: "6:11", color: "clr-1", message: "Unexpected bar.", ruleId: "bar" }); }); }); describe("when passed multiple files with 1 warning message each", () => { const rulesMeta = { foo: { type: "problem", docs: { description: "This is rule 'foo'", category: "error", recommended: true, url: "https://eslint.org/docs/rules/foo" }, fixable: "code", messages: { message1: "This is a message for rule 'foo'." } }, bar: { type: "suggestion", docs: { description: "This is rule 'bar'", category: "error", recommended: false }, messages: { message1: "This is a message for rule 'bar'." } } }; const code = { results: [{ filePath: "foo.js", errorCount: 0, warningCount: 1, messages: [{ message: "Unexpected foo.", severity: 1, line: 5, column: 10, ruleId: "foo", source: "foo" }] }, { filePath: "bar.js", errorCount: 0, warningCount: 1, messages: [{ message: "Unexpected bar.", severity: 1, line: 6, column: 11, ruleId: "bar", source: "bar" }] }], rulesMeta }; it("should return a string in HTML format with 2 issues in 2 files and styled accordingly", () => { const result = formatter(code.results, { rulesMeta }); const $ = cheerio.load(result); // Check overview checkOverview($, { bgColor: "bg-1", problems: "2 problems (0 errors, 2 warnings)" }); // Check rows assert.strictEqual($("tr").length, 4, "Check that there are two (2 header, 2 content)"); assert.strictEqual($("tr[data-group|=\"f\"]").length, 2, "Check that is 2 header row (implying 2 content row)"); checkHeaderRow($, $("tr")[0], { bgColor: "bg-1", group: "f-0", file: "foo.js", problems: "1 problem (0 errors, 1 warning)" }); checkContentRow($, $("tr")[1], { group: "f-0", lineCol: "5:10", color: "clr-1", message: "Unexpected foo.", ruleId: "foo" }); checkHeaderRow($, $("tr")[2], { bgColor: "bg-1", group: "f-1", file: "bar.js", problems: "1 problem (0 errors, 1 warning)" }); checkContentRow($, $("tr")[3], { group: "f-1", lineCol: "6:11", color: "clr-1", message: "Unexpected bar.", ruleId: "bar" }); }); }); describe("when passing a single message with illegal characters", () => { const rulesMeta = { foo: { type: "problem", docs: { description: "This is rule 'foo'", category: "error", recommended: true, url: "https://eslint.org/docs/rules/foo" }, fixable: "code", messages: { message1: "This is a message for rule 'foo'." } } }; const code = { results: [{ filePath: "foo.js", errorCount: 1, warningCount: 0, messages: [{ message: "Unexpected <&\"'> foo.", severity: 2, line: 5, column: 10, ruleId: "foo", source: "foo" }] }], rulesMeta }; it("should return a string in HTML format with 1 issue in 1 file", () => { const result = formatter(code.results, { rulesMeta }); const $ = cheerio.load(result); checkContentRow($, $("tr")[1], { group: "f-0", lineCol: "5:10", color: "clr-2", message: "Unexpected <&"'> foo.", ruleId: "foo" }); }); }); describe("when passing a single message with no rule id or message", () => { const code = [{ filePath: "foo.js", errorCount: 1, warningCount: 0, messages: [{ severity: 2, line: 5, column: 10 }] }]; it("should return a string in HTML format with 1 issue in 1 file", () => { const result = formatter(code, {}); const $ = cheerio.load(result); checkContentRow($, $("tr")[1], { group: "f-0", lineCol: "5:10", color: "clr-2", message: "", ruleId: "" }); }); }); describe("when passed a single message with no line or column", () => { const rulesMeta = { foo: { type: "problem", docs: { description: "This is rule 'foo'", category: "error", recommended: true, url: "https://eslint.org/docs/rules/foo" }, fixable: "code", messages: { message1: "This is a message for rule 'foo'." } } }; const code = { results: [{ filePath: "foo.js", errorCount: 1, warningCount: 0, messages: [{ message: "Unexpected foo.", severity: 2, ruleId: "foo", source: "foo" }] }], rulesMeta }; it("should return a string in HTML format with 1 issue in 1 file and styled accordingly", () => { const result = formatter(code.results, { rulesMeta }); const $ = cheerio.load(result); checkContentRow($, $("tr")[1], { group: "f-0", lineCol: "0:0", color: "clr-2", message: "Unexpected foo.", ruleId: "foo" }); }); }); });