-
-
Notifications
You must be signed in to change notification settings - Fork 213
fix: resolve all eslint errors in utility and test files (#725) #725
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
84fb586
7f7be9c
c132043
ee38022
ea6b867
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -2,22 +2,33 @@ import { describe, it, expect, vi, beforeEach } from 'vitest'; | |||||
| import { render, screen } from '@testing-library/react'; | ||||||
| import SettingsModal from '../../components/SettingsModal'; | ||||||
|
|
||||||
| // Mock the store - use inline functions to avoid hoisting issues | ||||||
| interface StoreState { | ||||||
| isSettingsOpen: boolean; | ||||||
| setSettingsOpen: (value: boolean) => void; | ||||||
| showLineNumbers: boolean; | ||||||
| setShowLineNumbers: (value: boolean) => void; | ||||||
| textColor: string; | ||||||
| backgroundColor: string; | ||||||
| toggleDarkMode: () => void; | ||||||
| } | ||||||
|
Comment on lines
+5
to
+13
|
||||||
|
|
||||||
| // Update the mock | ||||||
|
||||||
| // Update the mock | |
| // Mock the Zustand store selector with a fixed settings state so SettingsModal can be tested in isolation |
| Original file line number | Diff line number | Diff line change | ||
|---|---|---|---|---|
| @@ -1,23 +1,33 @@ | ||||
| // Helper function to extract meaningful error message from complex error objects | ||||
| interface NestedError { | ||||
| error?: { | ||||
| message?: string; | ||||
| }; | ||||
| } | ||||
|
|
||||
| interface CommonErrorStructure { | ||||
| error?: string | { | ||||
| message?: string; | ||||
| }; | ||||
| detail?: string; | ||||
| message?: string; | ||||
| } | ||||
|
|
||||
| export const extractErrorMessage = (error: Error | unknown): string => { | ||||
| if (!error) return 'An unknown error occurred'; | ||||
|
|
||||
| let errorMessage = error instanceof Error ? error.message : String(error); | ||||
| const errorMessage = error instanceof Error ? error.message : String(error); | ||||
|
|
||||
| // Try to extract JSON from the message (might be prefixed with error type/code) | ||||
| let jsonMatch = errorMessage.match(/\{.*\}/s); | ||||
| const jsonMatch = errorMessage.match(/\{.*\}/s); | ||||
| if (jsonMatch) { | ||||
| try { | ||||
| const parsed = JSON.parse(jsonMatch[0]); | ||||
| const parsed = JSON.parse(jsonMatch[0]) as CommonErrorStructure; | ||||
|
|
||||
| // Handle Google error structure: {"error":{"message":"..."}} | ||||
| if (parsed.error) { | ||||
| if (typeof parsed.error === 'object') { | ||||
| // Handle nested error with message | ||||
| if (parsed.error.message) { | ||||
| if (typeof parsed.error.message === 'string') { | ||||
| try { | ||||
| const inner = JSON.parse(parsed.error.message); | ||||
| const inner = JSON.parse(parsed.error.message) as NestedError; | ||||
| if (inner?.error?.message) { | ||||
| return inner.error.message; | ||||
| } | ||||
|
|
@@ -26,63 +36,56 @@ export const extractErrorMessage = (error: Error | unknown): string => { | |||
| } | ||||
| } | ||||
| } | ||||
| } else if (typeof parsed.error === 'string') { | ||||
|
|
||||
|
Comment on lines
+39
to
+40
|
||||
| } else if (typeof parsed.error === 'string') { |
| Original file line number | Diff line number | Diff line change | ||
|---|---|---|---|---|
|
|
@@ -8,13 +8,9 @@ afterEach(() => { | |||
| cleanup(); | ||||
| }); | ||||
|
|
||||
| // Mock getComputedStyle for Ant Design components that use scroll locking | ||||
| // jsdom doesn't fully support getComputedStyle with pseudo-elements | ||||
| // rc-util's getScrollBarSize calls .match() on style properties | ||||
| const originalGetComputedStyle = window.getComputedStyle; | ||||
| window.getComputedStyle = (elt: Element, pseudoElt?: string | null) => { | ||||
| if (pseudoElt) { | ||||
| // Return a mock CSSStyleDeclaration with string properties for .match() calls | ||||
| return { | ||||
| width: '0px', | ||||
| height: '0px', | ||||
|
|
@@ -30,62 +26,87 @@ Object.defineProperty(window, "matchMedia", { | |||
| matches: false, | ||||
| media: query, | ||||
| onchange: null, | ||||
| addListener: () => { | ||||
| // Mock implementation for tests | ||||
| }, | ||||
| removeListener: () => { | ||||
| // Mock implementation for tests | ||||
| }, | ||||
| addEventListener: () => { | ||||
| // Mock implementation for tests | ||||
| }, | ||||
| removeEventListener: () => { | ||||
| // Mock implementation for tests | ||||
| }, | ||||
| dispatchEvent: () => { | ||||
| return false; | ||||
| }, | ||||
| addListener: () => { /* mock */ }, | ||||
| removeListener: () => { /* mock */ }, | ||||
| addEventListener: () => { /* mock */ }, | ||||
| removeEventListener: () => { /* mock */ }, | ||||
| dispatchEvent: () => { return false; }, | ||||
| }), | ||||
| }); | ||||
|
|
||||
| // Mock HTMLCanvasElement.getContext for lottie-web library | ||||
| // jsdom doesn't implement canvas 2D context | ||||
| // @ts-expect-error: Mock implementation has simplified types | ||||
| HTMLCanvasElement.prototype.getContext = ((originalGetContext) => { | ||||
| return function ( | ||||
| this: HTMLCanvasElement, | ||||
| contextId: string, | ||||
| options?: unknown | ||||
| ) { | ||||
| if (contextId === '2d') { | ||||
| return { | ||||
| fillStyle: '', | ||||
| fillRect: () => {}, | ||||
| clearRect: () => {}, | ||||
| getImageData: () => ({ data: [] }), | ||||
| putImageData: () => {}, | ||||
| createImageData: () => ({ data: [] }), | ||||
| setTransform: () => {}, | ||||
| drawImage: () => {}, | ||||
| save: () => {}, | ||||
| restore: () => {}, | ||||
| beginPath: () => {}, | ||||
| moveTo: () => {}, | ||||
| lineTo: () => {}, | ||||
| closePath: () => {}, | ||||
| stroke: () => {}, | ||||
| fill: () => {}, | ||||
| translate: () => {}, | ||||
| scale: () => {}, | ||||
| rotate: () => {}, | ||||
| arc: () => {}, | ||||
| measureText: () => ({ width: 0 }), | ||||
| transform: () => {}, | ||||
| rect: () => {}, | ||||
| clip: () => {}, | ||||
| canvas: this, | ||||
| } as unknown as CanvasRenderingContext2D; | ||||
| } | ||||
| return originalGetContext.call(this, contextId as any, options); | ||||
| }; | ||||
| })(HTMLCanvasElement.prototype.getContext); | ||||
| interface MockCanvasContext { | ||||
| fillStyle: string; | ||||
| fillRect: () => void; | ||||
| clearRect: () => void; | ||||
| getImageData: () => { data: number[] }; | ||||
| putImageData: () => void; | ||||
| createImageData: () => { data: number[] }; | ||||
| setTransform: () => void; | ||||
| drawImage: () => void; | ||||
| save: () => void; | ||||
| restore: () => void; | ||||
| beginPath: () => void; | ||||
| moveTo: () => void; | ||||
| lineTo: () => void; | ||||
| closePath: () => void; | ||||
| stroke: () => void; | ||||
| fill: () => void; | ||||
| translate: () => void; | ||||
| scale: () => void; | ||||
| rotate: () => void; | ||||
| arc: () => void; | ||||
| measureText: () => { width: number }; | ||||
| transform: () => void; | ||||
| rect: () => void; | ||||
| clip: () => void; | ||||
| canvas: HTMLCanvasElement; | ||||
| } | ||||
|
|
||||
| // capture original method so we can delegate for non-2d calls | ||||
|
||||
| const originalGetContext = HTMLCanvasElement.prototype.getContext as ( | ||||
| this: HTMLCanvasElement, | ||||
| contextId: string, | ||||
| options?: unknown | ||||
| ) => RenderingContext | null; | ||||
|
|
||||
| HTMLCanvasElement.prototype.getContext = function ( | ||||
| this: HTMLCanvasElement, | ||||
| contextId: string, | ||||
| options?: unknown | ||||
| ) { | ||||
| if (contextId === '2d') { | ||||
| const mockContext: MockCanvasContext = { | ||||
| fillStyle: '', | ||||
| fillRect: () => { /* mock */ }, | ||||
| clearRect: () => { /* mock */ }, | ||||
| getImageData: () => ({ data: [] }), | ||||
| putImageData: () => { /* mock */ }, | ||||
| createImageData: () => ({ data: [] }), | ||||
| setTransform: () => { /* mock */ }, | ||||
| drawImage: () => { /* mock */ }, | ||||
| save: () => { /* mock */ }, | ||||
| restore: () => { /* mock */ }, | ||||
| beginPath: () => { /* mock */ }, | ||||
| moveTo: () => { /* mock */ }, | ||||
| lineTo: () => { /* mock */ }, | ||||
| closePath: () => { /* mock */ }, | ||||
| stroke: () => { /* mock */ }, | ||||
| fill: () => { /* mock */ }, | ||||
| translate: () => { /* mock */ }, | ||||
| scale: () => { /* mock */ }, | ||||
| rotate: () => { /* mock */ }, | ||||
| arc: () => { /* mock */ }, | ||||
| measureText: () => ({ width: 0 }), | ||||
| transform: () => { /* mock */ }, | ||||
| rect: () => { /* mock */ }, | ||||
| clip: () => { /* mock */ }, | ||||
| canvas: this, | ||||
| }; | ||||
| // cast through unknown since the mock only implements a subset of methods | ||||
| return mockContext as unknown as CanvasRenderingContext2D; | ||||
| } | ||||
|
|
||||
| // for other context types, delegate to original | ||||
| // for other context types, delegate to original | ||||
|
||||
| // for other context types, delegate to original |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The
eslint-disable-next-line react-refresh/only-export-componentscomment has been placed after the closing brace ofMarkdownEditorProvider(line 35), but it is followed by a blank line before the function it is intended to suppress (useMarkdownEditorContextat line 37). ESLint disable-next-line comments apply to the immediately following non-blank line, so the blank line between the comment and the function means the directive may not work as intended and could suppress a warning on the wrong line. The comment should be placed directly aboveuseMarkdownEditorContextwith no blank line in between.