eslint-plugin-smarthr 6.12.1 → 6.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/.claude/settings.local.json +4 -1
- package/CHANGELOG.md +7 -0
- package/package.json +2 -2
- package/rules/autofixer-smarthr-ui-migration/index.js +3 -0
- package/rules/autofixer-smarthr-ui-migration/versions/v92-to-v93/README.md +130 -0
- package/rules/autofixer-smarthr-ui-migration/versions/v92-to-v93/REFERENCE.md +287 -0
- package/rules/autofixer-smarthr-ui-migration/versions/v92-to-v93/index.js +198 -0
- package/rules/autofixer-smarthr-ui-migration/versions/v92-to-v93/test.js +135 -0
- package/test/autofixer-smarthr-ui-migration.js +7 -6
|
@@ -118,7 +118,10 @@
|
|
|
118
118
|
"Bash(for pr:*)",
|
|
119
119
|
"Bash(npx lerna:*)",
|
|
120
120
|
"Bash(npm login:*)",
|
|
121
|
-
"Bash(curl -s https://raw.githubusercontent.com/kufu/smarthr-ui/main/CHANGELOG.md)"
|
|
121
|
+
"Bash(curl -s https://raw.githubusercontent.com/kufu/smarthr-ui/main/CHANGELOG.md)",
|
|
122
|
+
"Bash(npm pack:*)",
|
|
123
|
+
"Bash(npx prettier:*)",
|
|
124
|
+
"Bash(pnpm prerelease:*)"
|
|
122
125
|
]
|
|
123
126
|
}
|
|
124
127
|
}
|
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
|
|
4
4
|
|
|
5
|
+
## [6.13.0](https://github.com/kufu/tamatebako/compare/eslint-plugin-smarthr-v6.12.1...eslint-plugin-smarthr-v6.13.0) (2026-04-20)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
### Features
|
|
9
|
+
|
|
10
|
+
* add autofixer for smarthr-ui v92 to v93 migration ([#1267](https://github.com/kufu/tamatebako/issues/1267)) ([cbff132](https://github.com/kufu/tamatebako/commit/cbff132559f93f4fdabc44a561ccc61afd4c8ed8))
|
|
11
|
+
|
|
5
12
|
## [6.12.1](https://github.com/kufu/tamatebako/compare/eslint-plugin-smarthr-v6.12.0...eslint-plugin-smarthr-v6.12.1) (2026-04-19)
|
|
6
13
|
|
|
7
14
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eslint-plugin-smarthr",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.13.0",
|
|
4
4
|
"author": "SmartHR",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"description": "A sharable ESLint plugin for SmartHR",
|
|
@@ -34,5 +34,5 @@
|
|
|
34
34
|
"eslintplugin",
|
|
35
35
|
"smarthr"
|
|
36
36
|
],
|
|
37
|
-
"gitHead": "
|
|
37
|
+
"gitHead": "75b2791f637c4769435be4f8cfe07cb2a2b5fa2d"
|
|
38
38
|
}
|
|
@@ -17,11 +17,13 @@
|
|
|
17
17
|
|
|
18
18
|
const v90ToV91 = require('./versions/v90-to-v91/index')
|
|
19
19
|
const v91ToV92 = require('./versions/v91-to-v92/index')
|
|
20
|
+
const v92ToV93 = require('./versions/v92-to-v93/index')
|
|
20
21
|
|
|
21
22
|
// サポートしているバージョン間の移行モジュール
|
|
22
23
|
const VERSION_MODULES = {
|
|
23
24
|
'v90-v91': v90ToV91,
|
|
24
25
|
'v91-v92': v91ToV92,
|
|
26
|
+
'v92-v93': v92ToV93,
|
|
25
27
|
}
|
|
26
28
|
|
|
27
29
|
module.exports = {
|
|
@@ -55,6 +57,7 @@ module.exports = {
|
|
|
55
57
|
skippedVersion: 'v{{version}} の自動修正ルールが実装されていません。変更内容は https://github.com/kufu/smarthr-ui/releases から対応するversionの情報を確認してください',
|
|
56
58
|
...v90ToV91.messages,
|
|
57
59
|
...v91ToV92.messages,
|
|
60
|
+
...v92ToV93.messages,
|
|
58
61
|
},
|
|
59
62
|
},
|
|
60
63
|
create(context) {
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
# smarthr-ui v92 → v93 移行ガイド
|
|
2
|
+
|
|
3
|
+
このドキュメントは、smarthr-ui v92からv93への移行に必要な変更をまとめたものです。
|
|
4
|
+
|
|
5
|
+
## 対応する破壊的変更
|
|
6
|
+
|
|
7
|
+
### 1. DropZone: decorators属性の削除
|
|
8
|
+
|
|
9
|
+
v93では、`DropZone`コンポーネントから`decorators`属性が削除されました。ファイル選択ボタンのラベルは、`selectButtonLabel`属性として独立しました。
|
|
10
|
+
|
|
11
|
+
#### 変更内容
|
|
12
|
+
|
|
13
|
+
**削除された属性:**
|
|
14
|
+
- `decorators?: DecoratorsType<'selectButtonLabel'>`
|
|
15
|
+
|
|
16
|
+
**追加された属性:**
|
|
17
|
+
- `selectButtonLabel?: string`
|
|
18
|
+
- ファイル選択ボタンのラベル
|
|
19
|
+
- 省略時はIntlProviderの翻訳が適用される(デフォルト: 「ファイルを選択」)
|
|
20
|
+
|
|
21
|
+
#### 移行方法
|
|
22
|
+
|
|
23
|
+
**Before (v92):**
|
|
24
|
+
```tsx
|
|
25
|
+
<DropZone decorators={{ selectButtonLabel: () => 'Choose File' }} />
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
**After (v93):**
|
|
29
|
+
```tsx
|
|
30
|
+
<DropZone selectButtonLabel="Choose File" />
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
**省略も可能(IntlProviderの翻訳を使用):**
|
|
34
|
+
```tsx
|
|
35
|
+
<DropZone />
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
#### 自動修正可能なパターン
|
|
39
|
+
|
|
40
|
+
以下のパターンは、ESLintの`--fix`オプションで自動的に修正されます:
|
|
41
|
+
|
|
42
|
+
```tsx
|
|
43
|
+
// 文字列リテラル
|
|
44
|
+
<DropZone decorators={{ selectButtonLabel: () => 'Choose' }} />
|
|
45
|
+
→ <DropZone selectButtonLabel="Choose" />
|
|
46
|
+
|
|
47
|
+
// 変数参照
|
|
48
|
+
<DropZone decorators={{ selectButtonLabel: () => buttonLabel }} />
|
|
49
|
+
→ <DropZone selectButtonLabel={buttonLabel} />
|
|
50
|
+
|
|
51
|
+
// 関数呼び出し
|
|
52
|
+
<DropZone decorators={{ selectButtonLabel: () => getLabel() }} />
|
|
53
|
+
→ <DropZone selectButtonLabel={getLabel()} />
|
|
54
|
+
|
|
55
|
+
// テンプレートリテラル
|
|
56
|
+
<DropZone decorators={{ selectButtonLabel: () => `Select ${fileType}` }} />
|
|
57
|
+
→ <DropZone selectButtonLabel={`Select ${fileType}`} />
|
|
58
|
+
|
|
59
|
+
// decorators が空の場合
|
|
60
|
+
<DropZone decorators={{}} />
|
|
61
|
+
→ <DropZone />
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
#### 手動対応が必要なパターン
|
|
65
|
+
|
|
66
|
+
以下のパターンは自動修正できません。手動で修正してください:
|
|
67
|
+
|
|
68
|
+
```tsx
|
|
69
|
+
// ❌ 引数を使用している場合
|
|
70
|
+
<DropZone decorators={{ selectButtonLabel: (defaultLabel) => customLabel || defaultLabel }} />
|
|
71
|
+
|
|
72
|
+
// ❌ BlockStatement(return文を使用)
|
|
73
|
+
<DropZone decorators={{ selectButtonLabel: () => { return 'Choose' } }} />
|
|
74
|
+
|
|
75
|
+
// ❌ spread syntax
|
|
76
|
+
<DropZone decorators={{ ...baseDecorators, selectButtonLabel: () => 'Choose' }} />
|
|
77
|
+
|
|
78
|
+
// ❌ selectButtonLabel以外のキーがある場合
|
|
79
|
+
<DropZone decorators={{ selectButtonLabel: () => 'Choose', otherKey: () => 'value' }} />
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
#### escape hatch className の変更
|
|
83
|
+
|
|
84
|
+
v93では、DropZoneコンポーネントのescape hatch用className(`smarthr-ui-DropZone`等)に変更はありません。
|
|
85
|
+
|
|
86
|
+
## ESLintルールの使用方法
|
|
87
|
+
|
|
88
|
+
### .eslintrc.js の設定
|
|
89
|
+
|
|
90
|
+
```javascript
|
|
91
|
+
module.exports = {
|
|
92
|
+
rules: {
|
|
93
|
+
'smarthr/autofixer-smarthr-ui-migration': ['error', { from: '92', to: '93' }],
|
|
94
|
+
},
|
|
95
|
+
}
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### 自動修正の実行
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
# エラーを確認
|
|
102
|
+
pnpm run lint
|
|
103
|
+
|
|
104
|
+
# 自動修正を実行
|
|
105
|
+
pnpm run lint --fix
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### smarthrUiAlias オプション
|
|
109
|
+
|
|
110
|
+
プロジェクト固有のsmarthr-ui aliasパスを使用している場合は、`smarthrUiAlias`オプションを指定してください。
|
|
111
|
+
|
|
112
|
+
```javascript
|
|
113
|
+
module.exports = {
|
|
114
|
+
rules: {
|
|
115
|
+
'smarthr/autofixer-smarthr-ui-migration': [
|
|
116
|
+
'error',
|
|
117
|
+
{
|
|
118
|
+
from: '92',
|
|
119
|
+
to: '93',
|
|
120
|
+
smarthrUiAlias: '@/components/parts/smarthr-ui', // プロジェクト固有のalias
|
|
121
|
+
},
|
|
122
|
+
],
|
|
123
|
+
},
|
|
124
|
+
}
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
## 参考リンク
|
|
128
|
+
|
|
129
|
+
- [smarthr-ui v93.0.0 リリースノート](https://github.com/kufu/smarthr-ui/releases/tag/smarthr-ui-v93.0.0)
|
|
130
|
+
- [PR #6236: DropZone の decorators 属性削除](https://github.com/kufu/smarthr-ui/pull/6236)
|
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
# v92-to-v93 実装の参考ポイント
|
|
2
|
+
|
|
3
|
+
このドキュメントは、v92→v93の移行ルール実装の構造と、新しいversionを追加する際の参考ポイントを説明します。
|
|
4
|
+
|
|
5
|
+
## v92→v93 特有の実装パターン
|
|
6
|
+
|
|
7
|
+
### 1. DropZone の decorators 属性削除と selectButtonLabel の移行
|
|
8
|
+
|
|
9
|
+
v93では DropZone コンポーネントから `decorators` 属性が削除されました。`selectButtonLabel` を新しい独立した属性に移行する必要があります。
|
|
10
|
+
|
|
11
|
+
#### 1-1. selectButtonLabel抽出のヘルパー関数
|
|
12
|
+
|
|
13
|
+
```javascript
|
|
14
|
+
/**
|
|
15
|
+
* decorators属性からselectButtonLabelを抽出し、移行可能かチェック
|
|
16
|
+
*
|
|
17
|
+
* @param {Object} decoratorsNode - decorators属性のASTノード
|
|
18
|
+
* @param {Object} sourceCode - ソースコード
|
|
19
|
+
* @returns {Object} 解析結果
|
|
20
|
+
* - type: 'spread' | 'migratable' | 'not-migratable' | 'no-label' | 'invalid' | 'other-keys'
|
|
21
|
+
* - value?: string (migratableの場合)
|
|
22
|
+
* - isStringLiteral?: boolean (migratableの場合)
|
|
23
|
+
*/
|
|
24
|
+
function extractSelectButtonLabel(decoratorsNode, sourceCode) {
|
|
25
|
+
// decorators={{ ... }} の形式か確認
|
|
26
|
+
if (!decoratorsNode.value || decoratorsNode.value.type !== 'JSXExpressionContainer') {
|
|
27
|
+
return { type: 'invalid' }
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const expression = decoratorsNode.value.expression
|
|
31
|
+
if (expression.type !== 'ObjectExpression') {
|
|
32
|
+
return { type: 'invalid' }
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// spread syntaxが含まれているかチェック
|
|
36
|
+
const hasSpread = expression.properties.some((prop) => prop.type === 'SpreadElement')
|
|
37
|
+
if (hasSpread) {
|
|
38
|
+
return { type: 'spread' }
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// selectButtonLabelプロパティを探す
|
|
42
|
+
const selectButtonLabelProp = expression.properties.find(
|
|
43
|
+
(prop) => prop.type === 'Property' && prop.key.name === 'selectButtonLabel'
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
if (!selectButtonLabelProp) {
|
|
47
|
+
return { type: 'no-label' }
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// selectButtonLabel以外のキーがある場合
|
|
51
|
+
if (expression.properties.length > 1) {
|
|
52
|
+
return { type: 'other-keys' }
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const value = selectButtonLabelProp.value
|
|
56
|
+
|
|
57
|
+
// ArrowFunctionExpressionで、引数なし、returnなしのパターンのみ対応
|
|
58
|
+
if (
|
|
59
|
+
value.type !== 'ArrowFunctionExpression' ||
|
|
60
|
+
value.params.length > 0 ||
|
|
61
|
+
value.body.type === 'BlockStatement'
|
|
62
|
+
) {
|
|
63
|
+
return { type: 'not-migratable' }
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// bodyの式を抽出
|
|
67
|
+
const bodyExpression = value.body
|
|
68
|
+
const bodyText = sourceCode.getText(bodyExpression)
|
|
69
|
+
|
|
70
|
+
// 文字列リテラルの場合は値を抽出(クォートを除く)
|
|
71
|
+
const isStringLiteral = bodyExpression.type === 'Literal' && typeof bodyExpression.value === 'string'
|
|
72
|
+
|
|
73
|
+
return {
|
|
74
|
+
type: 'migratable',
|
|
75
|
+
value: isStringLiteral ? bodyExpression.value : bodyText,
|
|
76
|
+
isStringLiteral,
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
**ポイント:**
|
|
82
|
+
- **spread syntax検出**: `SpreadElement` の存在をチェック
|
|
83
|
+
- **selectButtonLabelの有無**: プロパティが存在するかチェック
|
|
84
|
+
- **他のキーの存在**: selectButtonLabel以外のキーがないかチェック
|
|
85
|
+
- **自動移行可能性**: arrow function で引数なし、returnなし(`() => expression`)のみ対応
|
|
86
|
+
- **戻り値のtype分類**: spread / migratable / not-migratable / no-label / invalid / other-keys
|
|
87
|
+
|
|
88
|
+
#### 1-2. decorators属性のチェッカー(条件分岐)
|
|
89
|
+
|
|
90
|
+
```javascript
|
|
91
|
+
'JSXAttribute[name.name="decorators"]'(node) {
|
|
92
|
+
const componentName = node.parent.name.name
|
|
93
|
+
|
|
94
|
+
// DropZoneコンポーネントのみを対象
|
|
95
|
+
if (componentName !== 'DropZone') return
|
|
96
|
+
|
|
97
|
+
const result = extractSelectButtonLabel(node, sourceCode)
|
|
98
|
+
|
|
99
|
+
// spread syntaxがある場合 → エラーのみ(手動対応)
|
|
100
|
+
if (result.type === 'spread') {
|
|
101
|
+
context.report({
|
|
102
|
+
node,
|
|
103
|
+
messageId: 'migrateSelectButtonLabelManually',
|
|
104
|
+
data: { component: componentName, to: TARGET_VERSION },
|
|
105
|
+
// fixなし
|
|
106
|
+
})
|
|
107
|
+
return
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// selectButtonLabel以外のキーがある場合 → エラーのみ(手動対応)
|
|
111
|
+
if (result.type === 'other-keys') {
|
|
112
|
+
context.report({
|
|
113
|
+
node,
|
|
114
|
+
messageId: 'migrateSelectButtonLabelManually',
|
|
115
|
+
data: { component: componentName, to: TARGET_VERSION },
|
|
116
|
+
// fixなし
|
|
117
|
+
})
|
|
118
|
+
return
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// selectButtonLabelが自動移行可能な場合
|
|
122
|
+
if (result.type === 'migratable') {
|
|
123
|
+
context.report({
|
|
124
|
+
node,
|
|
125
|
+
messageId: 'removeDecorators',
|
|
126
|
+
data: { component: componentName, to: TARGET_VERSION },
|
|
127
|
+
fix(fixer) {
|
|
128
|
+
const fixes = []
|
|
129
|
+
|
|
130
|
+
// 1. selectButtonLabel属性を追加
|
|
131
|
+
const { value, isStringLiteral } = result
|
|
132
|
+
const selectButtonLabelAttr = isStringLiteral
|
|
133
|
+
? ` selectButtonLabel="${value}"`
|
|
134
|
+
: ` selectButtonLabel={${value}}`
|
|
135
|
+
fixes.push(fixer.insertTextAfter(node.parent.name, selectButtonLabelAttr))
|
|
136
|
+
|
|
137
|
+
// 2. decorators属性を削除
|
|
138
|
+
const tokenBefore = sourceCode.getTokenBefore(node)
|
|
139
|
+
if (tokenBefore && tokenBefore.range[1] < node.range[0]) {
|
|
140
|
+
fixes.push(fixer.removeRange([tokenBefore.range[1], node.range[1]]))
|
|
141
|
+
} else {
|
|
142
|
+
fixes.push(fixer.remove(node))
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
return fixes
|
|
146
|
+
},
|
|
147
|
+
})
|
|
148
|
+
return
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// selectButtonLabelが存在するが自動移行不可能な場合 → エラーのみ(手動対応)
|
|
152
|
+
if (result.type === 'not-migratable') {
|
|
153
|
+
context.report({
|
|
154
|
+
node,
|
|
155
|
+
messageId: 'migrateSelectButtonLabelManually',
|
|
156
|
+
data: { component: componentName, to: TARGET_VERSION },
|
|
157
|
+
// fixなし
|
|
158
|
+
})
|
|
159
|
+
return
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// selectButtonLabelがない場合 → decoratorsを削除
|
|
163
|
+
if (result.type === 'no-label') {
|
|
164
|
+
context.report({
|
|
165
|
+
node,
|
|
166
|
+
messageId: 'removeDecorators',
|
|
167
|
+
data: { component: componentName, to: TARGET_VERSION },
|
|
168
|
+
fix(fixer) {
|
|
169
|
+
const tokenBefore = sourceCode.getTokenBefore(node)
|
|
170
|
+
if (tokenBefore && tokenBefore.range[1] < node.range[0]) {
|
|
171
|
+
return fixer.removeRange([tokenBefore.range[1], node.range[1]])
|
|
172
|
+
}
|
|
173
|
+
return fixer.remove(node)
|
|
174
|
+
},
|
|
175
|
+
})
|
|
176
|
+
return
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
**処理フロー:**
|
|
182
|
+
1. **spread syntax** → エラーのみ(`migrateSelectButtonLabelManually`)
|
|
183
|
+
2. **selectButtonLabel以外のキーあり** → エラーのみ(`migrateSelectButtonLabelManually`)
|
|
184
|
+
3. **selectButtonLabel自動移行可能** → selectButtonLabel追加 + decorators削除
|
|
185
|
+
4. **selectButtonLabel自動移行不可能** → エラーのみ(`migrateSelectButtonLabelManually`)
|
|
186
|
+
5. **selectButtonLabelなし** → decorators削除のみ
|
|
187
|
+
|
|
188
|
+
**メッセージID:**
|
|
189
|
+
- `removeDecorators`: decorators削除(自動修正あり)
|
|
190
|
+
- `migrateSelectButtonLabelManually`: selectButtonLabelの手動移行が必要(自動修正なし)
|
|
191
|
+
|
|
192
|
+
## decorators属性のテストパターン(v92→v93特有)
|
|
193
|
+
|
|
194
|
+
#### パターン1: DropZone - selectButtonLabel自動移行
|
|
195
|
+
|
|
196
|
+
```javascript
|
|
197
|
+
// 文字列リテラル
|
|
198
|
+
{
|
|
199
|
+
code: `<DropZone decorators={{ selectButtonLabel: () => 'Choose File' }} />`,
|
|
200
|
+
output: `<DropZone selectButtonLabel="Choose File" />`,
|
|
201
|
+
options: v92ToV93Options,
|
|
202
|
+
errors: [{ messageId: 'removeDecorators', data: { component: 'DropZone', to: 'v93' } }],
|
|
203
|
+
},
|
|
204
|
+
|
|
205
|
+
// 変数参照
|
|
206
|
+
{
|
|
207
|
+
code: `<DropZone decorators={{ selectButtonLabel: () => buttonLabel }} />`,
|
|
208
|
+
output: `<DropZone selectButtonLabel={buttonLabel} />`,
|
|
209
|
+
options: v92ToV93Options,
|
|
210
|
+
errors: [{ messageId: 'removeDecorators', data: { component: 'DropZone', to: 'v93' } }],
|
|
211
|
+
},
|
|
212
|
+
|
|
213
|
+
// 関数呼び出し
|
|
214
|
+
{
|
|
215
|
+
code: `<DropZone decorators={{ selectButtonLabel: () => getLabel() }} />`,
|
|
216
|
+
output: `<DropZone selectButtonLabel={getLabel()} />`,
|
|
217
|
+
options: v92ToV93Options,
|
|
218
|
+
errors: [{ messageId: 'removeDecorators', data: { component: 'DropZone', to: 'v93' } }],
|
|
219
|
+
},
|
|
220
|
+
|
|
221
|
+
// テンプレートリテラル
|
|
222
|
+
{
|
|
223
|
+
code: `<DropZone decorators={{ selectButtonLabel: () => \`Select \${fileType}\` }} />`,
|
|
224
|
+
output: `<DropZone selectButtonLabel={\`Select \${fileType}\`} />`,
|
|
225
|
+
options: v92ToV93Options,
|
|
226
|
+
errors: [{ messageId: 'removeDecorators', data: { component: 'DropZone', to: 'v93' } }],
|
|
227
|
+
},
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
#### パターン2: DropZone - selectButtonLabelがない
|
|
231
|
+
|
|
232
|
+
```javascript
|
|
233
|
+
// decorators削除のみ(selectButtonLabelなし)
|
|
234
|
+
{
|
|
235
|
+
code: `<DropZone decorators={{}} />`,
|
|
236
|
+
output: `<DropZone />`,
|
|
237
|
+
options: v92ToV93Options,
|
|
238
|
+
errors: [{ messageId: 'removeDecorators', data: { component: 'DropZone', to: 'v93' } }],
|
|
239
|
+
},
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
#### パターン3: DropZone - 手動対応が必要(エラーのみ、outputなし)
|
|
243
|
+
|
|
244
|
+
```javascript
|
|
245
|
+
// returnあり
|
|
246
|
+
{
|
|
247
|
+
code: `<DropZone decorators={{ selectButtonLabel: () => { return 'Choose' } }} />`,
|
|
248
|
+
options: v92ToV93Options,
|
|
249
|
+
errors: [{ messageId: 'migrateSelectButtonLabelManually', data: { component: 'DropZone', to: 'v93' } }],
|
|
250
|
+
},
|
|
251
|
+
|
|
252
|
+
// 引数あり
|
|
253
|
+
{
|
|
254
|
+
code: `<DropZone decorators={{ selectButtonLabel: (defaultLabel) => defaultLabel }} />`,
|
|
255
|
+
options: v92ToV93Options,
|
|
256
|
+
errors: [{ messageId: 'migrateSelectButtonLabelManually', data: { component: 'DropZone', to: 'v93' } }],
|
|
257
|
+
},
|
|
258
|
+
|
|
259
|
+
// spread syntax
|
|
260
|
+
{
|
|
261
|
+
code: `<DropZone decorators={{ ...baseDecorators, selectButtonLabel: () => 'Choose' }} />`,
|
|
262
|
+
options: v92ToV93Options,
|
|
263
|
+
errors: [{ messageId: 'migrateSelectButtonLabelManually', data: { component: 'DropZone', to: 'v93' } }],
|
|
264
|
+
},
|
|
265
|
+
|
|
266
|
+
// selectButtonLabel以外のキーがある
|
|
267
|
+
{
|
|
268
|
+
code: `<DropZone decorators={{ selectButtonLabel: () => 'Choose', otherKey: () => 'value' }} />`,
|
|
269
|
+
options: v92ToV93Options,
|
|
270
|
+
errors: [{ messageId: 'migrateSelectButtonLabelManually', data: { component: 'DropZone', to: 'v93' } }],
|
|
271
|
+
},
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
**ポイント:**
|
|
275
|
+
- **outputあり**: 自動修正が行われる
|
|
276
|
+
- **outputなし**: エラーのみ(手動対応が必要)
|
|
277
|
+
- **messageId**: `removeDecorators`(自動修正)または `migrateSelectButtonLabelManually`(手動対応)
|
|
278
|
+
|
|
279
|
+
## 最新versionへの参照(重要)
|
|
280
|
+
|
|
281
|
+
**このREFERENCE.mdを作成したら、DEVELOPER.mdの「参考にするファイル」セクションを必ず更新してください!**
|
|
282
|
+
|
|
283
|
+
更新箇所:
|
|
284
|
+
- `rules/autofixer-smarthr-ui-migration/DEVELOPER.md` の56-65行目付近
|
|
285
|
+
- `v91-to-v92` → `v92-to-v93` に変更
|
|
286
|
+
|
|
287
|
+
これにより、次回以降のversion追加時に最新の実装パターンを参照できるようになります。
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* smarthr-ui v92 → v93 移行ルール
|
|
3
|
+
*
|
|
4
|
+
* v93での破壊的変更に対応する自動修正を提供します。
|
|
5
|
+
*
|
|
6
|
+
* 対応する破壊的変更:
|
|
7
|
+
* 1. DropZone の decorators 属性削除
|
|
8
|
+
* - decorators={{ selectButtonLabel: () => 'label' }} → selectButtonLabel="label"
|
|
9
|
+
* - decorators なしの場合、IntlProviderの翻訳が適用される
|
|
10
|
+
*
|
|
11
|
+
* 参考: https://github.com/kufu/smarthr-ui/releases/tag/smarthr-ui-v93.0.0
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
const { setupSmarthrUiAliasOptions } = require('../../helpers')
|
|
15
|
+
|
|
16
|
+
// ============================================================
|
|
17
|
+
// 定数定義
|
|
18
|
+
// ============================================================
|
|
19
|
+
|
|
20
|
+
// v93を示す定数(メッセージで使用)
|
|
21
|
+
const TARGET_VERSION = 'v93'
|
|
22
|
+
|
|
23
|
+
// ============================================================
|
|
24
|
+
// モジュールエクスポート
|
|
25
|
+
// ============================================================
|
|
26
|
+
|
|
27
|
+
module.exports = {
|
|
28
|
+
messages: {
|
|
29
|
+
removeDecorators: 'smarthr-ui {{to}} では {{component}} の decorators 属性は削除されました。selectButtonLabel 属性を使用してください',
|
|
30
|
+
migrateSelectButtonLabelManually: '{{component}} の decorators.selectButtonLabel を手動で移行してください。selectButtonLabel属性として独立しました。詳細: https://github.com/kufu/smarthr-ui/pull/6236',
|
|
31
|
+
},
|
|
32
|
+
|
|
33
|
+
createCheckers(context, sourceCode, options = {}) {
|
|
34
|
+
const { validSources, isAliasFile, filename } = setupSmarthrUiAliasOptions(context, options)
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* decorators属性からselectButtonLabelを抽出し、移行可能かチェック
|
|
38
|
+
*
|
|
39
|
+
* @param {Object} decoratorsNode - decorators属性のASTノード
|
|
40
|
+
* @returns {Object} 解析結果
|
|
41
|
+
* - type: 'spread' | 'migratable' | 'not-migratable' | 'no-label' | 'invalid' | 'other-keys'
|
|
42
|
+
* - value?: string (migratableの場合)
|
|
43
|
+
* - isStringLiteral?: boolean (migratableの場合)
|
|
44
|
+
*/
|
|
45
|
+
function extractSelectButtonLabel(decoratorsNode) {
|
|
46
|
+
// decorators={{ ... }} の形式か確認
|
|
47
|
+
if (!decoratorsNode.value || decoratorsNode.value.type !== 'JSXExpressionContainer') {
|
|
48
|
+
return { type: 'invalid' }
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const expression = decoratorsNode.value.expression
|
|
52
|
+
if (expression.type !== 'ObjectExpression') {
|
|
53
|
+
return { type: 'invalid' }
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// spread syntaxが含まれているかチェック
|
|
57
|
+
const hasSpread = expression.properties.some((prop) => prop.type === 'SpreadElement')
|
|
58
|
+
if (hasSpread) {
|
|
59
|
+
return { type: 'spread' }
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// selectButtonLabelプロパティを探す
|
|
63
|
+
const selectButtonLabelProp = expression.properties.find(
|
|
64
|
+
(prop) => prop.type === 'Property' && prop.key.name === 'selectButtonLabel'
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
if (!selectButtonLabelProp) {
|
|
68
|
+
return { type: 'no-label' }
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// selectButtonLabel以外のキーがある場合
|
|
72
|
+
if (expression.properties.length > 1) {
|
|
73
|
+
return { type: 'other-keys' }
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const value = selectButtonLabelProp.value
|
|
77
|
+
|
|
78
|
+
// ArrowFunctionExpressionで、引数なし、returnなしのパターンのみ対応
|
|
79
|
+
if (
|
|
80
|
+
value.type !== 'ArrowFunctionExpression' ||
|
|
81
|
+
value.params.length > 0 ||
|
|
82
|
+
value.body.type === 'BlockStatement'
|
|
83
|
+
) {
|
|
84
|
+
return { type: 'not-migratable' }
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// bodyの式を抽出
|
|
88
|
+
const bodyExpression = value.body
|
|
89
|
+
const bodyText = sourceCode.getText(bodyExpression)
|
|
90
|
+
|
|
91
|
+
// 文字列リテラルの場合は値を抽出(クォートを除く)
|
|
92
|
+
const isStringLiteral = bodyExpression.type === 'Literal' && typeof bodyExpression.value === 'string'
|
|
93
|
+
|
|
94
|
+
return {
|
|
95
|
+
type: 'migratable',
|
|
96
|
+
value: isStringLiteral ? bodyExpression.value : bodyText,
|
|
97
|
+
isStringLiteral,
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const checkers = {
|
|
102
|
+
// ============================================================
|
|
103
|
+
// DropZone の decorators 属性削除
|
|
104
|
+
// ============================================================
|
|
105
|
+
|
|
106
|
+
'JSXAttribute[name.name="decorators"]'(node) {
|
|
107
|
+
const componentName = node.parent.name.name
|
|
108
|
+
|
|
109
|
+
// DropZoneコンポーネントのみを対象
|
|
110
|
+
if (componentName !== 'DropZone') return
|
|
111
|
+
|
|
112
|
+
const result = extractSelectButtonLabel(node)
|
|
113
|
+
|
|
114
|
+
// spread syntaxがある場合 → エラーのみ(手動対応)
|
|
115
|
+
if (result.type === 'spread') {
|
|
116
|
+
context.report({
|
|
117
|
+
node,
|
|
118
|
+
messageId: 'migrateSelectButtonLabelManually',
|
|
119
|
+
data: { component: componentName, to: TARGET_VERSION },
|
|
120
|
+
})
|
|
121
|
+
return
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// selectButtonLabel以外のキーがある場合 → エラーのみ(手動対応)
|
|
125
|
+
if (result.type === 'other-keys') {
|
|
126
|
+
context.report({
|
|
127
|
+
node,
|
|
128
|
+
messageId: 'migrateSelectButtonLabelManually',
|
|
129
|
+
data: { component: componentName, to: TARGET_VERSION },
|
|
130
|
+
})
|
|
131
|
+
return
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// selectButtonLabelが自動移行可能な場合
|
|
135
|
+
if (result.type === 'migratable') {
|
|
136
|
+
context.report({
|
|
137
|
+
node,
|
|
138
|
+
messageId: 'removeDecorators',
|
|
139
|
+
data: { component: componentName, to: TARGET_VERSION },
|
|
140
|
+
fix(fixer) {
|
|
141
|
+
const fixes = []
|
|
142
|
+
|
|
143
|
+
// 1. selectButtonLabel属性を追加
|
|
144
|
+
const { value, isStringLiteral } = result
|
|
145
|
+
const selectButtonLabelAttr = isStringLiteral
|
|
146
|
+
? ` selectButtonLabel="${value}"`
|
|
147
|
+
: ` selectButtonLabel={${value}}`
|
|
148
|
+
fixes.push(fixer.insertTextAfter(node.parent.name, selectButtonLabelAttr))
|
|
149
|
+
|
|
150
|
+
// 2. decorators属性を削除
|
|
151
|
+
const tokenBefore = sourceCode.getTokenBefore(node)
|
|
152
|
+
if (tokenBefore && tokenBefore.range[1] < node.range[0]) {
|
|
153
|
+
fixes.push(fixer.removeRange([tokenBefore.range[1], node.range[1]]))
|
|
154
|
+
} else {
|
|
155
|
+
fixes.push(fixer.remove(node))
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
return fixes
|
|
159
|
+
},
|
|
160
|
+
})
|
|
161
|
+
return
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// selectButtonLabelが存在するが自動移行不可能な場合 → エラーのみ(手動対応)
|
|
165
|
+
if (result.type === 'not-migratable') {
|
|
166
|
+
context.report({
|
|
167
|
+
node,
|
|
168
|
+
messageId: 'migrateSelectButtonLabelManually',
|
|
169
|
+
data: { component: componentName, to: TARGET_VERSION },
|
|
170
|
+
})
|
|
171
|
+
return
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// selectButtonLabelがない場合 → decoratorsを削除
|
|
175
|
+
if (result.type === 'no-label') {
|
|
176
|
+
context.report({
|
|
177
|
+
node,
|
|
178
|
+
messageId: 'removeDecorators',
|
|
179
|
+
data: { component: componentName, to: TARGET_VERSION },
|
|
180
|
+
fix(fixer) {
|
|
181
|
+
const tokenBefore = sourceCode.getTokenBefore(node)
|
|
182
|
+
if (tokenBefore && tokenBefore.range[1] < node.range[0]) {
|
|
183
|
+
return fixer.removeRange([tokenBefore.range[1], node.range[1]])
|
|
184
|
+
}
|
|
185
|
+
return fixer.remove(node)
|
|
186
|
+
},
|
|
187
|
+
})
|
|
188
|
+
return
|
|
189
|
+
}
|
|
190
|
+
},
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// aliasファイルの場合、export変数名の置換は不要
|
|
194
|
+
// (DropZoneはリネームされないため)
|
|
195
|
+
|
|
196
|
+
return checkers
|
|
197
|
+
},
|
|
198
|
+
}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* smarthr-ui v92 → v93 移行ルール テストケース
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
const v92ToV93Options = [{ from: '92', to: '93' }]
|
|
6
|
+
|
|
7
|
+
// ============================================================
|
|
8
|
+
// validテストケース(エラーにならないコード)
|
|
9
|
+
// ============================================================
|
|
10
|
+
|
|
11
|
+
const valid = [
|
|
12
|
+
// decorators属性なし
|
|
13
|
+
{ code: `<DropZone />`, options: v92ToV93Options },
|
|
14
|
+
{ code: `<DropZone selectButtonLabel="Choose File" />`, options: v92ToV93Options },
|
|
15
|
+
|
|
16
|
+
// DropZone以外のコンポーネント(decorators属性があってもエラーにしない)
|
|
17
|
+
{ code: `<OtherComponent decorators={{ key: () => 'value' }} />`, options: v92ToV93Options },
|
|
18
|
+
]
|
|
19
|
+
|
|
20
|
+
// ============================================================
|
|
21
|
+
// invalidテストケース(エラーになり、自動修正されるコード)
|
|
22
|
+
// ============================================================
|
|
23
|
+
|
|
24
|
+
const invalid = [
|
|
25
|
+
// ============================================================
|
|
26
|
+
// 1. DropZone - selectButtonLabel 自動移行
|
|
27
|
+
// ============================================================
|
|
28
|
+
|
|
29
|
+
// 文字列リテラル
|
|
30
|
+
{
|
|
31
|
+
code: `<DropZone decorators={{ selectButtonLabel: () => 'Choose File' }} />`,
|
|
32
|
+
output: `<DropZone selectButtonLabel="Choose File" />`,
|
|
33
|
+
options: v92ToV93Options,
|
|
34
|
+
errors: [{ messageId: 'removeDecorators', data: { component: 'DropZone', to: 'v93' } }],
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
code: `<DropZone decorators={{ selectButtonLabel: () => "選択" }} />`,
|
|
38
|
+
output: `<DropZone selectButtonLabel="選択" />`,
|
|
39
|
+
options: v92ToV93Options,
|
|
40
|
+
errors: [{ messageId: 'removeDecorators', data: { component: 'DropZone', to: 'v93' } }],
|
|
41
|
+
},
|
|
42
|
+
|
|
43
|
+
// 変数参照
|
|
44
|
+
{
|
|
45
|
+
code: `<DropZone decorators={{ selectButtonLabel: () => buttonLabel }} />`,
|
|
46
|
+
output: `<DropZone selectButtonLabel={buttonLabel} />`,
|
|
47
|
+
options: v92ToV93Options,
|
|
48
|
+
errors: [{ messageId: 'removeDecorators', data: { component: 'DropZone', to: 'v93' } }],
|
|
49
|
+
},
|
|
50
|
+
|
|
51
|
+
// 関数呼び出し
|
|
52
|
+
{
|
|
53
|
+
code: `<DropZone decorators={{ selectButtonLabel: () => getLabel() }} />`,
|
|
54
|
+
output: `<DropZone selectButtonLabel={getLabel()} />`,
|
|
55
|
+
options: v92ToV93Options,
|
|
56
|
+
errors: [{ messageId: 'removeDecorators', data: { component: 'DropZone', to: 'v93' } }],
|
|
57
|
+
},
|
|
58
|
+
|
|
59
|
+
// テンプレートリテラル
|
|
60
|
+
{
|
|
61
|
+
code: `<DropZone decorators={{ selectButtonLabel: () => \`Select \${fileType}\` }} />`,
|
|
62
|
+
output: `<DropZone selectButtonLabel={\`Select \${fileType}\`} />`,
|
|
63
|
+
options: v92ToV93Options,
|
|
64
|
+
errors: [{ messageId: 'removeDecorators', data: { component: 'DropZone', to: 'v93' } }],
|
|
65
|
+
},
|
|
66
|
+
|
|
67
|
+
// 三項演算子
|
|
68
|
+
{
|
|
69
|
+
code: `<DropZone decorators={{ selectButtonLabel: () => isJapanese ? '選択' : 'Choose' }} />`,
|
|
70
|
+
output: `<DropZone selectButtonLabel={isJapanese ? '選択' : 'Choose'} />`,
|
|
71
|
+
options: v92ToV93Options,
|
|
72
|
+
errors: [{ messageId: 'removeDecorators', data: { component: 'DropZone', to: 'v93' } }],
|
|
73
|
+
},
|
|
74
|
+
|
|
75
|
+
// 複数の属性がある場合
|
|
76
|
+
{
|
|
77
|
+
code: `<DropZone accept="image/*" decorators={{ selectButtonLabel: () => 'Choose' }} multiple />`,
|
|
78
|
+
output: `<DropZone selectButtonLabel="Choose" accept="image/*" multiple />`,
|
|
79
|
+
options: v92ToV93Options,
|
|
80
|
+
errors: [{ messageId: 'removeDecorators', data: { component: 'DropZone', to: 'v93' } }],
|
|
81
|
+
},
|
|
82
|
+
|
|
83
|
+
// ============================================================
|
|
84
|
+
// 2. DropZone - selectButtonLabel なし(decorators削除のみ)
|
|
85
|
+
// ============================================================
|
|
86
|
+
|
|
87
|
+
{
|
|
88
|
+
code: `<DropZone decorators={{}} />`,
|
|
89
|
+
output: `<DropZone />`,
|
|
90
|
+
options: v92ToV93Options,
|
|
91
|
+
errors: [{ messageId: 'removeDecorators', data: { component: 'DropZone', to: 'v93' } }],
|
|
92
|
+
},
|
|
93
|
+
|
|
94
|
+
// ============================================================
|
|
95
|
+
// 3. DropZone - 手動対応が必要(エラーのみ、outputなし)
|
|
96
|
+
// ============================================================
|
|
97
|
+
|
|
98
|
+
// returnあり(BlockStatement)
|
|
99
|
+
{
|
|
100
|
+
code: `<DropZone decorators={{ selectButtonLabel: () => { return 'Choose' } }} />`,
|
|
101
|
+
options: v92ToV93Options,
|
|
102
|
+
errors: [{ messageId: 'migrateSelectButtonLabelManually', data: { component: 'DropZone', to: 'v93' } }],
|
|
103
|
+
},
|
|
104
|
+
|
|
105
|
+
// 引数あり
|
|
106
|
+
{
|
|
107
|
+
code: `<DropZone decorators={{ selectButtonLabel: (defaultLabel) => defaultLabel }} />`,
|
|
108
|
+
options: v92ToV93Options,
|
|
109
|
+
errors: [{ messageId: 'migrateSelectButtonLabelManually', data: { component: 'DropZone', to: 'v93' } }],
|
|
110
|
+
},
|
|
111
|
+
|
|
112
|
+
// spread syntax
|
|
113
|
+
{
|
|
114
|
+
code: `<DropZone decorators={{ ...baseDecorators, selectButtonLabel: () => 'Choose' }} />`,
|
|
115
|
+
options: v92ToV93Options,
|
|
116
|
+
errors: [{ messageId: 'migrateSelectButtonLabelManually', data: { component: 'DropZone', to: 'v93' } }],
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
code: `<DropZone decorators={{ selectButtonLabel: () => 'Choose', ...rest }} />`,
|
|
120
|
+
options: v92ToV93Options,
|
|
121
|
+
errors: [{ messageId: 'migrateSelectButtonLabelManually', data: { component: 'DropZone', to: 'v93' } }],
|
|
122
|
+
},
|
|
123
|
+
|
|
124
|
+
// selectButtonLabel以外のキーがある
|
|
125
|
+
{
|
|
126
|
+
code: `<DropZone decorators={{ selectButtonLabel: () => 'Choose', otherKey: () => 'value' }} />`,
|
|
127
|
+
options: v92ToV93Options,
|
|
128
|
+
errors: [{ messageId: 'migrateSelectButtonLabelManually', data: { component: 'DropZone', to: 'v93' } }],
|
|
129
|
+
},
|
|
130
|
+
]
|
|
131
|
+
|
|
132
|
+
module.exports = {
|
|
133
|
+
valid,
|
|
134
|
+
invalid,
|
|
135
|
+
}
|
|
@@ -2,6 +2,7 @@ const rule = require('../rules/autofixer-smarthr-ui-migration')
|
|
|
2
2
|
const RuleTester = require('eslint').RuleTester
|
|
3
3
|
const v90ToV91Tests = require('../rules/autofixer-smarthr-ui-migration/versions/v90-to-v91/test')
|
|
4
4
|
const v91ToV92Tests = require('../rules/autofixer-smarthr-ui-migration/versions/v91-to-v92/test')
|
|
5
|
+
const v92ToV93Tests = require('../rules/autofixer-smarthr-ui-migration/versions/v92-to-v93/test')
|
|
5
6
|
|
|
6
7
|
const ruleTester = new RuleTester({
|
|
7
8
|
languageOptions: {
|
|
@@ -17,6 +18,7 @@ ruleTester.run('autofixer-smarthr-ui-migration', rule, {
|
|
|
17
18
|
valid: [
|
|
18
19
|
...v90ToV91Tests.valid,
|
|
19
20
|
...v91ToV92Tests.valid,
|
|
21
|
+
...v92ToV93Tests.valid,
|
|
20
22
|
],
|
|
21
23
|
|
|
22
24
|
invalid: [
|
|
@@ -29,7 +31,7 @@ ruleTester.run('autofixer-smarthr-ui-migration', rule, {
|
|
|
29
31
|
},
|
|
30
32
|
{
|
|
31
33
|
code: `import { ActionDialog } from 'smarthr-ui'`,
|
|
32
|
-
options: [{ from: '
|
|
34
|
+
options: [{ from: '93', to: '94' }],
|
|
33
35
|
errors: [{ messageId: 'unsupportedVersion' }],
|
|
34
36
|
},
|
|
35
37
|
|
|
@@ -37,12 +39,10 @@ ruleTester.run('autofixer-smarthr-ui-migration', rule, {
|
|
|
37
39
|
// 複数バージョンスキップ
|
|
38
40
|
// ============================================================
|
|
39
41
|
{
|
|
40
|
-
code: `import {
|
|
41
|
-
|
|
42
|
-
options: [{ from: '91', to: '93' }],
|
|
42
|
+
code: `import { DropZone } from 'smarthr-ui'`,
|
|
43
|
+
options: [{ from: '92', to: '94' }],
|
|
43
44
|
errors: [
|
|
44
|
-
{ messageId: 'skippedVersion', data: { version: '
|
|
45
|
-
{ messageId: 'renameRemoteTriggerDialog', data: { old: 'RemoteTriggerActionDialog', new: 'ActionDialog', to: 'v92' } },
|
|
45
|
+
{ messageId: 'skippedVersion', data: { version: 'v94' } },
|
|
46
46
|
],
|
|
47
47
|
},
|
|
48
48
|
{
|
|
@@ -65,5 +65,6 @@ ruleTester.run('autofixer-smarthr-ui-migration', rule, {
|
|
|
65
65
|
// ============================================================
|
|
66
66
|
...v90ToV91Tests.invalid,
|
|
67
67
|
...v91ToV92Tests.invalid,
|
|
68
|
+
...v92ToV93Tests.invalid,
|
|
68
69
|
],
|
|
69
70
|
})
|