From 3c4ba8f56bc6059d867289e0a6b02c730255794b Mon Sep 17 00:00:00 2001 From: Julien Wajsberg Date: Thu, 11 Feb 2021 17:59:03 +0000 Subject: [PATCH] Bug 1690631 - Add string matching helpers to Assert.jsm r=Gijs This adds Assert.stringContains and Assert.stringMatches. Differential Revision: https://phabricator.services.mozilla.com/D104254 --- testing/modules/Assert.jsm | 80 ++++++++++++++++++- .../tests/browser/browser_test_assert.js | 4 + testing/modules/tests/xpcshell/test_assert.js | 23 ++++++ .../lib/configs/browser-test.js | 2 + 4 files changed, 108 insertions(+), 1 deletion(-) diff --git a/testing/modules/Assert.jsm b/testing/modules/Assert.jsm index ec0ce3cb5310..c98aa3c14992 100644 --- a/testing/modules/Assert.jsm +++ b/testing/modules/Assert.jsm @@ -424,7 +424,7 @@ function expectedException(actual, expected) { * * @param block * (function) Function block to evaluate and catch eventual thrown errors - * @param expected (optional) + * @param expected * (mixed) This parameter can be either a RegExp or a function. The * function is either the error type's constructor, or it's a method that returns a boolean * that describes the test outcome. @@ -596,3 +596,81 @@ proto.less = function less(lhs, rhs, message) { proto.lessOrEqual = function lessOrEqual(lhs, rhs, message) { compareNumbers.call(this, lhs > rhs, lhs, rhs, message, "<="); }; + +/** + * The lhs must be a string that matches the rhs regular expression. + * rhs can be specified either as a string or a RegExp object. If specified as a + * string it will be interpreted as a regular expression so take care to escape + * special characters such as "?" or "(" if you need the actual characters. + * + * @param lhs + * (string) The string to be tested. + * @param rhs + * (string | RegExp) The regular expression that the string will be + * tested with. Note that if passed as a string, this will be interpreted + * as a regular expression. + * @param message (optional) + * (string) Short explanation of the comparison result + */ +proto.stringMatches = function stringMatches(lhs, rhs, message) { + if (typeof rhs != "string" && !instanceOf(rhs, "RegExp")) { + this.report( + true, + lhs, + String(rhs), + `Expected a string or a RegExp for rhs, but "${rhs}" isn't a string or a RegExp object.` + ); + return; + } + + if (typeof lhs != "string") { + this.report( + true, + lhs, + String(rhs), + `Expected a string for lhs, but "${lhs}" isn't a string.` + ); + return; + } + + if (typeof rhs == "string") { + try { + rhs = new RegExp(rhs); + } catch { + this.report( + true, + lhs, + rhs, + `Expected a valid regular expression for rhs, but "${rhs}" isn't one.` + ); + return; + } + } + + const isCorrect = rhs.test(lhs); + this.report(!isCorrect, lhs, rhs.toString(), message, "matches"); +}; + +/** + * The lhs must be a string that contains the rhs string. + * + * @param lhs + * (string) The string to be tested. + * @param rhs + * (string) The string to be found. + * @param message (optional) + * (string) Short explanation of the comparison result + */ +proto.stringContains = function stringContains(lhs, rhs, message) { + if (typeof lhs != "string" || typeof rhs != "string") { + this.report( + true, + lhs, + rhs, + `Expected a string for both lhs and rhs, but either "${lhs}" or "${rhs}" is not a string.` + ); + } + + const isCorrect = lhs.includes(rhs); + this.report(!isCorrect, lhs, rhs, message, "includes"); +}; diff --git a/testing/modules/tests/browser/browser_test_assert.js b/testing/modules/tests/browser/browser_test_assert.js index f331f3224282..ea0823e60de1 100644 --- a/testing/modules/tests/browser/browser_test_assert.js +++ b/testing/modules/tests/browser/browser_test_assert.js @@ -14,4 +14,8 @@ function test() { var func = is; func(1, 1, "pass indirect is"); + + stringMatches("hello world", /llo\s/); + stringMatches("hello world", "llo\\s"); + stringContains("hello world", "llo"); } diff --git a/testing/modules/tests/xpcshell/test_assert.js b/testing/modules/tests/xpcshell/test_assert.js index 14fd38e8834f..c26265d88849 100644 --- a/testing/modules/tests/xpcshell/test_assert.js +++ b/testing/modules/tests/xpcshell/test_assert.js @@ -409,6 +409,29 @@ function run_test() { } assert.equal(message, "AssertionError: 2 <= 1"); + /* ---- stringMatches ---- */ + assert.stringMatches("hello world", /llo\s/); + assert.stringMatches("hello world", "llo\\s"); + assert.throws( + () => assert.stringMatches("hello world", /foo/), + /^AssertionError: "hello world" matches "\/foo\/"/ + ); + assert.throws( + () => assert.stringMatches(5, /foo/), + /^AssertionError: Expected a string for lhs, but "5" isn't a string./ + ); + assert.throws( + () => assert.stringMatches("foo bar", "+"), + /^AssertionError: Expected a valid regular expression for rhs, but "\+" isn't one./ + ); + + /* ---- stringContains ---- */ + assert.stringContains("hello world", "llo"); + assert.throws( + () => assert.stringContains(5, "foo"), + /^AssertionError: Expected a string for both lhs and rhs, but either "5" or "foo" is not a string./ + ); + run_next_test(); } diff --git a/tools/lint/eslint/eslint-plugin-mozilla/lib/configs/browser-test.js b/tools/lint/eslint/eslint-plugin-mozilla/lib/configs/browser-test.js index 596815c85020..d62b18f39045 100644 --- a/tools/lint/eslint/eslint-plugin-mozilla/lib/configs/browser-test.js +++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/configs/browser-test.js @@ -45,6 +45,8 @@ module.exports = { registerCleanupFunction: false, requestLongerTimeout: false, setExpectedFailuresForSelfTest: false, + stringContains: false, + stringMatches: false, todo: false, todo_is: false, todo_isnot: false,