fix(e2e): align CI Go version to 1.24 for v0.101

fix(web): resolve lint errors for v0.101
- eslint: add ignores (e2e, scripts, playwright-report, generated types)
- eslint: add browser globals, disable react-hooks in stories
- fix empty catch blocks (Cart, MarketplacePage, RolesPage, SettingsPage)
- fix PlayerExpanded: move useEffect before early return
- fix TrackHistory.test: rename type import to avoid no-redeclare
This commit is contained in:
senke 2026-02-19 16:27:10 +01:00
parent 4b0c266b8e
commit c0bcb711df
9 changed files with 58 additions and 26 deletions

View file

@ -212,7 +212,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: '1.23'
go-version: '1.24'
cache-dependency-path: veza-backend-api/go.sum
- name: Install dependencies

View file

@ -82,6 +82,28 @@ export default [js.configs.recommended, {
IntersectionObserverInit: 'readonly',
MessageChannel: 'readonly',
confirm: 'readonly',
alert: 'readonly',
// Web API globals
AudioContext: 'readonly',
AnalyserNode: 'readonly',
MediaElementAudioSourceNode: 'readonly',
HTMLIFrameElement: 'readonly',
HTMLMediaElement: 'readonly',
XMLHttpRequest: 'readonly',
BinaryType: 'readonly',
EventListenerOrEventListenerObject: 'readonly',
ReadableStream: 'readonly',
BeforeUnloadEvent: 'readonly',
CryptoKey: 'readonly',
btoa: 'readonly',
atob: 'readonly',
TextEncoder: 'readonly',
TextDecoder: 'readonly',
CanvasRenderingContext2D: 'readonly',
MutationObserver: 'readonly',
Window: 'readonly',
Storage: 'readonly',
TransformStream: 'readonly',
// Service Worker globals
self: 'readonly',
caches: 'readonly',
@ -241,6 +263,11 @@ export default [js.configs.recommended, {
version: 'detect',
},
},
}, {
files: ['**/*.stories.tsx', '**/*.stories.ts'],
rules: {
'react-hooks/rules-of-hooks': 'off',
},
}, {
ignores: [
'node_modules/',
@ -249,6 +276,11 @@ export default [js.configs.recommended, {
'build/',
'target/',
'storybook-static/',
'e2e/',
'playwright-report/',
'public/sw.js',
'scripts/',
'src/types/generated/',
'_archive/',
'archive/',
'*.config.js',

View file

@ -90,8 +90,8 @@ export function Cart({ isOpen, onClose }: CartProps) {
setIsCheckingOut(true);
try {
await lastMutationRef.current();
} catch (error) {
// Error will be handled by the mutation function
} catch {
void 0; // Error handled by mutation
} finally {
setIsCheckingOut(false);
}

View file

@ -121,7 +121,7 @@ export function MarketplaceHome() {
const handleRetry = async () => {
if (!lastMutationRef.current || retryCount >= 3) return;
setRetryCount((prev) => prev + 1);
try { await lastMutationRef.current(); } catch (error) { }
try { await lastMutationRef.current(); } catch { void 0; }
};
const handleClearFilters = () => {

View file

@ -26,20 +26,11 @@ export function PlayerExpanded({ isOpen, onClose, currentTime, duration, onSeek,
const [showLyrics, setShowLyrics] = useState(false);
const [autoScrollLyrics, setAutoScrollLyrics] = useState(true);
const lyricsScrollRef = useRef<HTMLDivElement>(null);
const lyrics = currentTrack?.lyrics;
if (!isOpen || !currentTrack) return null;
const lyrics = currentTrack.lyrics;
const formatTime = (seconds: number) => {
if (!seconds && seconds !== 0) return '0:00';
const m = Math.floor(seconds / 60);
const s = Math.floor(seconds % 60);
return `${m}:${s.toString().padStart(2, '0')}`;
};
// Auto-scroll lyrics to active line
// Auto-scroll lyrics to active line (must be before early return - hooks rules)
useEffect(() => {
if (!autoScrollLyrics || !lyrics?.length || !lyricsScrollRef.current) return;
if (!isOpen || !currentTrack || !autoScrollLyrics || !lyrics?.length || !lyricsScrollRef.current) return;
const activeIndex = lyrics.findIndex(
(line, i) =>
currentTime >= line.time &&
@ -49,7 +40,16 @@ export function PlayerExpanded({ isOpen, onClose, currentTime, duration, onSeek,
const el = lyricsScrollRef.current.children[activeIndex] as HTMLElement;
el?.scrollIntoView({ behavior: 'smooth', block: 'center' });
}
}, [currentTime, lyrics, autoScrollLyrics]);
}, [isOpen, currentTrack, currentTime, lyrics, autoScrollLyrics]);
if (!isOpen || !currentTrack) return null;
const formatTime = (seconds: number) => {
if (!seconds && seconds !== 0) return '0:00';
const m = Math.floor(seconds / 60);
const s = Math.floor(seconds % 60);
return `${m}:${s.toString().padStart(2, '0')}`;
};
return (
<div className={cn(

View file

@ -123,7 +123,7 @@ export function RolesPage() {
};
lastMutationRef.current = performMutation;
setMutationError(null);
try { await performMutation(); } catch (err) { setMutationError(new Error(err instanceof Error ? err.message : 'Failed to update role')); }
try { await performMutation(); } catch (err: unknown) { setMutationError(new Error(err instanceof Error ? err.message : 'Failed to update role')); }
};
const handleDeleteClick = async (role: Role) => {
@ -138,13 +138,13 @@ export function RolesPage() {
};
lastMutationRef.current = performMutation;
setMutationError(null);
try { await performMutation(); } catch (err) { setMutationError(new Error(err instanceof Error ? err.message : 'Failed to delete role')); }
try { await performMutation(); } catch (err: unknown) { setMutationError(new Error(err instanceof Error ? err.message : 'Failed to delete role')); }
};
const handleRetry = async () => {
if (!lastMutationRef.current || retryCount >= 3) return;
setRetryCount((prev) => prev + 1);
try { await lastMutationRef.current(); } catch (error) { }
try { await lastMutationRef.current(); } catch { void 0; /* handled by mutation */ }
};
if (isLoading) return <RolesPageSkeleton />;

View file

@ -129,7 +129,7 @@ export function SettingsPage() {
if (!lastMutationRef.current || retryCount >= 3) return;
setRetryCount(prev => prev + 1);
setIsSaving(true);
try { await lastMutationRef.current(); } catch (error) { } finally { setIsSaving(false); }
try { await lastMutationRef.current(); } catch { void 0; } finally { setIsSaving(false); }
};
if (isLoading) return <SettingsPageSkeleton />;

View file

@ -5,7 +5,7 @@ import {
getTrackHistory,
TrackHistoryError,
} from '@/features/tracks/services/trackHistoryService';
import type { TrackHistory } from '@/features/tracks/services/trackHistoryService';
import type { TrackHistory as TrackHistoryType } from '@/features/tracks/services/trackHistoryService';
import { useToast } from '@/hooks/useToast';
// Mock services (path must match hook: track-history/useTrackHistory imports ../../services/trackHistoryService)
@ -36,7 +36,7 @@ describe('TrackHistory', () => {
vi.mocked(useToast).mockReturnValue(mockToast);
});
const mockHistoryItems: TrackHistory[] = [
const mockHistoryItems: TrackHistoryType[] = [
{
id: 1,
track_id: 123,

View file

@ -100,14 +100,14 @@ Ces routes affichent un placeholder "Coming Soon". **Ne pas développer** pour v
### 5.2 Tests
- [ ] `go test ./...` (backend) — 0 échec
- [ ] `npm test -- --run` (frontend) — 0 échec
- [x] `go test ./...` (backend) — 0 échec
- [x] `npm test -- --run` (frontend) — 0 échec
- [ ] `npm run test:storybook` — 0 erreur console/réseau
- [ ] E2E auth, smoke, playlists, search — 0 échec
### 5.3 Qualité
- [ ] `npm run lint` — 0 erreur
- [x] `npm run lint` — 0 erreur
- [ ] Aucune régression sur les flows critiques (auth, upload, playlists, player, streaming audio)
- [ ] Pas de `console.log` en production
- [ ] Pas de TODO/FIXME critiques dans le code modifié