Skip to content

Commit 5a4b9eb

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

File tree

11 files changed

+223
-46
lines changed

11 files changed

+223
-46
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-custom-styles.css

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
/* Bootstrap 4 will not show <a> as a link style if it has no href.
1919
This adds that style back. */
2020
.link-style {
21-
color: #337ab7;
21+
color: #337ab7 !important;
2222
cursor: pointer;
2323
}
2424

@@ -123,12 +123,12 @@
123123

124124
.dropdown-item {
125125
cursor: pointer;
126-
color: #212529;
126+
color: #212529 !important;
127127
}
128128

129129
.dropdown-item:hover,
130130
.dropdown-item:focus {
131-
color: #1e2125;
131+
color: #1e2125 !important;
132132
}
133133

134134
.form-control:focus {
@@ -164,19 +164,19 @@
164164
.icon-blue:hover,
165165
.icon-blue:focus,
166166
.icon-blue:active {
167-
color: #68aae2;
167+
color: #68aae2 !important;
168168
}
169169

170170
.icon-green:hover,
171171
.icon-green:focus,
172172
.icon-green:active {
173-
color: #0de00d;
173+
color: #0de00d !important;
174174
}
175175

176176
.icon-cyan:hover,
177177
.icon-cyan:focus,
178178
.icon-cyan:active {
179-
color: #00ffff;
179+
color: #00ffff !important;
180180
}
181181

182182
.icon-superscript {
@@ -186,7 +186,7 @@
186186
}
187187

188188
.hover-warning:hover {
189-
color: #fa4444;
189+
color: #fa4444 !important;
190190
}
191191

192192
.dim-quarter {
@@ -383,7 +383,7 @@
383383

384384
/* Darker Secondary */
385385
.text-darker-secondary {
386-
color: #53595f;
386+
color: #53595f !important;
387387
}
388388

389389
.alert-darker-secondary,
@@ -399,14 +399,14 @@
399399
.btn-darker-secondary,
400400
a.btn-darker-secondary,
401401
a.btn-darker-secondary:visited {
402-
color: #ffffff;
402+
color: #ffffff !important;
403403
background-color: #6c757d;
404404
border-color: #6c757d;
405405
}
406406

407407
.btn-darker-secondary:hover,
408408
a.btn-darker-secondary:hover {
409-
color: #ffffff;
409+
color: #ffffff !important;
410410
background-color: #5a6268;
411411
border-color: #545b62;
412412
}
@@ -444,9 +444,9 @@ a.btn-darker-secondary:hover {
444444
/* Outline Dark Button */
445445
.btn-outline-dark:hover,
446446
a.btn-outline-dark:hover {
447-
background-color: #e9ecef;
448-
border-color: #6c757d;
449-
color: #212529;
447+
background-color: #e9ecef !important;
448+
border-color: #6c757d !important;
449+
color: #212529 !important;
450450
}
451451

452452
/*

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,

0 commit comments

Comments
 (0)