Repository: eslint/eslint
File: lib/rule-tester/rule-tester.js (JavaScript)

Code before:
) {
	assert.ok(
		typeof value === "string" || typeof value === "undefined",
		message,
	);
}

/**
 * Asserts that a value is an object.
 * If the value is not an object, it throws an assertion error.
 * @param {any} value The value to check.
 * @param {string?} message The error message to display if the value is not an object.
 * @returns {void}
 */
function assertObject(value, message = "Value must be an object") {
	assert.ok(value && typeof value === "object", message);
}

/**
 * Asserts that a value is a string.
 * If the value is not a string, it throws an assertion error.
 * @param {any} value The value to check.
 * @param {string?} message The error message to display if the value is not a string.
 * @returns {void}
 */
function assertString(value, message = "Value must be a string") {
	assert.ok(typeof value === "string", message);
}

/**
 * Asserts that a value is a boolean or undefined.
 * If the value is not a boolean or undefined, it throws an assertion error.
 * @param {any} value The value to check.
 * @param {string?} message The error message to display if the value is not a boolean or undefined.
 * @returns {void}
 */
function assertBoolOrUndefined(
	value,
	message = "Value must be a boolean or undefined",
) {
	assert.ok(
		typeof value === "boolean" || typeof value === "undefined",
		message,
	);
}

/**
 * Asserts that a value is a function or undefined.
 * If the value is not a function or undefined, it throws an assertion error.
 * @param {any} value The value to check.
 * @param {string?} message The error message to display if the value is not a function or undefined.

Review comment (refactor):
This function and the next three functions would be unnecessary with the refactoring mentioned below as it would be only called once.

Code after:
 * @param {number | string[]} errors The `errors` property of the invalid test case.
 * @param {string} ruleName The name of the rule being tested.
 * @returns {void}
 */
function assertErrorsProperty(errors, ruleName) {
	const isNumber = typeof errors === "number";
	const isArray = Array.isArray(errors);

	if (!isNumber && !isArray) {
		if (errors === void 0) {
			assert.fail(
				`Did not specify errors for an invalid test of ${ruleName}`,
			);
		} else {
			assert.fail(
				`Invalid 'errors' property for invalid test of ${ruleName}: expected a number or an array but got ${
					errors === null ? "null" : typeof errors
				}`,
			);
		}
	}

	if (isArray) {
		assert.ok(
			errors.length !== 0,
			"Invalid cases must have at least one error",
		);
	} else {
		assert.ok(
			errors > 0,
			"Invalid cases must have 'error' value greater than 0",
		);
	}
}

/**
 * Check if this test case is a duplicate of one we have seen before.
 * @param {Object} item test case object
 * @param {Set<string>} seenTestCases set of serialized test cases we have seen so far (managed by this function)
 * @returns {void}
 */
function checkDuplicateTestCase(item, seenTestCases) {
	if (!isSerializable(item)) {
		/*
		 * If we can't serialize a test case (because it contains a function, RegExp, etc), skip the check.
		 * This might happen with properties like: options, plugins, settings, languageOptions.parser, languageOptions.parserOptions.
		 */
		return;
	}

	const serializedTestCase = stringify(item, {