Skip to content

Commit 70922f0

Browse files
committed
fix easy rule warnings from docs/biome-cleanup-todo.md
1 parent e777fb0 commit 70922f0

File tree

10 files changed

+210
-33
lines changed

10 files changed

+210
-33
lines changed

biome.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,10 @@
4242
"noStaticOnlyClass": "off"
4343
},
4444
"correctness": {
45-
"noUnusedVariables": "warn",
45+
"noUnusedVariables": "error",
4646
"noUnusedImports": "warn",
4747
"noUnusedFunctionParameters": "off",
48-
"useJsxKeyInIterable": "warn",
48+
"useJsxKeyInIterable": "error",
4949
"useExhaustiveDependencies": "off",
5050
"noUnknownProperty": "off"
5151
},
@@ -59,7 +59,7 @@
5959
"noAlert": "off",
6060
"noConsole": "off",
6161
"noArrayIndexKey": "off",
62-
"noImportAssign": "warn",
62+
"noImportAssign": "error",
6363
"useIterableCallbackReturn": "off",
6464
"noAsyncPromiseExecutor": "warn"
6565
},

docs/biome-cleanup-todo.md

Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
# Biome Code Cleanup TODO
2+
3+
This document lists suggested code improvements identified during the Biome migration. Items are prioritized by impact and effort.
4+
5+
## Priority 1: Quick Wins (Low effort, High value)
6+
7+
### Fix Missing React Keys
8+
9+
**Rule:** `useJsxKeyInIterable`
10+
**Current:** warn
11+
**Files:**
12+
13+
- `ui/infra-compare/InfraCompareTable.jsx:74` - Add key to `<tbody>`
14+
- `ui/infra-compare/InfraCompareTableControls.jsx:134` - Add key to `<InfraCompareTable>`
15+
- `ui/perfherder/alerts/AlertHeader.jsx:233` - Add key to `<Link>`
16+
- `ui/shared/AdditionalInformationTable.jsx:165` - Add key to `<tr>`
17+
- `ui/shared/AdditionalInformationTable.jsx:183` - Add key to `<tr>`
18+
19+
**Why:** Missing keys can cause React rendering bugs and performance issues.
20+
21+
### Remove Unused Variables
22+
23+
**Rule:** `noUnusedVariables`
24+
**Current:** warn
25+
**Files:**
26+
27+
- `ui/perfherder/graphs/GraphsContainer.jsx:325` - `selectedDataPoint` unused
28+
- `ui/perfherder/graphs/GraphsContainer.jsx:326` - `highlightAlerts` unused
29+
30+
**Why:** Dead code that should be removed.
31+
32+
### Fix Import Assignment
33+
34+
**Rule:** `noImportAssign`
35+
**Current:** warn
36+
**File:** `ui/taskcluster-auth-callback/TaskclusterCallback.jsx:30`
37+
38+
**Why:** Reassigning an imported variable is a bug - imports are read-only. Use a local variable instead.
39+
40+
---
41+
42+
## Priority 2: Code Quality (Medium effort, High value)
43+
44+
### Fix Async Promise Executor
45+
46+
**Rule:** `noAsyncPromiseExecutor`
47+
**Current:** warn
48+
**File:** `ui/shared/auth/AuthService.js:19`
49+
50+
**Why:** Async promise executors can silently swallow errors. Refactor to use async/await directly without wrapping in Promise.
51+
52+
### Enable React Hooks Exhaustive Dependencies
53+
54+
**Rule:** `useExhaustiveDependencies`
55+
**Current:** off
56+
**Estimated files:** ~10
57+
58+
**Why:** Missing dependencies in useEffect/useCallback can cause stale closures and subtle bugs.
59+
60+
### Enable Array Index Key Warnings
61+
62+
**Rule:** `noArrayIndexKey`
63+
**Current:** off
64+
**Estimated files:** ~5
65+
66+
**Why:** Using array index as key can cause issues when list items are reordered or filtered.
67+
68+
---
69+
70+
## Priority 3: Performance (Medium effort, Medium value)
71+
72+
### Fix Accumulating Spread Operations
73+
74+
**Rule:** `noAccumulatingSpread`
75+
**Current:** off
76+
**Files:** Multiple locations in reducers and helpers
77+
78+
**Why:** Spreading in a loop (e.g., `arr.reduce((acc, x) => [...acc, x])`) is O(n²). Use `push()` or `concat()` instead.
79+
80+
### Enable useFlatMap
81+
82+
**Rule:** `useFlatMap`
83+
**Current:** off
84+
85+
**Why:** Replace `.map().flat()` with `.flatMap()` for better performance and readability.
86+
87+
---
88+
89+
## Priority 4: Accessibility (Higher effort, High value)
90+
91+
### Enable Semantic Elements
92+
93+
**Rule:** `useSemanticElements`
94+
**Current:** off
95+
**Estimated files:** ~15
96+
97+
**Why:** Using `role="button"` on `<div>` instead of `<button>` reduces accessibility. Requires careful testing.
98+
99+
### Enable ARIA Props Validation
100+
101+
**Rule:** `useAriaPropsSupportedByRole`
102+
**Current:** off
103+
104+
**Why:** Ensures ARIA attributes are valid for the element's role.
105+
106+
### Enable SVG Accessibility
107+
108+
**Rule:** `noSvgWithoutTitle`
109+
**Current:** off
110+
**File:** `ui/shared/GraphIcon.jsx:28`
111+
112+
**Why:** SVGs should have titles for screen readers.
113+
114+
---
115+
116+
## Priority 5: Code Style (Optional)
117+
118+
### Enable Formatter
119+
120+
**Current:** disabled
121+
122+
Enabling the Biome formatter would standardize code style across the codebase. This is a large change that would touch many files. Consider doing this in a separate PR.
123+
124+
### Enable Import Organization
125+
126+
**Current:** disabled
127+
128+
Biome can auto-organize imports. This would be a large change affecting many files.
129+
130+
### Refactor Static-Only Classes
131+
132+
**Rule:** `noStaticOnlyClass`
133+
**Current:** off
134+
**Files:** Multiple files in `ui/models/`
135+
136+
**Why:** Classes with only static methods could be plain objects or ES modules. This is a stylistic preference.
137+
138+
---
139+
140+
## How to Enable Rules
141+
142+
To enable a rule, update `biome.json`:
143+
144+
```json
145+
{
146+
"linter": {
147+
"rules": {
148+
"correctness": {
149+
"useJsxKeyInIterable": "error" // Change from "warn" to "error"
150+
}
151+
}
152+
}
153+
}
154+
```
155+
156+
To auto-fix issues where possible:
157+
158+
```bash
159+
pnpm biome lint --write
160+
```
161+
162+
---
163+
164+
## Tracking Progress
165+
166+
- [ ] Priority 1: Quick Wins
167+
- [ ] Priority 2: Code Quality
168+
- [ ] Priority 3: Performance
169+
- [ ] Priority 4: Accessibility
170+
- [ ] Priority 5: Code Style (optional)

tests/ui/infra-compare/InfraCompare.test.jsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -81,9 +81,9 @@ describe('InfraCompareView', () => {
8181
// Reset the mock props
8282
mockTableViewProps = {};
8383
// Mock Date.now() to return a fixed timestamp for consistent testing
84-
jest
85-
.spyOn(Date.prototype, 'getTime')
86-
.mockImplementation(() => 1596340000000);
84+
// The mock timestamps (push_timestamp) are around 1596240000-1596250000
85+
// We need Date.now() to be close to these values (within 30 days = 2592000 seconds)
86+
jest.spyOn(Date, 'now').mockImplementation(() => 1596340000 * 1000);
8787
});
8888

8989
afterEach(() => {

ui/css/treeherder-job-buttons.css

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -9,21 +9,21 @@
99

1010
.job-btn {
1111
background-color: transparent;
12-
padding: 0 2px 0 2px;
13-
vertical-align: 0;
14-
line-height: 1.32;
12+
padding: 0 2px 0 2px !important;
13+
vertical-align: 0 !important;
14+
line-height: 1.32 !important;
1515
display: none;
1616
transition: transform 0.1s;
17-
font-size: 12px;
17+
font-size: 12px !important;
1818
}
1919

2020
.group-btn {
2121
background: transparent;
22-
padding: 0 2px 0 2px;
23-
vertical-align: 0;
24-
line-height: 1.32;
22+
padding: 0 2px 0 2px !important;
23+
vertical-align: 0 !important;
24+
line-height: 1.32 !important;
2525
cursor: pointer;
26-
font-size: 12px;
26+
font-size: 12px !important;
2727
}
2828

2929
.group-btn::before {
@@ -36,10 +36,10 @@
3636

3737
.group-symbol {
3838
background: transparent;
39-
padding: 0 2px 0 2px;
39+
padding: 0 2px 0 2px !important;
4040
border: 0;
41-
vertical-align: 0;
42-
line-height: 1.32;
41+
vertical-align: 0 !important;
42+
line-height: 1.32 !important;
4343
cursor: pointer;
4444
margin-right: -3px;
4545
}
@@ -75,10 +75,10 @@
7575
color: rgba(128, 128, 0, 0.5);
7676
margin: 0;
7777
background: transparent;
78-
padding: 0 2px;
79-
vertical-align: 0;
80-
line-height: 1.32;
81-
font-size: 12px;
78+
padding: 0 2px !important;
79+
vertical-align: 0 !important;
80+
line-height: 1.32 !important;
81+
font-size: 12px !important;
8282
border-radius: 0;
8383
text-align: center;
8484
white-space: nowrap;
@@ -93,12 +93,12 @@
9393
/* Selected jobs: white background for classified failures and non-failures */
9494
.job-btn.selected-job:not([data-status='testfailed']):not([data-status='busted']):not([data-status='exception']),
9595
.job-btn.selected-job[data-classified='true'] {
96-
background: #fff;
96+
background: #fff !important;
9797
}
9898

9999
/* All selected jobs get outline matching text color */
100100
.job-btn.selected-job {
101-
outline: 4px solid;
101+
outline: 4px solid !important;
102102
outline-color: currentcolor;
103103
}
104104

@@ -426,7 +426,7 @@
426426
background: transparent;
427427
padding: 0 2px 0 2px;
428428
border: 0;
429-
vertical-align: 0;
429+
vertical-align: 0 !important;
430430
line-height: 1.32;
431431
cursor: pointer;
432432
margin-right: -3px;

ui/infra-compare/InfraCompareTable.jsx

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,13 @@ export default class InfraCompareTable extends React.PureComponent {
7171
</tr>
7272
</thead>
7373
{data.map((suiteResults) => (
74-
<tbody>
74+
<tbody
75+
key={getHashBasedId(
76+
suiteResults.suite,
77+
hashFunction,
78+
suiteResults.platform,
79+
)}
80+
>
7581
<InfraCompareTableRow
7682
hashkey={getHashBasedId(
7783
suiteResults.suite,

ui/infra-compare/InfraCompareTableControls.jsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ export default class CompareTableControls extends React.Component {
132132
{results.size > 0 ? (
133133
Array.from(results).map(([platform, data]) => (
134134
<InfraCompareTable
135+
key={platform}
135136
platform={platform}
136137
data={data}
137138
{...this.props}

ui/perfherder/alerts/AlertHeader.jsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,7 @@ const AlertHeader = ({
231231
Duplicated summaries:
232232
{alertSummary.duplicated_summaries_ids.map((id, index) => (
233233
<Link
234+
key={id}
234235
className="text-dark me-1"
235236
target="_blank"
236237
to={`./alerts?id=${id}&hideDwnToInv=0`}

ui/perfherder/graphs/GraphsContainer.jsx

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -322,8 +322,6 @@ class GraphsContainer extends React.Component {
322322
changelogData = [],
323323
showTable,
324324
zoom = {},
325-
selectedDataPoint,
326-
highlightAlerts = true,
327325
highlightedRevisions = ['', ''],
328326
highlightChangelogData,
329327
highlightCommonAlerts,

ui/shared/AdditionalInformationTable.jsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ const AdditionalInformationTable = function AdditionalInformationTable() {
162162

163163
<tbody>
164164
{alertViewHoverableItems.map((item) => (
165-
<tr>
165+
<tr key={item.name}>
166166
<td>
167167
<span>{item.name}</span>
168168
</td>
@@ -180,7 +180,7 @@ const AdditionalInformationTable = function AdditionalInformationTable() {
180180

181181
<tbody>
182182
{compareViewHoverableItems.map((item) => (
183-
<tr>
183+
<tr key={item.name}>
184184
<td>
185185
<span>{item.name}</span>
186186
</td>

ui/taskcluster-auth-callback/TaskclusterCallback.jsx

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,13 @@ export default class TaskclusterCallback extends React.PureComponent {
2525
if (code && requestState && requestState === state) {
2626
this.getCredentials(code);
2727
} else {
28-
if (error)
29-
// eslint-disable-next-line no-import-assign
30-
errorMessage += `We received error: ${error} from Taskcluster.`;
28+
let message = errorMessage;
29+
if (error) {
30+
message += `We received error: ${error} from Taskcluster.`;
31+
}
3132

3233
this.setState({
33-
errorMessage,
34+
errorMessage: message,
3435
});
3536
}
3637
}

0 commit comments

Comments
 (0)