From d21ff6053e15f9320d07015c41382986bb7d5b62 Mon Sep 17 00:00:00 2001 From: nayounsang Date: Thu, 5 Jun 2025 18:06:20 +0900 Subject: [PATCH 1/2] test: flatten dynamic test cases to hand-written --- .../tests/rules/no-base-to-string.test.ts | 304 +++++++++++++++--- 1 file changed, 267 insertions(+), 37 deletions(-) diff --git a/packages/eslint-plugin/tests/rules/no-base-to-string.test.ts b/packages/eslint-plugin/tests/rules/no-base-to-string.test.ts index f0fe39979c4d..d29c5af52891 100644 --- a/packages/eslint-plugin/tests/rules/no-base-to-string.test.ts +++ b/packages/eslint-plugin/tests/rules/no-base-to-string.test.ts @@ -13,55 +13,285 @@ const ruleTester = new RuleTester({ }, }); -const literalListBasic: string[] = [ - "''", - "'text'", - 'true', - 'false', - '1', - '1n', - '[]', - '/regex/', -]; - -const literalListNeedParen: string[] = [ - "__dirname === 'foobar'", - '{}.constructor()', - '() => {}', - 'function() {}', -]; - -const literalList = [...literalListBasic, ...literalListNeedParen]; - -const literalListWrapped = [ - ...literalListBasic, - ...literalListNeedParen.map(i => `(${i})`), -]; +/** + * ref: https://github.com/typescript-eslint/typescript-eslint/issues/11043 + * Be careful with dynamic test case generation. + * Iterate based on the following cases: + * 1. literalListBasic + * ``` + [ + "''", + "'text'", + 'true', + 'false', + '1', + '1n', + '[]', + '/regex/', + ]; + * ``` + * 2. literalListNeedParen + * ``` + [ + "__dirname === 'foobar'", + '{}.constructor()', + '() => {}', + 'function() {}', + ]; + * ``` + */ ruleTester.run('no-base-to-string', rule, { valid: [ // template - ...literalList.map(i => `\`\${${i}}\`;`), + "`${''}`;", + "`${'text'}`;", + '`${true}`;', + '`${false}`;', + '`${1}`;', + '`${1n}`;', + '`${[]}`;', + '`${/regex/}`;', + "`${__dirname === 'foobar'}`;", + '`${{}.constructor()}`;', + '`${() => {}}`;', + '`${function () {}}`;', // operator + += - ...literalListWrapped.flatMap(l => - literalListWrapped.map(r => `${l} + ${r};`), - ), + "'' + '';", + "'' + 'text';", + "'' + true;", + "'' + false;", + "'' + 1;", + "'' + 1n;", + "'' + [];", + "'' + /regex/;", + "'' + (__dirname === 'foobar');", + "'' + {}.constructor();", + "'' + (() => {});", + "'' + function () {};", + "'text' + '';", + "'text' + 'text';", + "'text' + true;", + "'text' + false;", + "'text' + 1;", + "'text' + 1n;", + "'text' + [];", + "'text' + /regex/;", + "'text' + (__dirname === 'foobar');", + "'text' + {}.constructor();", + "'text' + (() => {});", + "'text' + function () {};", + "true + '';", + "true + 'text';", + 'true + true;', + 'true + false;', + 'true + 1;', + 'true + 1n;', + 'true + [];', + 'true + /regex/;', + "true + (__dirname === 'foobar');", + 'true + {}.constructor();', + 'true + (() => {});', + 'true + function () {};', + "false + '';", + "false + 'text';", + 'false + true;', + 'false + false;', + 'false + 1;', + 'false + 1n;', + 'false + [];', + 'false + /regex/;', + "false + (__dirname === 'foobar');", + 'false + {}.constructor();', + 'false + (() => {});', + 'false + function () {};', + "1 + '';", + "1 + 'text';", + '1 + true;', + '1 + false;', + '1 + 1;', + '1 + 1n;', + '1 + [];', + '1 + /regex/;', + "1 + (__dirname === 'foobar');", + '1 + {}.constructor();', + '1 + (() => {});', + '1 + function () {};', + "1n + '';", + "1n + 'text';", + '1n + true;', + '1n + false;', + '1n + 1;', + '1n + 1n;', + '1n + [];', + '1n + /regex/;', + "1n + (__dirname === 'foobar');", + '1n + {}.constructor();', + '1n + (() => {});', + '1n + function () {};', + "[] + '';", + "[] + 'text';", + '[] + true;', + '[] + false;', + '[] + 1;', + '[] + 1n;', + '[] + [];', + '[] + /regex/;', + "[] + (__dirname === 'foobar');", + '[] + {}.constructor();', + '[] + (() => {});', + '[] + function () {};', + "/regex/ + '';", + "/regex/ + 'text';", + '/regex/ + true;', + '/regex/ + false;', + '/regex/ + 1;', + '/regex/ + 1n;', + '/regex/ + [];', + '/regex/ + /regex/;', + "/regex/ + (__dirname === 'foobar');", + '/regex/ + {}.constructor();', + '/regex/ + (() => {});', + '/regex/ + function () {};', + "(__dirname === 'foobar') + '';", + "(__dirname === 'foobar') + 'text';", + "(__dirname === 'foobar') + true;", + "(__dirname === 'foobar') + false;", + "(__dirname === 'foobar') + 1;", + "(__dirname === 'foobar') + 1n;", + "(__dirname === 'foobar') + [];", + "(__dirname === 'foobar') + /regex/;", + "(__dirname === 'foobar') + (__dirname === 'foobar');", + "(__dirname === 'foobar') + {}.constructor();", + "(__dirname === 'foobar') + (() => {});", + "(__dirname === 'foobar') + function () {};", + "({}).constructor() + '';", + "({}).constructor() + 'text';", + '({}).constructor() + true;', + '({}).constructor() + false;', + '({}).constructor() + 1;', + '({}).constructor() + 1n;', + '({}).constructor() + [];', + '({}).constructor() + /regex/;', + "({}).constructor() + (__dirname === 'foobar');", + '({}).constructor() + {}.constructor();', + '({}).constructor() + (() => {});', + '({}).constructor() + function () {};', + "(() => {}) + '';", + "(() => {}) + 'text';", + '(() => {}) + true;', + '(() => {}) + false;', + '(() => {}) + 1;', + '(() => {}) + 1n;', + '(() => {}) + [];', + '(() => {}) + /regex/;', + "(() => {}) + (__dirname === 'foobar');", + '(() => {}) + {}.constructor();', + '(() => {}) + (() => {});', + '(() => {}) + function () {};', + "(function () {}) + '';", + "(function () {}) + 'text';", + '(function () {}) + true;', + '(function () {}) + false;', + '(function () {}) + 1;', + '(function () {}) + 1n;', + '(function () {}) + [];', + '(function () {}) + /regex/;', + "(function () {}) + (__dirname === 'foobar');", + '(function () {}) + {}.constructor();', + '(function () {}) + (() => {});', + '(function () {}) + function () {};', // toString() - ...literalListWrapped.map(i => `${i === '1' ? `(${i})` : i}.toString();`), + "''.toString();", + "'text'.toString();", + 'true.toString();', + 'false.toString();', + '(1).toString();', + '1n.toString();', + '[].toString();', + '/regex/.toString();', + "(__dirname === 'foobar').toString();", + '({}).constructor().toString();', + '(() => {}).toString();', + '(function () {}).toString();', // variable toString() and template - ...literalList.map( - i => ` - let value = ${i}; - value.toString(); - let text = \`\${value}\`; - `, - ), + ` + let value = ''; + value.toString(); + let text = \`\${value}\`; + `, + ` + let value = 'text'; + value.toString(); + let text = \`\${value}\`; + `, + ` + let value = true; + value.toString(); + let text = \`\${value}\`; + `, + ` + let value = false; + value.toString(); + let text = \`\${value}\`; + `, + ` + let value = 1; + value.toString(); + let text = \`\${value}\`; + `, + ` + let value = 1n; + value.toString(); + let text = \`\${value}\`; + `, + ` + let value = []; + value.toString(); + let text = \`\${value}\`; + `, + ` + let value = /regex/; + value.toString(); + let text = \`\${value}\`; + `, + ` + let value = __dirname === 'foobar'; + value.toString(); + let text = \`\${value}\`; + `, + ` + let value = {}.constructor(); + value.toString(); + let text = \`\${value}\`; + `, + ` + let value = () => {}; + value.toString(); + let text = \`\${value}\`; + `, + ` + let value = function () {}; + value.toString(); + let text = \`\${value}\`; + `, // String() - ...literalList.map(i => `String(${i});`), + "String('');", + "String('text');", + 'String(true);', + 'String(false);', + 'String(1);', + 'String(1n);', + 'String([]);', + 'String(/regex/);', + "String(__dirname === 'foobar');", + 'String({}.constructor());', + 'String(() => {});', + 'String(function () {});', ` function someFunction() {} someFunction.toString(); From 03160f9ec1999e19ae613a13d82c648c45408fbe Mon Sep 17 00:00:00 2001 From: nayounsang Date: Thu, 12 Jun 2025 01:53:29 +0900 Subject: [PATCH 2/2] refactor: remove dupe tc in + op --- .../tests/rules/no-base-to-string.test.ts | 111 +++--------------- 1 file changed, 16 insertions(+), 95 deletions(-) diff --git a/packages/eslint-plugin/tests/rules/no-base-to-string.test.ts b/packages/eslint-plugin/tests/rules/no-base-to-string.test.ts index d29c5af52891..5a8cd58742ae 100644 --- a/packages/eslint-plugin/tests/rules/no-base-to-string.test.ts +++ b/packages/eslint-plugin/tests/rules/no-base-to-string.test.ts @@ -19,28 +19,27 @@ const ruleTester = new RuleTester({ * Iterate based on the following cases: * 1. literalListBasic * ``` - [ - "''", - "'text'", - 'true', - 'false', - '1', - '1n', - '[]', - '/regex/', - ]; +[ + "''", + "'text'", + 'true', + 'false', + '1', + '1n', + '[]', + '/regex/', +]; * ``` * 2. literalListNeedParen * ``` - [ - "__dirname === 'foobar'", - '{}.constructor()', - '() => {}', - 'function() {}', - ]; +[ + "__dirname === 'foobar'", + '{}.constructor()', + '() => {}', + 'function() {}', +]; * ``` */ - ruleTester.run('no-base-to-string', rule, { valid: [ // template @@ -58,7 +57,6 @@ ruleTester.run('no-base-to-string', rule, { '`${function () {}}`;', // operator + += - "'' + '';", "'' + 'text';", "'' + true;", "'' + false;", @@ -70,8 +68,6 @@ ruleTester.run('no-base-to-string', rule, { "'' + {}.constructor();", "'' + (() => {});", "'' + function () {};", - "'text' + '';", - "'text' + 'text';", "'text' + true;", "'text' + false;", "'text' + 1;", @@ -82,9 +78,6 @@ ruleTester.run('no-base-to-string', rule, { "'text' + {}.constructor();", "'text' + (() => {});", "'text' + function () {};", - "true + '';", - "true + 'text';", - 'true + true;', 'true + false;', 'true + 1;', 'true + 1n;', @@ -94,10 +87,6 @@ ruleTester.run('no-base-to-string', rule, { 'true + {}.constructor();', 'true + (() => {});', 'true + function () {};', - "false + '';", - "false + 'text';", - 'false + true;', - 'false + false;', 'false + 1;', 'false + 1n;', 'false + [];', @@ -106,11 +95,6 @@ ruleTester.run('no-base-to-string', rule, { 'false + {}.constructor();', 'false + (() => {});', 'false + function () {};', - "1 + '';", - "1 + 'text';", - '1 + true;', - '1 + false;', - '1 + 1;', '1 + 1n;', '1 + [];', '1 + /regex/;', @@ -118,90 +102,27 @@ ruleTester.run('no-base-to-string', rule, { '1 + {}.constructor();', '1 + (() => {});', '1 + function () {};', - "1n + '';", - "1n + 'text';", - '1n + true;', - '1n + false;', - '1n + 1;', - '1n + 1n;', '1n + [];', '1n + /regex/;', "1n + (__dirname === 'foobar');", '1n + {}.constructor();', '1n + (() => {});', '1n + function () {};', - "[] + '';", - "[] + 'text';", - '[] + true;', - '[] + false;', - '[] + 1;', - '[] + 1n;', - '[] + [];', '[] + /regex/;', "[] + (__dirname === 'foobar');", '[] + {}.constructor();', '[] + (() => {});', '[] + function () {};', - "/regex/ + '';", - "/regex/ + 'text';", - '/regex/ + true;', - '/regex/ + false;', - '/regex/ + 1;', - '/regex/ + 1n;', - '/regex/ + [];', - '/regex/ + /regex/;', "/regex/ + (__dirname === 'foobar');", '/regex/ + {}.constructor();', '/regex/ + (() => {});', '/regex/ + function () {};', - "(__dirname === 'foobar') + '';", - "(__dirname === 'foobar') + 'text';", - "(__dirname === 'foobar') + true;", - "(__dirname === 'foobar') + false;", - "(__dirname === 'foobar') + 1;", - "(__dirname === 'foobar') + 1n;", - "(__dirname === 'foobar') + [];", - "(__dirname === 'foobar') + /regex/;", - "(__dirname === 'foobar') + (__dirname === 'foobar');", "(__dirname === 'foobar') + {}.constructor();", "(__dirname === 'foobar') + (() => {});", "(__dirname === 'foobar') + function () {};", - "({}).constructor() + '';", - "({}).constructor() + 'text';", - '({}).constructor() + true;', - '({}).constructor() + false;', - '({}).constructor() + 1;', - '({}).constructor() + 1n;', - '({}).constructor() + [];', - '({}).constructor() + /regex/;', - "({}).constructor() + (__dirname === 'foobar');", - '({}).constructor() + {}.constructor();', '({}).constructor() + (() => {});', '({}).constructor() + function () {};', - "(() => {}) + '';", - "(() => {}) + 'text';", - '(() => {}) + true;', - '(() => {}) + false;', - '(() => {}) + 1;', - '(() => {}) + 1n;', - '(() => {}) + [];', - '(() => {}) + /regex/;', - "(() => {}) + (__dirname === 'foobar');", - '(() => {}) + {}.constructor();', - '(() => {}) + (() => {});', '(() => {}) + function () {};', - "(function () {}) + '';", - "(function () {}) + 'text';", - '(function () {}) + true;', - '(function () {}) + false;', - '(function () {}) + 1;', - '(function () {}) + 1n;', - '(function () {}) + [];', - '(function () {}) + /regex/;', - "(function () {}) + (__dirname === 'foobar');", - '(function () {}) + {}.constructor();', - '(function () {}) + (() => {});', - '(function () {}) + function () {};', // toString() "''.toString();",