Skip to content

fix: resolve lint warnings (batch approach)#12478

Draft
pedrobonamin wants to merge 7 commits intomainfrom
fix-lint-warnings
Draft

fix: resolve lint warnings (batch approach)#12478
pedrobonamin wants to merge 7 commits intomainfrom
fix-lint-warnings

Conversation

@pedrobonamin
Copy link
Copy Markdown
Contributor

@pedrobonamin pedrobonamin commented Mar 20, 2026

Summary

This PR systematically fixes ESLint lint warnings across the monorepo.

Result: 330 → 18 warnings (312 fixed, 95% reduction, 0 errors)


Batch 1: no-empty-function (45 warnings → 0) ✅

  • Added // eslint-disable-next-line no-empty-function to suppress warnings on intentionally empty function bodies across 33 files
  • No functional changes

Batch 2: render-result-naming-convention + no-param-reassign (37 warnings → 0) ✅

  • Renamed render result variables to view per testing-library convention across 12 files
    • result, rendered, value, html, component, retview
  • Replaced parameter reassignment with local variables in 3 files
    • resolveDeep.test.ts: depth param → currentDepth local
    • panels/util.ts: delta param → effectiveDelta local
    • useMainDocument.ts: route param → currentRoute local
  • No functional changes

Batch 3: testing-library/no-node-access (211 warnings → 0) ✅

  • Replaced direct DOM access with testing-library queries across 23+ test files
    • container.querySelector()screen.getByRole/getByTestId/getByText
    • .closest("button")screen.getByRole("button", { name })
    • document.querySelector()screen.getByTestId/getByRole
    • document.activeElement checks → toHaveFocus() matcher
    • .firstChild/.children/.parentNodewithin().getBy* queries
  • Added eslint-disable for legitimate cases (hidden file inputs, SVGs, false positives)
  • No functional changes

Batch 4: Remaining testing-library rules (6 warnings → 0) ✅

  • prefer-query-by-disappearance: use queryBy* instead of getBy* in waitForElementToBeRemoved() (4 warnings)
  • no-render-in-lifecycle: move render() from beforeEach into individual tests (1 warning)
  • no-container: eslint-disable for SVG with no accessible role (1 warning)
  • No functional changes

Remaining 18 warnings (not fixable in this PR)

complexity — 9 warnings

Functions exceeding max cyclomatic complexity of 30. Would require significant logic refactoring with risk of introducing bugs.

File Function Complexity
src/core/field/types/image/diff/ImageFieldDiff.tsx arrow function (L23) 34
src/core/form/inputs/PortableText/hooks/useTrackFocusPath.tsx arrow function (L29) 35
src/core/form/inputs/ReferenceInput/ReferenceInputPreview.tsx ReferenceInputPreview 36
src/core/form/inputs/ReferenceInput/ReferenceItem.tsx ReferenceItem 66
src/core/form/inputs/arrays/ArrayOfObjectsInput/Grid/GridItem.tsx GridItem 33
src/core/form/inputs/arrays/ArrayOfObjectsInput/List/PreviewItem.tsx PreviewItem 34
src/core/releases/tool/overview/ReleasesOverview.tsx ReleasesOverview 41
src/core/studio/components/navbar/search/contexts/search/reducer.ts searchReducer 33
src/structure/documentActions/PublishAction.tsx arrow function (L211) 35

react-hooks/incompatible-library — 7 warnings

TanStack Table / virtualization libraries return functions that can't be memoized safely by React Compiler. Not fixable in userland.

File Line
src/core/components/commandList/CommandList.tsx 154
src/core/form/inputs/arrays/.../VirtualizedArrayList.tsx 191
src/core/releases/tool/components/Table/Table.tsx 107
src/core/releases/tool/detail/ReleaseActivityList.tsx 80
src/core/scheduled-publishing/tool/schedules/VirtualList.tsx 95
src/structure/panes/documentList/sheetList/DocumentSheetListPane.tsx 66
src/structure/panes/documentList/sheetList/__tests__/ColumnsControl.test.tsx 25

react-hooks/todo — 2 warnings

React compiler doesn't yet support UpdateExpression on globals (syncRenders++). Awaiting compiler support.

File Lines
src/core/util/__tests__/createHookFromObservableFactory.test.tsx 106, 111

class-methods-use-this — 1 warning

Base class validate() method that throws "must be implemented by extending class". Using this would be incorrect here — it's an intentional design pattern.

File Line
packages/@sanity/schema/src/legacy/Rule.ts 355

@pedrobonamin pedrobonamin requested a review from a team as a code owner March 20, 2026 14:35
@pedrobonamin pedrobonamin requested review from RitaDias and removed request for a team March 20, 2026 14:35
@vercel
Copy link
Copy Markdown

vercel bot commented Mar 20, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
e2e-studio Building Building Preview, Comment Mar 24, 2026 9:03am
page-building-studio Ready Ready Preview, Comment Mar 24, 2026 9:03am
test-studio Ready Ready Preview, Comment Mar 24, 2026 9:03am

Request Review

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Mar 20, 2026

📦 Bundle Stats — sanity

Compared against main (9e36cda2) · v5.17.1 (npm)

Metric Value vs main (9e36cda) vs v5.17.1
Internal (raw) 4.37 MB +95 B, +0.0% -33.0 KB, -0.7%
Internal (gzip) 1.00 MB +17 B, +0.0% -8.8 KB, -0.9%
Bundled (raw) 12.04 MB +191 B, +0.0% -69.6 KB, -0.6%
Bundled (gzip) 2.71 MB +22 B, +0.0% -15.6 KB, -0.6%
Import time 1.61s +18ms, +1.1% +97ms, +6.4%
Details
  • Import time regressions over 10% are flagged with ⚠️
  • Treemap artifacts are attached to the CI run for detailed size analysis
  • Sizes shown as raw / gzip 🗜️. Internal bytes = own code only. Total bytes = with all dependencies. Import time = Node.js cold-start median.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Mar 20, 2026

🧪 E2E Preview environment

🔑 Environment Variables for Local Testing

This is the preview URL for the E2E tests: https://e2e-studio-oh7au1f0n.sanity.dev

To run the E2E tests locally, you can use the following environment variables, then run pnpm test:e2e --ui to open the Playwright test runner.

💬 Remember to build the project first with pnpm build:e2e.

  SANITY_E2E_PROJECT_ID=ittbm412
  SANITY_E2E_BASE_URL=https://e2e-studio-oh7au1f0n.sanity.dev
  SANITY_E2E_DATASET="update depending the project you want to test (pr-12478-chromium-23481263773 || pr-12478-firefox-23481263773 )"
  SANITY_E2E_DATASET_CHROMIUM=pr-12478-chromium-23481263773
  SANITY_E2E_DATASET_FIREFOX=pr-12478-firefox-23481263773

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Mar 20, 2026

📊 Playwright Test Report

Download Full E2E Report

This report contains test results, including videos of failing tests.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Mar 20, 2026

📚 TypeDoc Generation Result

TypeDoc generated successfully!

  • File size: 8.1M
  • Total exports: 1057
  • Artifact: sanity-typedoc-9d6dfa6e52fb138c3f8e9ba91703e4c8c9fcb72c

The TypeDoc JSON file has been generated and validated. All documentation scripts completed successfully.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Mar 20, 2026

⚡️ Editor Performance Report

Updated Tue, 24 Mar 2026 09:10:44 GMT

Benchmark reference
latency of sanity@latest
experiment
latency of this branch
Δ (%)
latency difference
arrayI18n (simple-en) 55.6 efps (18ms) 55.6 efps (18ms) +0ms (-/-%)
article (title) 43.5 efps (23ms) 47.6 efps (21ms) -2ms (-8.7%)
article (body) 44.1 efps (23ms) 42.0 efps (24ms) +1ms (+4.8%)
article (string inside object) 47.6 efps (21ms) 45.5 efps (22ms) +1ms (+4.8%)
article (string inside array) 45.5 efps (22ms) 44.4 efps (23ms) +1ms (+2.3%)
recipe (name) 99.9+ efps (10ms) 99.9+ efps (10ms) +0ms (-/-%)
recipe (description) 50.0 efps (20ms) 52.6 efps (19ms) -1ms (-5.0%)
recipe (instructions) 99.9+ efps (6ms) 99.9+ efps (8ms) +2ms (-/-%)
singleString (stringField) 99.9+ efps (7ms) 99.9+ efps (7ms) -1ms (-/-%)
synthetic (title) 62.5 efps (16ms) 62.5 efps (16ms) +0ms (-/-%)
synthetic (string inside object) 54.1 efps (19ms) 58.8 efps (17ms) -2ms (-8.1%)

efps — editor "frames per second". The number of updates assumed to be possible within a second.

Derived from input latency. efps = 1000 / input_latency

Detailed information

🏠 Reference result

The performance result of sanity@latest

Benchmark latency p75 p90 p99 blocking time test duration
arrayI18n (simple-en) 18ms 22ms 28ms 52ms 14ms 6.2s
article (title) 23ms 28ms 32ms 52ms 22ms 7.3s
article (body) 23ms 38ms 73ms 110ms 225ms 5.7s
article (string inside object) 21ms 30ms 42ms 61ms 0ms 6.2s
article (string inside array) 22ms 30ms 45ms 60ms 0ms 6.8s
recipe (name) 10ms 12ms 15ms 34ms 0ms 5.2s
recipe (description) 20ms 26ms 32ms 51ms 16ms 4.5s
recipe (instructions) 6ms 9ms 12ms 30ms 0ms 3.2s
singleString (stringField) 7ms 10ms 14ms 24ms 0ms 4.5s
synthetic (title) 16ms 18ms 20ms 78ms 971ms 8.9s
synthetic (string inside object) 19ms 20ms 70ms 109ms 1061ms 9.0s

🧪 Experiment result

The performance result of this branch

Benchmark latency p75 p90 p99 blocking time test duration
arrayI18n (simple-en) 18ms 22ms 31ms 49ms 0ms 6.0s
article (title) 21ms 25ms 33ms 56ms 49ms 7.4s
article (body) 24ms 37ms 59ms 121ms 273ms 5.6s
article (string inside object) 22ms 27ms 46ms 64ms 2ms 6.4s
article (string inside array) 23ms 27ms 41ms 56ms 8ms 6.6s
recipe (name) 10ms 12ms 15ms 38ms 0ms 5.1s
recipe (description) 19ms 22ms 25ms 43ms 0ms 4.4s
recipe (instructions) 8ms 10ms 13ms 27ms 0ms 3.1s
singleString (stringField) 7ms 9ms 10ms 20ms 0ms 4.5s
synthetic (title) 16ms 18ms 22ms 85ms 1170ms 9.2s
synthetic (string inside object) 17ms 24ms 69ms 129ms 1175ms 9.1s

📚 Glossary

column definitions

  • benchmark — the name of the test, e.g. "article", followed by the label of the field being measured, e.g. "(title)".
  • latency — the time between when a key was pressed and when it was rendered. derived from a set of samples. the median (p50) is shown to show the most common latency.
  • p75 — the 75th percentile of the input latency in the test run. 75% of the sampled inputs in this benchmark were processed faster than this value. this provides insight into the upper range of typical performance.
  • p90 — the 90th percentile of the input latency in the test run. 90% of the sampled inputs were faster than this. this metric helps identify slower interactions that occurred less frequently during the benchmark.
  • p99 — the 99th percentile of the input latency in the test run. only 1% of sampled inputs were slower than this. this represents the worst-case scenarios encountered during the benchmark, useful for identifying potential performance outliers.
  • blocking time — the total time during which the main thread was blocked, preventing user input and UI updates. this metric helps identify performance bottlenecks that may cause the interface to feel unresponsive.
  • test duration — how long the test run took to complete.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Mar 20, 2026

Coverage Report

Status Category Percentage Covered / Total
🔵 Lines 39.65% 25972 / 65502
🔵 Statements 32.2% 33828 / 105044
🔵 Functions 28.49% 5251 / 18427
🔵 Branches 24.68% 20648 / 83652
File Coverage
File Stmts Branches Functions Lines Uncovered Lines
Changed Files
packages/sanity/src/_singletons/context/FullscreenPTEContext.ts 33.33% 100% 0% 33.33% 11-15
packages/sanity/src/_singletons/context/PackageVersionInfoContext.tsx 50% 100% 0% 50% 58
packages/sanity/src/core/canvas/actions/LinkToCanvas/useLinkToCanvas.ts 3.17% 0% 0% 5.97% 67-218
packages/sanity/src/core/releases/tool/detail/events/getReleaseEvents.ts 8.57% 0% 0% 9.37% 63-138, 143-157
packages/sanity/src/core/studio/packageVersionStatus/PackageVersionStatusProvider.tsx 10.61% 0% 0% 16.92% 43, 47, 54-103, 55-173
packages/sanity/src/core/studio/screens/RequestAccessScreen.tsx 0.52% 0% 0% 1.03% 34-242
packages/sanity/src/core/studio/studioAnnouncements/useStudioAnnouncements.tsx 75% 50% 66.66% 85.71% 16, 9-17, 19
packages/sanity/src/presentation/useMainDocument.ts 16.96% 8.04% 6.66% 25.35% 20-56, 96-188
packages/sanity/src/presentation/panels/util.ts 0% 0% 0% 0% 11-203
packages/sanity/src/structure/panes/document/documentPanel/header/perspective/DocumentPerspectiveList.tsx 44.4% 35.79% 25.8% 65.95% 43-83, 108, 110, 115, 122-130, 134-165, 170, 198-202, 213-215, 218, 236, 245, 267, 270, 280-281, 287, 287, 303, 306, 308, 319, 320, 354-365, 372-407, 432-452, 462, 463, 44-115, 117-449
Generated in workflow #53795 for commit d7934b9 by the Vitest Coverage Report Action

}

const result = render(
const view = render(
Copy link
Copy Markdown
Contributor Author

@pedrobonamin pedrobonamin Mar 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixes:
result is not a recommended name for render returned value. Instead, you should destructure it, or name it using one of: view, or utilseslinttesting-library/render-result-naming-convention

{
getFullscreenPath: () => undefined,
setFullscreenPath: () => {},
setFullscreenPath: () => { /* intentionally empty */ },
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixes

Unexpected empty arrow function.eslintno-empty-function

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if it would be preferrable in these cases to simply add a lint ignore? 🤔

Miriad and others added 3 commits March 24, 2026 09:00
Add `/* intentionally empty */` comments to 45 empty function bodies
across 33 files to satisfy the no-empty-function ESLint rule.

No functional changes.

Co-authored-by: luke <luke@miriad.systems>
…nt warnings

- Rename render result variables to `view` per testing-library convention
  (33 warnings across 12 files: result, rendered, value, html, component, ret → view)
- Replace parameter reassignment with local variables (4 warnings across 3 files)

No functional changes.

Co-authored-by: luke <luke@miriad.systems>
Co-authored-by: luke <luke@miriad.systems>
Miriad and others added 4 commits March 24, 2026 09:00
- StringInputBasic.test.tsx: Replace container.querySelector('input') with screen.getByRole('textbox')
- ReleaseDetail.test.tsx: Remove .closest('button') calls on publish-all-button testid
- ReleaseDocumentPreview.test.tsx: Replace container.querySelector('a') with screen.getByRole('link'), add data-testid to mock
- IntentLink.test.tsx: Replace container.querySelector('a')?.href with screen.getByRole('link') + toHaveAttribute
- StringInputPortableText.test.tsx: Replace container.querySelector with screen.getByTestId
- DialogTimeZone.test.tsx: Replace parentElement traversal with direct screen.getByRole query
- useScheduledDraftMenuActions.test.tsx: Replace .children access with within().getAllByRole('menuitem')
- ColumnsControl.test.tsx: Replace document.querySelector('[role="menu"]') with screen.getByRole('menu')
- ReleaseTypePicker.test.tsx: Replace .closest('[role="tab"]') with screen.getByRole('tab', {name})
- ReleaseDashboardFooter.test.tsx: Minor cleanup (rule not active in flat config)
- CreateReleaseDialog.test.tsx: Remove .closest('button') on submit button

Co-authored-by: luke <luke@miriad.systems>
…rnings)

Replace direct DOM access patterns with testing-library queries:
- container.querySelector() → screen.getByRole/getByTestId/getByText
- .closest('button') → screen.getByRole('button', { name })
- document.querySelector() → screen.getByTestId/getByRole
- document.activeElement checks → toHaveFocus() matcher
- .firstChild/.children/.parentNode → within().getBy* queries

Add eslint-disable for legitimate cases with no testing-library equivalent:
- Hidden file inputs (no accessible role)
- SVG elements (no accessible role)
- React class component this.props.children (false positive)
- Structural child count assertions

No functional changes — all tests preserve their original semantics.

Co-authored-by: luke <luke@miriad.systems>
- prefer-query-by-disappearance: use queryBy* instead of getBy* in
  waitForElementToBeRemoved() callbacks (4 warnings)
- no-render-in-lifecycle: move render() from beforeEach into individual
  test blocks (1 warning)
- no-container: add eslint-disable for SVG with no accessible role (1 warning)

No functional changes.

Co-authored-by: luke <luke@miriad.systems>
…ty */

Per code review feedback, replace `/* intentionally empty */` comments
inside empty function bodies with `// eslint-disable-next-line no-empty-function`
comments and collapse back to empty `() => {}` bodies.

This is cleaner — it explicitly suppresses the lint rule rather than
working around it with a placeholder comment.

Co-authored-by: luke <luke@miriad.systems>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants