From 5101d3385872760de6fc44a28056641467ef48cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johan=20R=C3=B8ed?= Date: Mon, 13 Apr 2026 14:43:29 +0200 Subject: [PATCH 1/5] Fix template-require-form-method: throw on bad config; default disabled parseConfig now throws on invalid allowedMethods (matches upstream's strictness instead of silently disabling). parseConfig(undefined) returns false so the rule doesn't run when options are omitted (matches upstream default). Schema accepts boolean root for parity. --- lib/rules/template-require-form-method.js | 24 ++++++-- .../lib/rules/template-require-form-method.js | 57 +++++++++++++++---- 2 files changed, 66 insertions(+), 15 deletions(-) diff --git a/lib/rules/template-require-form-method.js b/lib/rules/template-require-form-method.js index 66be830ca5..85762b6ca8 100644 --- a/lib/rules/template-require-form-method.js +++ b/lib/rules/template-require-form-method.js @@ -26,7 +26,16 @@ function parseConfig(config) { } } - return false; + // Invalid configuration (e.g. unknown method in allowedMethods). Throw a + // descriptive error to surface the problem to the user, matching upstream + // ember-template-lint (which throws instead of silently disabling). + throw new Error( + 'template-require-form-method: invalid configuration. Expected one of:\n' + + ' * boolean - `true` to enable / `false` to disable\n' + + ' * object -- An object with the following keys:\n' + + ` * \`allowedMethods\` -- An array of allowed form \`method\` attribute values of \`${VALID_FORM_METHODS}\`\n` + + `Received: ${JSON.stringify(config)}` + ); } function makeErrorMessage(methods) { @@ -51,12 +60,16 @@ module.exports = { schema: [ { oneOf: [ + { type: 'boolean' }, { type: 'object', properties: { allowedMethods: { type: 'array', items: { + // Accept any string so case-insensitive values like "get" + // still pass schema validation; parseConfig normalizes to + // upper-case and throws on values not in VALID_FORM_METHODS. type: 'string', }, }, @@ -78,9 +91,12 @@ module.exports = { }, create(context) { - // If no options provided, use defaults - let config = context.options[0]; - config = config ? parseConfig(config) : DEFAULT_CONFIG; + // Match upstream ember-template-lint: when no options are provided, + // parseConfig(undefined) returns false and the rule is disabled. This + // rule must be enabled explicitly via `true` or an `allowedMethods` + // object. + const rawOption = context.options[0]; + const config = parseConfig(rawOption); if (config === false) { return {}; diff --git a/tests/lib/rules/template-require-form-method.js b/tests/lib/rules/template-require-form-method.js index 5e3573b565..f634e69b60 100644 --- a/tests/lib/rules/template-require-form-method.js +++ b/tests/lib/rules/template-require-form-method.js @@ -9,17 +9,22 @@ const validHbs = [ options: [{ allowedMethods: ['get'] }], code: '
', }, - '
', - '
', - '
', - '
', - '
', - '
', - '
', - '
', - '
', - '
', - '
', + // Default behavior: when no options are provided, the rule is disabled + // (matching upstream ember-template-lint). A bare
should NOT error. + '
', + '
', + { options: [true], code: '
' }, + { options: [true], code: '
' }, + { options: [true], code: '
' }, + { options: [true], code: '
' }, + { options: [true], code: '
' }, + { options: [true], code: '
' }, + { options: [true], code: '
' }, + { options: [true], code: '
' }, + { options: [true], code: '
' }, + { options: [true], code: '
' }, + { options: [true], code: '
' }, + { options: [false], code: '
' }, ]; const invalidHbs = [ @@ -40,26 +45,31 @@ const invalidHbs = [ ], }, { + options: [true], code: '
', output: '
', errors: [{ message: DEFAULT_ERROR }], }, { + options: [true], code: '
', output: '
', errors: [{ message: DEFAULT_ERROR }], }, { + options: [true], code: '
', output: '
', errors: [{ message: DEFAULT_ERROR }], }, { + options: [true], code: '
', output: '
', errors: [{ message: DEFAULT_ERROR }], }, { + options: [true], code: '
', output: '
', errors: [{ message: DEFAULT_ERROR }], @@ -100,3 +110,28 @@ hbsRuleTester.run('template-require-form-method', rule, { valid: validHbs, invalid: invalidHbs, }); + +// Upstream-aligned error-surfacing tests. parseConfig should throw on an +// invalid `allowedMethods` entry rather than silently disabling the rule. +describe('template-require-form-method invalid configuration', () => { + const { Linter } = require('eslint'); + + function lintWith(options) { + const linter = new Linter(); + linter.defineParser('ember-eslint-parser/hbs', require('ember-eslint-parser/hbs')); + linter.defineRule('template-require-form-method', rule); + return linter.verify('
', { + parser: 'ember-eslint-parser/hbs', + parserOptions: { ecmaVersion: 2022, sourceType: 'module' }, + rules: { 'template-require-form-method': ['error', options] }, + }); + } + + test('throws on unknown method in allowedMethods', () => { + expect(() => lintWith({ allowedMethods: ['PATCH'] })).toThrow(/invalid configuration/); + }); + + test('throws on mixed valid/invalid method list', () => { + expect(() => lintWith({ allowedMethods: ['GET', 'BOGUS'] })).toThrow(/invalid configuration/); + }); +}); From 45cfa005dca9d77cbfb342df96de83a4803c235c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johan=20R=C3=B8ed?= Date: Tue, 14 Apr 2026 14:54:48 +0200 Subject: [PATCH 2/5] =?UTF-8?q?chore:=20remove=20'matches=20upstream'=20co?= =?UTF-8?q?mments=20=E2=80=94=20describe=20behavior=20directly?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/rules/template-require-form-method.js | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/lib/rules/template-require-form-method.js b/lib/rules/template-require-form-method.js index 85762b6ca8..55c8f368f9 100644 --- a/lib/rules/template-require-form-method.js +++ b/lib/rules/template-require-form-method.js @@ -27,8 +27,8 @@ function parseConfig(config) { } // Invalid configuration (e.g. unknown method in allowedMethods). Throw a - // descriptive error to surface the problem to the user, matching upstream - // ember-template-lint (which throws instead of silently disabling). + // descriptive error to surface the problem to the user rather than silently + // disabling the rule. throw new Error( 'template-require-form-method: invalid configuration. Expected one of:\n' + ' * boolean - `true` to enable / `false` to disable\n' + @@ -91,10 +91,9 @@ module.exports = { }, create(context) { - // Match upstream ember-template-lint: when no options are provided, - // parseConfig(undefined) returns false and the rule is disabled. This - // rule must be enabled explicitly via `true` or an `allowedMethods` - // object. + // When no options are provided, parseConfig(undefined) returns false and + // the rule is disabled. It must be enabled explicitly via `true` or an + // `allowedMethods` object. const rawOption = context.options[0]; const config = parseConfig(rawOption); From 86a4d57811ca94ed8ac377a35d5c18afeda6e66f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johan=20R=C3=B8ed?= Date: Tue, 14 Apr 2026 19:00:37 +0200 Subject: [PATCH 3/5] chore: remove what-comments and upstream references --- lib/rules/template-require-form-method.js | 3 --- tests/lib/rules/template-require-form-method.js | 8 ++++---- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/lib/rules/template-require-form-method.js b/lib/rules/template-require-form-method.js index 55c8f368f9..0545f452cd 100644 --- a/lib/rules/template-require-form-method.js +++ b/lib/rules/template-require-form-method.js @@ -26,9 +26,6 @@ function parseConfig(config) { } } - // Invalid configuration (e.g. unknown method in allowedMethods). Throw a - // descriptive error to surface the problem to the user rather than silently - // disabling the rule. throw new Error( 'template-require-form-method: invalid configuration. Expected one of:\n' + ' * boolean - `true` to enable / `false` to disable\n' + diff --git a/tests/lib/rules/template-require-form-method.js b/tests/lib/rules/template-require-form-method.js index f634e69b60..6770d9b69c 100644 --- a/tests/lib/rules/template-require-form-method.js +++ b/tests/lib/rules/template-require-form-method.js @@ -9,8 +9,8 @@ const validHbs = [ options: [{ allowedMethods: ['get'] }], code: '
', }, - // Default behavior: when no options are provided, the rule is disabled - // (matching upstream ember-template-lint). A bare
should NOT error. + // Default behavior: when no options are provided, the rule is disabled. + // A bare should NOT error. '
', '
', { options: [true], code: '
' }, @@ -111,8 +111,8 @@ hbsRuleTester.run('template-require-form-method', rule, { invalid: invalidHbs, }); -// Upstream-aligned error-surfacing tests. parseConfig should throw on an -// invalid `allowedMethods` entry rather than silently disabling the rule. +// parseConfig should throw on an invalid `allowedMethods` entry so that +// misconfiguration is surfaced immediately rather than silently ignored. describe('template-require-form-method invalid configuration', () => { const { Linter } = require('eslint'); From 34225ac2210d060ebfefd6453d76fba5d18bbdd9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johan=20R=C3=B8ed?= Date: Wed, 15 Apr 2026 08:15:55 +0200 Subject: [PATCH 4/5] fix(template-require-form-method): enable rule by default to match ember-template-lint Align with upstream: bare
and invalid method values are now flagged without explicit configuration. Pass `false` to opt out. --- lib/rules/template-require-form-method.js | 9 ++++----- tests/lib/rules/template-require-form-method.js | 15 +++++++++++---- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/lib/rules/template-require-form-method.js b/lib/rules/template-require-form-method.js index 0545f452cd..ae1f2eed46 100644 --- a/lib/rules/template-require-form-method.js +++ b/lib/rules/template-require-form-method.js @@ -7,11 +7,11 @@ const DEFAULT_CONFIG = { }; function parseConfig(config) { - if (config === false || config === undefined) { + if (config === false) { return false; } - if (config === true) { + if (config === true || config === undefined) { return DEFAULT_CONFIG; } @@ -88,9 +88,8 @@ module.exports = { }, create(context) { - // When no options are provided, parseConfig(undefined) returns false and - // the rule is disabled. It must be enabled explicitly via `true` or an - // `allowedMethods` object. + // Default-enabled: parseConfig(undefined) returns DEFAULT_CONFIG. + // Pass `false` to explicitly disable the rule. const rawOption = context.options[0]; const config = parseConfig(rawOption); diff --git a/tests/lib/rules/template-require-form-method.js b/tests/lib/rules/template-require-form-method.js index 6770d9b69c..7611306e97 100644 --- a/tests/lib/rules/template-require-form-method.js +++ b/tests/lib/rules/template-require-form-method.js @@ -9,10 +9,6 @@ const validHbs = [ options: [{ allowedMethods: ['get'] }], code: '
', }, - // Default behavior: when no options are provided, the rule is disabled. - // A bare
should NOT error. - '
', - '
', { options: [true], code: '
' }, { options: [true], code: '
' }, { options: [true], code: '
' }, @@ -28,6 +24,17 @@ const validHbs = [ ]; const invalidHbs = [ + // Default-enabled: no options → rule active with POST,GET,DIALOG. + { + code: '
', + output: '
', + errors: [{ message: DEFAULT_ERROR }], + }, + { + code: '
', + output: '
', + errors: [{ message: DEFAULT_ERROR }], + }, { options: [{ allowedMethods: ['get'] }], code: '
', From eaeb7919b5f10487cded1c8428a86cbec62db704 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johan=20R=C3=B8ed?= Date: Wed, 15 Apr 2026 15:16:27 +0200 Subject: [PATCH 5/5] test(template-require-form-method): exercise default-enabled path with no options With the rule default-enabled, `options: [true]` is redundant with no options. Switch most valid cases to bare strings so the tests exercise the default user path. Keep one `options: [true]` and one `options: [false]` as sentinels documenting that the explicit boolean forms still work. --- .../lib/rules/template-require-form-method.js | 24 +++++++++++-------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/tests/lib/rules/template-require-form-method.js b/tests/lib/rules/template-require-form-method.js index 7611306e97..779519422a 100644 --- a/tests/lib/rules/template-require-form-method.js +++ b/tests/lib/rules/template-require-form-method.js @@ -9,17 +9,21 @@ const validHbs = [ options: [{ allowedMethods: ['get'] }], code: '
', }, + // No options → default-enabled with POST,GET,DIALOG. + '
', + '
', + '
', + '
', + '
', + '
', + '
', + '
', + '
', + '
', + '
', + // Explicit `true` behaves identically to no options. { options: [true], code: '
' }, - { options: [true], code: '
' }, - { options: [true], code: '
' }, - { options: [true], code: '
' }, - { options: [true], code: '
' }, - { options: [true], code: '
' }, - { options: [true], code: '
' }, - { options: [true], code: '
' }, - { options: [true], code: '
' }, - { options: [true], code: '
' }, - { options: [true], code: '
' }, + // Explicit `false` disables the rule. { options: [false], code: '
' }, ];