@adyen/eslint-plugin-bento 2.11.0 → 2.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,21 @@
1
1
  # Changelog
2
2
 
3
+ ## 2.13.0 (2026-05-20)
4
+
5
+ This was a version bump only for eslint to align it with other projects, there were no code changes.
6
+
7
+
8
+ ## 2.12.0 (2026-05-12)
9
+
10
+ ### Features
11
+
12
+ - added rule to deprecate `bento-date-range-picker` prop `has-actions` in eslint ([d594fcb72](https://github.com/Adyen/bento/commit/d594fcb72))
13
+
14
+ ### ❤️ Thank You
15
+
16
+ - erice
17
+
18
+
3
19
  ## 2.11.0 (2026-05-06)
4
20
 
5
21
  ### Features
@@ -12,6 +12,7 @@ module.exports = [
12
12
  },
13
13
  rules: {
14
14
  '@adyen/bento/deprecation-bento-data-grid-cell-action-menu-item-handler': 'warn',
15
+ '@adyen/bento/deprecation-bento-date-range-picker-has-actions-prop': 'warn',
15
16
  '@adyen/bento/deprecation-input-filter-dropdown-options': 'warn',
16
17
  '@adyen/bento/deprecation-bento-dropdown-size-prop': 'warn',
17
18
  '@adyen/bento/deprecation-bento-timeline-item-variant-prop': 'warn',
@@ -12,6 +12,7 @@ module.exports = [
12
12
  },
13
13
  rules: {
14
14
  '@adyen/bento/deprecation-bento-data-grid-cell-action-menu-item-handler': 'error',
15
+ '@adyen/bento/deprecation-bento-date-range-picker-has-actions-prop': 'error',
15
16
  '@adyen/bento/deprecation-input-filter-dropdown-options': 'error',
16
17
  '@adyen/bento/deprecation-bento-dropdown-size-prop': 'error',
17
18
  '@adyen/bento/deprecation-bento-timeline-item-variant-prop': 'error',
package/index.js CHANGED
@@ -13,6 +13,7 @@ const plugin = {
13
13
  },
14
14
  rules: {
15
15
  'deprecation-bento-data-grid-cell-action-menu-item-handler': require('./rules/deprecation-bento-data-grid-cell-action-menu-item-handler/deprecation-bento-data-grid-cell-action-menu-item-handler'),
16
+ 'deprecation-bento-date-range-picker-has-actions-prop': require('./rules/deprecation-bento-date-range-picker-has-actions-prop/deprecation-bento-date-range-picker-has-actions-prop'),
16
17
  'deprecation-input-filter-dropdown-options': require('./rules/deprecation-input-filter-dropdown-options/deprecation-input-filter-dropdown-options'),
17
18
  'deprecation-bento-dropdown-size-prop': require('./rules/deprecation-bento-dropdown-size-prop/deprecation-bento-dropdown-size-prop'),
18
19
  'deprecation-bento-timeline-item-variant-prop': require('./rules/deprecation-bento-timeline-item-variant-prop/deprecation-bento-timeline-item-variant-prop'),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adyen/eslint-plugin-bento",
3
- "version": "2.11.0",
3
+ "version": "2.13.0",
4
4
  "description": "Adyen Bento ESLint rules",
5
5
  "main": "index.js",
6
6
  "files": [
@@ -0,0 +1,50 @@
1
+ # deprecation-bento-date-range-picker-has-actions-prop
2
+
3
+ ## Description
4
+
5
+ Manages the **temporary** `has-actions` prop on `bento-date-range-picker`.
6
+
7
+ The `has-actions` prop is a temporary opt-in flag for the new actions behavior. This rule helps teams adopt it during
8
+ the transition period, and later remove it once the behavior becomes the default.
9
+
10
+ ## Options
11
+
12
+ | Option | Type | Default | Description |
13
+ | :------------ | :-------------------- | :------ | :------------------------------------------------------------- |
14
+ | **`action`** | `'add'` \| `'remove'` | `'add'` | `add` reports missing `has-actions`. `remove` reports present. |
15
+ | **`autofix`** | `boolean` | `false` | Enables auto-fixing. |
16
+
17
+ ## Rule Details
18
+
19
+ ### Action: `add` (default)
20
+
21
+ Reports `bento-date-range-picker` instances that are **missing** the `has-actions` prop.
22
+
23
+ #### ❌ Incorrect
24
+
25
+ ```html
26
+ <bento-date-range-picker label="Pick" />
27
+ ```
28
+
29
+ #### ✅ Correct
30
+
31
+ ```html
32
+ <bento-date-range-picker has-actions label="Pick" />
33
+ ```
34
+
35
+ ### Action: `remove`
36
+
37
+ Reports `bento-date-range-picker` instances that **have** the `has-actions` prop, so it can be cleaned up once the
38
+ behavior becomes permanent.
39
+
40
+ #### ❌ Incorrect
41
+
42
+ ```html
43
+ <bento-date-range-picker has-actions label="Pick" />
44
+ ```
45
+
46
+ #### ✅ Correct
47
+
48
+ ```html
49
+ <bento-date-range-picker label="Pick" />
50
+ ```
@@ -0,0 +1,10 @@
1
+ <template>
2
+ <div>
3
+ <!-- These should trigger the "add" action (missing has-actions) -->
4
+ <bento-date-range-picker label="Pick a date" />
5
+ <bento-date-range-picker label="Another picker" :min="minDate" />
6
+ <bento-date-range-picker v-model="value" />
7
+ </div>
8
+ </template>
9
+
10
+ <script setup></script>
@@ -0,0 +1,29 @@
1
+ // eslint.config.js
2
+ const { defineConfig } = require('eslint/config');
3
+ const vueParser = require('vue-eslint-parser');
4
+ const tsParser = require('@typescript-eslint/parser');
5
+ const adyenBento = require('@adyen/eslint-plugin-bento');
6
+
7
+ module.exports = defineConfig([
8
+ {
9
+ languageOptions: {
10
+ ecmaVersion: 'latest',
11
+ sourceType: 'module',
12
+ parser: vueParser,
13
+ parserOptions: {
14
+ parser: tsParser,
15
+ },
16
+ },
17
+ plugins: {
18
+ '@adyen/bento': adyenBento,
19
+ },
20
+ rules: {
21
+ // Register the specific rule we are testing
22
+ '@adyen/bento/deprecation-bento-date-range-picker-has-actions-prop': [
23
+ 'warn',
24
+ { action: 'add', autofix: true },
25
+ ],
26
+ },
27
+ files: ['**/*.vue'],
28
+ },
29
+ ]);
@@ -0,0 +1,11 @@
1
+ <template>
2
+ <div>
3
+ <!-- These should trigger the "remove" action (has-actions present) -->
4
+ <bento-date-range-picker has-actions />
5
+ <bento-date-range-picker has-actions label="Pick a date" />
6
+ <bento-date-range-picker :has-actions="true" />
7
+ <bento-date-range-picker :has-actions="false" />
8
+ </div>
9
+ </template>
10
+
11
+ <script setup></script>
@@ -0,0 +1,29 @@
1
+ // eslint.config.js
2
+ const { defineConfig } = require('eslint/config');
3
+ const vueParser = require('vue-eslint-parser');
4
+ const tsParser = require('@typescript-eslint/parser');
5
+ const adyenBento = require('@adyen/eslint-plugin-bento');
6
+
7
+ module.exports = defineConfig([
8
+ {
9
+ languageOptions: {
10
+ ecmaVersion: 'latest',
11
+ sourceType: 'module',
12
+ parser: vueParser,
13
+ parserOptions: {
14
+ parser: tsParser,
15
+ },
16
+ },
17
+ plugins: {
18
+ '@adyen/bento': adyenBento,
19
+ },
20
+ rules: {
21
+ // Register the specific rule we are testing
22
+ '@adyen/bento/deprecation-bento-date-range-picker-has-actions-prop': [
23
+ 'warn',
24
+ { action: 'remove', autofix: true },
25
+ ],
26
+ },
27
+ files: ['**/*.vue'],
28
+ },
29
+ ]);
@@ -0,0 +1,47 @@
1
+ import path from 'node:path';
2
+ import { execFileSyncEslintVueFiles } from '../../utils/exec-file-sync-eslint-vue-files';
3
+
4
+ describe('@adyen/bento/deprecation-bento-date-range-picker-has-actions-prop', () => {
5
+ it('should lint with warning when has-actions is missing (add action)', () => {
6
+ const eslintrc = path.resolve(__dirname, '__tests__', 'eslint.config.js');
7
+ const vueFile = path.resolve(
8
+ __dirname,
9
+ '__tests__',
10
+ 'deprecation-bento-date-range-picker-has-actions-prop.vue'
11
+ );
12
+
13
+ const result = JSON.parse(execFileSyncEslintVueFiles(eslintrc, vueFile));
14
+
15
+ // The test .vue file has 3 bento-date-range-picker instances without has-actions
16
+ expect(result[0].warningCount).toBe(3);
17
+
18
+ expect(result[0].messages[0]).toMatchObject({
19
+ ruleId: '@adyen/bento/deprecation-bento-date-range-picker-has-actions-prop',
20
+ severity: 1,
21
+ messageId: 'missingProp',
22
+ message: `The temporary "has-actions" prop is missing on bento-date-range-picker. Add it to opt in to the new actions behavior.`,
23
+ });
24
+ });
25
+
26
+ it('should lint with warning when has-actions is present (remove action)', () => {
27
+ const eslintrc = path.resolve(__dirname, '__tests__', 'remove', 'eslint.config.js');
28
+ const vueFile = path.resolve(
29
+ __dirname,
30
+ '__tests__',
31
+ 'remove',
32
+ 'deprecation-bento-date-range-picker-has-actions-prop.vue'
33
+ );
34
+
35
+ const result = JSON.parse(execFileSyncEslintVueFiles(eslintrc, vueFile));
36
+
37
+ // The test .vue file has 4 bento-date-range-picker instances with has-actions
38
+ expect(result[0].warningCount).toBe(4);
39
+
40
+ expect(result[0].messages[0]).toMatchObject({
41
+ ruleId: '@adyen/bento/deprecation-bento-date-range-picker-has-actions-prop',
42
+ severity: 1,
43
+ messageId: 'removeProp',
44
+ message: `The temporary "has-actions" prop should be removed from bento-date-range-picker.`,
45
+ });
46
+ });
47
+ });
@@ -0,0 +1,205 @@
1
+ /**
2
+ * @typedef {import('eslint').Rule.RuleContext} RuleContext
3
+ */
4
+ /**
5
+ * @typedef {import('eslint-plugin-vue/lib/utils').RuleModule} RuleModule
6
+ */
7
+
8
+ const VueUtils = require('eslint-plugin-vue/lib/utils');
9
+
10
+ const COMPONENT_SELECTOR = `VElement:matches([name="bento-date-range-picker"], [name="BentoDateRangePicker"])`;
11
+ const STATIC_ATTR = `${COMPONENT_SELECTOR} > VStartTag > VAttribute[directive=false][key.name="has-actions"]`;
12
+ const DYNAMIC_ATTR = `${COMPONENT_SELECTOR} > VStartTag > VAttribute[directive=true][key.name.name="bind"][key.argument.name="has-actions"]`;
13
+
14
+ /**
15
+ * Checks whether a VElement already has the `has-actions` attribute set to a truthy value.
16
+ * Returns false if the prop is missing or explicitly set to false.
17
+ */
18
+ function hasHasActionsTruthy(startTag) {
19
+ return startTag.attributes.some(attr => {
20
+ if (!attr.directive) {
21
+ // Static: has-actions (boolean) or has-actions="something"
22
+ // has-actions="false" is the string "false", still counts as explicitly false
23
+ if (attr.key.name !== 'has-actions') {
24
+ return false;
25
+ }
26
+ return !attr.value || attr.value.value !== 'false';
27
+ }
28
+ // Dynamic: :has-actions="expr" or v-bind:has-actions="expr"
29
+ if (
30
+ attr.key.name &&
31
+ attr.key.name.name === 'bind' &&
32
+ attr.key.argument &&
33
+ attr.key.argument.name === 'has-actions'
34
+ ) {
35
+ // :has-actions="false" → expression is a Literal with value false
36
+ const expr = attr.value && attr.value.expression;
37
+ if (expr && expr.type === 'Literal' && expr.value === false) {
38
+ return false;
39
+ }
40
+ return true;
41
+ }
42
+ return false;
43
+ });
44
+ }
45
+
46
+ /**
47
+ * Removes an attribute node. If the attribute is alone on its line,
48
+ * removes the entire line (including leading whitespace and trailing newline)
49
+ * to avoid leaving a blank line.
50
+ */
51
+ function removeAttribute(fixer, node, sourceCode) {
52
+ const fullText = sourceCode.getText();
53
+ const lineStart = fullText.lastIndexOf('\n', node.range[0] - 1) + 1;
54
+ const lineEnd = node.range[1];
55
+
56
+ // Check if the attribute is the only non-whitespace content on its line
57
+ const textBefore = fullText.slice(lineStart, node.range[0]);
58
+ const textAfter = fullText.slice(node.range[1], fullText.indexOf('\n', node.range[1]));
59
+
60
+ if (textBefore.trim() === '' && textAfter.trim() === '') {
61
+ // Remove from end of previous line to end of this line
62
+ const removeEnd = fullText.indexOf('\n', lineEnd);
63
+ return fixer.removeRange([lineStart - 1, removeEnd >= 0 ? removeEnd : lineEnd]);
64
+ }
65
+
66
+ return fixer.remove(node);
67
+ }
68
+
69
+ /** @type {RuleModule} */
70
+ module.exports = {
71
+ meta: {
72
+ type: 'suggestion',
73
+ docs: {
74
+ description:
75
+ 'Manages the temporary "has-actions" prop on bento-date-range-picker. Use action "add" to add it or "remove" to remove it.',
76
+ category: 'Deprecations',
77
+ url: 'https://github.com/Adyen/bento/blob/main/packages/eslint/rules/deprecation-bento-date-range-picker-has-actions-prop/README.md',
78
+ recommended: true,
79
+ },
80
+ messages: {
81
+ missingProp: `The temporary "has-actions" prop is missing on bento-date-range-picker. Add it to opt in to the new actions behavior.`,
82
+ removeProp: `The temporary "has-actions" prop should be removed from bento-date-range-picker.`,
83
+ },
84
+ fixable: 'code',
85
+ schema: [
86
+ {
87
+ type: 'object',
88
+ properties: {
89
+ action: {
90
+ type: 'string',
91
+ enum: ['add', 'remove'],
92
+ default: 'add',
93
+ },
94
+ autofix: {
95
+ type: 'boolean',
96
+ default: false,
97
+ },
98
+ },
99
+ additionalProperties: false,
100
+ },
101
+ ],
102
+ },
103
+
104
+ /** @param {RuleContext} context */
105
+ create(context) {
106
+ const options = context.options[0] || {};
107
+ const action = options.action || 'add';
108
+ const autofix = options.autofix === true;
109
+
110
+ if (action === 'remove') {
111
+ /* ------------------------------------------------ */
112
+ /* REMOVE: report and optionally remove has-actions */
113
+ /* ------------------------------------------------ */
114
+ return VueUtils.defineTemplateBodyVisitor(context, {
115
+ [STATIC_ATTR](node) {
116
+ context.report({
117
+ node,
118
+ messageId: 'removeProp',
119
+ ...(autofix && {
120
+ fix(fixer) {
121
+ return removeAttribute(fixer, node, context.sourceCode);
122
+ },
123
+ }),
124
+ });
125
+ },
126
+ [DYNAMIC_ATTR](node) {
127
+ context.report({
128
+ node,
129
+ messageId: 'removeProp',
130
+ ...(autofix && {
131
+ fix(fixer) {
132
+ return removeAttribute(fixer, node, context.sourceCode);
133
+ },
134
+ }),
135
+ });
136
+ },
137
+ });
138
+ }
139
+
140
+ /* ------------------------------------------------ */
141
+ /* ADD: report components missing has-actions */
142
+ /* ------------------------------------------------ */
143
+ return VueUtils.defineTemplateBodyVisitor(context, {
144
+ [COMPONENT_SELECTOR](node) {
145
+ if (hasHasActionsTruthy(node.startTag)) {
146
+ return;
147
+ }
148
+
149
+ // Find if has-actions exists but is set to false
150
+ const falseAttr = node.startTag.attributes.find(attr => {
151
+ if (!attr.directive) {
152
+ return attr.key.name === 'has-actions' && attr.value && attr.value.value === 'false';
153
+ }
154
+ if (
155
+ attr.key.name &&
156
+ attr.key.name.name === 'bind' &&
157
+ attr.key.argument &&
158
+ attr.key.argument.name === 'has-actions'
159
+ ) {
160
+ const expr = attr.value && attr.value.expression;
161
+ return expr && expr.type === 'Literal' && expr.value === false;
162
+ }
163
+ return false;
164
+ });
165
+
166
+ context.report({
167
+ node: falseAttr || node.startTag,
168
+ messageId: 'missingProp',
169
+ ...(autofix && {
170
+ fix(fixer) {
171
+ // If has-actions="false" or :has-actions="false", replace with boolean has-actions
172
+ if (falseAttr) {
173
+ return fixer.replaceText(falseAttr, 'has-actions');
174
+ }
175
+
176
+ // Prop is completely missing – insert it
177
+ const sourceCode = context.sourceCode;
178
+ const fullText = sourceCode.getText();
179
+ const firstAttr = node.startTag.attributes[0];
180
+ if (firstAttr) {
181
+ const isMultiLine = firstAttr.loc.start.line !== node.startTag.loc.start.line;
182
+ if (isMultiLine) {
183
+ // Derive indentation from the actual whitespace before the first attribute
184
+ const lineStart = fullText.lastIndexOf('\n', firstAttr.range[0] - 1) + 1;
185
+ const indent = fullText.slice(lineStart, firstAttr.range[0]);
186
+ return fixer.insertTextBefore(firstAttr, `has-actions\n${indent}`);
187
+ }
188
+ return fixer.insertTextBefore(firstAttr, 'has-actions ');
189
+ }
190
+
191
+ // No attributes – insert before the closing > or />
192
+ const startTagText = sourceCode.getText(node.startTag);
193
+ const selfClosing = startTagText.endsWith('/>');
194
+ const insertPos = node.startTag.range[1] - (selfClosing ? 2 : 1);
195
+ // Only add a leading space if there isn't already whitespace before the insert position
196
+ const charBefore = fullText[insertPos - 1];
197
+ const leadingSpace = charBefore && /\s/.test(charBefore) ? '' : ' ';
198
+ return fixer.insertTextBeforeRange([insertPos, insertPos], `${leadingSpace}has-actions `);
199
+ },
200
+ }),
201
+ });
202
+ },
203
+ });
204
+ },
205
+ };
@@ -0,0 +1,176 @@
1
+ import { RuleTester } from 'eslint';
2
+ import vueParser from 'vue-eslint-parser';
3
+ import tsParser from '@typescript-eslint/parser';
4
+ import deprecationBentoDateRangePickerHasActionsProp from './deprecation-bento-date-range-picker-has-actions-prop';
5
+
6
+ const ruleTester = new RuleTester({
7
+ languageOptions: {
8
+ ecmaVersion: 'latest',
9
+ sourceType: 'module',
10
+ parser: vueParser,
11
+ parserOptions: {
12
+ parser: tsParser,
13
+ },
14
+ },
15
+ });
16
+
17
+ describe('@adyen/bento/deprecation-bento-date-range-picker-has-actions-prop', () => {
18
+ describe('action: add (default)', () => {
19
+ ruleTester.run(
20
+ 'deprecation-bento-date-range-picker-has-actions-prop (add)',
21
+ deprecationBentoDateRangePickerHasActionsProp,
22
+ {
23
+ valid: [
24
+ {
25
+ name: 'Valid: component already has has-actions (static boolean)',
26
+ filename: 'test.vue',
27
+ code: `<template><bento-date-range-picker has-actions /></template>`,
28
+ },
29
+ {
30
+ name: 'Valid: component already has has-actions (dynamic)',
31
+ filename: 'test.vue',
32
+ code: `<template><bento-date-range-picker :has-actions="true" /></template>`,
33
+ },
34
+ {
35
+ name: 'Valid: unrelated component without has-actions',
36
+ filename: 'test.vue',
37
+ code: `<template><bento-button label="click" /></template>`,
38
+ },
39
+ ],
40
+ invalid: [
41
+ {
42
+ name: 'Invalid: missing has-actions (no autofix)',
43
+ filename: 'test.vue',
44
+ code: `<template><bento-date-range-picker label="Pick" /></template>`,
45
+ output: null,
46
+ errors: [{ messageId: 'missingProp' }],
47
+ },
48
+ {
49
+ name: 'Invalid: missing has-actions (autofix adds prop)',
50
+ filename: 'test.vue',
51
+ code: `<template><bento-date-range-picker label="Pick" /></template>`,
52
+ output: `<template><bento-date-range-picker has-actions label="Pick" /></template>`,
53
+ options: [{ action: 'add', autofix: true }],
54
+ errors: [{ messageId: 'missingProp' }],
55
+ },
56
+ {
57
+ name: 'Invalid: missing has-actions on self-closing tag without attrs (autofix)',
58
+ filename: 'test.vue',
59
+ code: `<template><bento-date-range-picker /></template>`,
60
+ output: `<template><bento-date-range-picker has-actions /></template>`,
61
+ options: [{ autofix: true }],
62
+ errors: [{ messageId: 'missingProp' }],
63
+ },
64
+ {
65
+ name: 'Invalid: missing has-actions on self-closing tag without space before /> (autofix)',
66
+ filename: 'test.vue',
67
+ code: `<template><bento-date-range-picker/></template>`,
68
+ output: `<template><bento-date-range-picker has-actions /></template>`,
69
+ options: [{ autofix: true }],
70
+ errors: [{ messageId: 'missingProp' }],
71
+ },
72
+ {
73
+ name: 'Invalid: has-actions="false" (static string false, no autofix)',
74
+ filename: 'test.vue',
75
+ code: `<template><bento-date-range-picker has-actions="false" /></template>`,
76
+ output: null,
77
+ errors: [{ messageId: 'missingProp' }],
78
+ },
79
+ {
80
+ name: 'Invalid: has-actions="false" (static string false, autofix replaces)',
81
+ filename: 'test.vue',
82
+ code: `<template><bento-date-range-picker has-actions="false" label="Pick" /></template>`,
83
+ output: `<template><bento-date-range-picker has-actions label="Pick" /></template>`,
84
+ options: [{ autofix: true }],
85
+ errors: [{ messageId: 'missingProp' }],
86
+ },
87
+ {
88
+ name: 'Invalid: :has-actions="false" (dynamic false, autofix replaces)',
89
+ filename: 'test.vue',
90
+ code: `<template><bento-date-range-picker :has-actions="false" label="Pick" /></template>`,
91
+ output: `<template><bento-date-range-picker has-actions label="Pick" /></template>`,
92
+ options: [{ autofix: true }],
93
+ errors: [{ messageId: 'missingProp' }],
94
+ },
95
+ {
96
+ name: 'Invalid: multi-line component missing has-actions (autofix preserves indentation)',
97
+ filename: 'test.vue',
98
+ code: `<template>
99
+ <bento-date-range-picker
100
+ label="Pick"
101
+ />
102
+ </template>`,
103
+ output: `<template>
104
+ <bento-date-range-picker
105
+ has-actions
106
+ label="Pick"
107
+ />
108
+ </template>`,
109
+ options: [{ autofix: true }],
110
+ errors: [{ messageId: 'missingProp' }],
111
+ },
112
+ ],
113
+ }
114
+ );
115
+ });
116
+
117
+ describe('action: remove', () => {
118
+ ruleTester.run(
119
+ 'deprecation-bento-date-range-picker-has-actions-prop (remove)',
120
+ deprecationBentoDateRangePickerHasActionsProp,
121
+ {
122
+ valid: [
123
+ {
124
+ name: 'Valid: component without has-actions',
125
+ filename: 'test.vue',
126
+ code: `<template><bento-date-range-picker label="Pick" /></template>`,
127
+ options: [{ action: 'remove' }],
128
+ },
129
+ ],
130
+ invalid: [
131
+ {
132
+ name: 'Invalid: has-actions present (static boolean, no autofix)',
133
+ filename: 'test.vue',
134
+ code: `<template><bento-date-range-picker has-actions /></template>`,
135
+ output: null,
136
+ options: [{ action: 'remove' }],
137
+ errors: [{ messageId: 'removeProp' }],
138
+ },
139
+ {
140
+ name: 'Invalid: has-actions present (static boolean, autofix removes)',
141
+ filename: 'test.vue',
142
+ code: `<template><bento-date-range-picker has-actions label="Pick" /></template>`,
143
+ output: `<template><bento-date-range-picker label="Pick" /></template>`,
144
+ options: [{ action: 'remove', autofix: true }],
145
+ errors: [{ messageId: 'removeProp' }],
146
+ },
147
+ {
148
+ name: 'Invalid: has-actions present (dynamic, autofix removes)',
149
+ filename: 'test.vue',
150
+ code: `<template><bento-date-range-picker :has-actions="true" /></template>`,
151
+ output: `<template><bento-date-range-picker /></template>`,
152
+ options: [{ action: 'remove', autofix: true }],
153
+ errors: [{ messageId: 'removeProp' }],
154
+ },
155
+ {
156
+ name: 'Invalid: multi-line has-actions on its own line (autofix removes entire line)',
157
+ filename: 'test.vue',
158
+ code: `<template>
159
+ <bento-date-range-picker
160
+ has-actions
161
+ label="Pick"
162
+ />
163
+ </template>`,
164
+ output: `<template>
165
+ <bento-date-range-picker
166
+ label="Pick"
167
+ />
168
+ </template>`,
169
+ options: [{ action: 'remove', autofix: true }],
170
+ errors: [{ messageId: 'removeProp' }],
171
+ },
172
+ ],
173
+ }
174
+ );
175
+ });
176
+ });