From d73fbf2228631d6c468cd24710e2579fe6cb70fd Mon Sep 17 00:00:00 2001 From: fnx Date: Mon, 21 Aug 2023 03:22:22 +0200 Subject: [PATCH] feat: rule tester do not create empty valid or invalid test suites (#17475) * feat: rule-tester do not create empty valid or invalid test suites * chore: fix grammatical errors in test case descriptions * fix: pass an invalid test case when checking for missing valid test cases * chore: make test cases more consistent * chore: actually make tests consistent --- lib/rule-tester/flat-rule-tester.js | 42 ++++++++------ lib/rule-tester/rule-tester.js | 42 ++++++++------ tests/lib/rule-tester/flat-rule-tester.js | 69 +++++++++++++++++++++++ tests/lib/rule-tester/rule-tester.js | 69 +++++++++++++++++++++++ 4 files changed, 186 insertions(+), 36 deletions(-) diff --git a/lib/rule-tester/flat-rule-tester.js b/lib/rule-tester/flat-rule-tester.js index f143873f7bc..f297965ec33 100644 --- a/lib/rule-tester/flat-rule-tester.js +++ b/lib/rule-tester/flat-rule-tester.js @@ -1011,29 +1011,35 @@ class FlatRuleTester { /* * This creates a mocha test suite and pipes all supplied info through * one of the templates above. + * The test suites for valid/invalid are created conditionally as + * test runners (eg. vitest) fail for empty test suites. */ this.constructor.describe(ruleName, () => { - this.constructor.describe("valid", () => { - test.valid.forEach(valid => { - this.constructor[valid.only ? "itOnly" : "it"]( - sanitize(typeof valid === "object" ? valid.name || valid.code : valid), - () => { - testValidTemplate(valid); - } - ); + if (test.valid.length > 0) { + this.constructor.describe("valid", () => { + test.valid.forEach(valid => { + this.constructor[valid.only ? "itOnly" : "it"]( + sanitize(typeof valid === "object" ? valid.name || valid.code : valid), + () => { + testValidTemplate(valid); + } + ); + }); }); - }); + } - this.constructor.describe("invalid", () => { - test.invalid.forEach(invalid => { - this.constructor[invalid.only ? "itOnly" : "it"]( - sanitize(invalid.name || invalid.code), - () => { - testInvalidTemplate(invalid); - } - ); + if (test.invalid.length > 0) { + this.constructor.describe("invalid", () => { + test.invalid.forEach(invalid => { + this.constructor[invalid.only ? "itOnly" : "it"]( + sanitize(invalid.name || invalid.code), + () => { + testInvalidTemplate(invalid); + } + ); + }); }); - }); + } }); } } diff --git a/lib/rule-tester/rule-tester.js b/lib/rule-tester/rule-tester.js index e4dc126783c..a61f4028609 100644 --- a/lib/rule-tester/rule-tester.js +++ b/lib/rule-tester/rule-tester.js @@ -1021,29 +1021,35 @@ class RuleTester { /* * This creates a mocha test suite and pipes all supplied info through * one of the templates above. + * The test suites for valid/invalid are created conditionally as + * test runners (eg. vitest) fail for empty test suites. */ this.constructor.describe(ruleName, () => { - this.constructor.describe("valid", () => { - test.valid.forEach(valid => { - this.constructor[valid.only ? "itOnly" : "it"]( - sanitize(typeof valid === "object" ? valid.name || valid.code : valid), - () => { - testValidTemplate(valid); - } - ); + if (test.valid.length > 0) { + this.constructor.describe("valid", () => { + test.valid.forEach(valid => { + this.constructor[valid.only ? "itOnly" : "it"]( + sanitize(typeof valid === "object" ? valid.name || valid.code : valid), + () => { + testValidTemplate(valid); + } + ); + }); }); - }); + } - this.constructor.describe("invalid", () => { - test.invalid.forEach(invalid => { - this.constructor[invalid.only ? "itOnly" : "it"]( - sanitize(invalid.name || invalid.code), - () => { - testInvalidTemplate(invalid); - } - ); + if (test.invalid.length > 0) { + this.constructor.describe("invalid", () => { + test.invalid.forEach(invalid => { + this.constructor[invalid.only ? "itOnly" : "it"]( + sanitize(invalid.name || invalid.code), + () => { + testInvalidTemplate(invalid); + } + ); + }); }); - }); + } }); } } diff --git a/tests/lib/rule-tester/flat-rule-tester.js b/tests/lib/rule-tester/flat-rule-tester.js index f5cdba967ec..8e1f83af616 100644 --- a/tests/lib/rule-tester/flat-rule-tester.js +++ b/tests/lib/rule-tester/flat-rule-tester.js @@ -2626,4 +2626,73 @@ describe("FlatRuleTester", () => { }); + describe("Optional Test Suites", () => { + let originalRuleTesterDescribe; + let spyRuleTesterDescribe; + + before(() => { + originalRuleTesterDescribe = FlatRuleTester.describe; + spyRuleTesterDescribe = sinon.spy((title, callback) => callback()); + FlatRuleTester.describe = spyRuleTesterDescribe; + }); + after(() => { + FlatRuleTester.describe = originalRuleTesterDescribe; + }); + beforeEach(() => { + spyRuleTesterDescribe.resetHistory(); + ruleTester = new FlatRuleTester(); + }); + + it("should create a test suite with the rule name even if there are no test cases", () => { + ruleTester.run("no-var", require("../../fixtures/testers/rule-tester/no-var"), { + valid: [], + invalid: [] + }); + sinon.assert.calledWith(spyRuleTesterDescribe, "no-var"); + }); + + it("should create a valid test suite if there is a valid test case", () => { + ruleTester.run("no-var", require("../../fixtures/testers/rule-tester/no-var"), { + valid: ["value = 0;"], + invalid: [] + }); + sinon.assert.calledWith(spyRuleTesterDescribe, "valid"); + }); + + it("should not create a valid test suite if there are no valid test cases", () => { + ruleTester.run("no-var", require("../../fixtures/testers/rule-tester/no-var"), { + valid: [], + invalid: [ + { + code: "var value = 0;", + errors: [/^Bad var/u], + output: " value = 0;" + } + ] + }); + sinon.assert.neverCalledWith(spyRuleTesterDescribe, "valid"); + }); + + it("should create an invalid test suite if there is an invalid test case", () => { + ruleTester.run("no-var", require("../../fixtures/testers/rule-tester/no-var"), { + valid: [], + invalid: [ + { + code: "var value = 0;", + errors: [/^Bad var/u], + output: " value = 0;" + } + ] + }); + sinon.assert.calledWith(spyRuleTesterDescribe, "invalid"); + }); + + it("should not create an invalid test suite if there are no invalid test cases", () => { + ruleTester.run("no-var", require("../../fixtures/testers/rule-tester/no-var"), { + valid: ["value = 0;"], + invalid: [] + }); + sinon.assert.neverCalledWith(spyRuleTesterDescribe, "invalid"); + }); + }); }); diff --git a/tests/lib/rule-tester/rule-tester.js b/tests/lib/rule-tester/rule-tester.js index cb1cf346f62..c607e4476a0 100644 --- a/tests/lib/rule-tester/rule-tester.js +++ b/tests/lib/rule-tester/rule-tester.js @@ -2870,4 +2870,73 @@ describe("RuleTester", () => { }); + describe("Optional Test Suites", () => { + let originalRuleTesterDescribe; + let spyRuleTesterDescribe; + + before(() => { + originalRuleTesterDescribe = RuleTester.describe; + spyRuleTesterDescribe = sinon.spy((title, callback) => callback()); + RuleTester.describe = spyRuleTesterDescribe; + }); + after(() => { + RuleTester.describe = originalRuleTesterDescribe; + }); + beforeEach(() => { + spyRuleTesterDescribe.resetHistory(); + ruleTester = new RuleTester(); + }); + + it("should create a test suite with the rule name even if there are no test cases", () => { + ruleTester.run("no-var", require("../../fixtures/testers/rule-tester/no-var"), { + valid: [], + invalid: [] + }); + sinon.assert.calledWith(spyRuleTesterDescribe, "no-var"); + }); + + it("should create a valid test suite if there is a valid test case", () => { + ruleTester.run("no-var", require("../../fixtures/testers/rule-tester/no-var"), { + valid: ["value = 0;"], + invalid: [] + }); + sinon.assert.calledWith(spyRuleTesterDescribe, "valid"); + }); + + it("should not create a valid test suite if there are no valid test cases", () => { + ruleTester.run("no-var", require("../../fixtures/testers/rule-tester/no-var"), { + valid: [], + invalid: [ + { + code: "var value = 0;", + errors: [/^Bad var/u], + output: " value = 0;" + } + ] + }); + sinon.assert.neverCalledWith(spyRuleTesterDescribe, "valid"); + }); + + it("should create an invalid test suite if there is an invalid test case", () => { + ruleTester.run("no-var", require("../../fixtures/testers/rule-tester/no-var"), { + valid: [], + invalid: [ + { + code: "var value = 0;", + errors: [/^Bad var/u], + output: " value = 0;" + } + ] + }); + sinon.assert.calledWith(spyRuleTesterDescribe, "invalid"); + }); + + it("should not create an invalid test suite if there are no invalid test cases", () => { + ruleTester.run("no-var", require("../../fixtures/testers/rule-tester/no-var"), { + valid: ["value = 0;"], + invalid: [] + }); + sinon.assert.neverCalledWith(spyRuleTesterDescribe, "invalid"); + }); + }); });