================================================================================ RAPPORT TECHNIQUE QA — Ticket #124 (GetYourJob) "Recuperer automatiquement la photo de profil LinkedIn a la connexion" ================================================================================ Branche : feat/124-linkedin-profile-picture Commit teste : b99ff5d feat(auth): auto-fetch LinkedIn profile picture + DP initials fallback (#124) PR : #255 (base dev) Worktree QA : .worktrees/qa-124 (dedie, cree depuis origin/feat/124-linkedin-profile-picture) Date : 2026-06-15 Note : secrets/tokens/CLIENT_ID/CLIENT_SECRET volontairement absents (jamais imprimes ni joints). -------------------------------------------------------------------------------- PERIMETRE MODIFIE (git diff origin/dev...HEAD) -------------------------------------------------------------------------------- src/components/atoms/ConnectionButton.tsx | 42 +-- (avatar en-tete -> UserAvatar) src/components/atoms/UserAvatar.tsx | 82 ++ (NOUVEAU : avatar rond + fallback) src/components/atoms/__tests__/UserAvatar.test.tsx | 59 ++ (NOUVEAU : tests) src/lib/__tests__/auth-providers.test.ts | 63 ++ (NOUVEAU : tests) src/lib/auth-providers.ts | 45 ++ (NOUVEAU : mapLinkedInProfileToUser) src/lib/auth.ts | 15 +- (provider LinkedIn delegue au helper) -------------------------------------------------------------------------------- 1) SUITES VITEST TOUCHEES -------------------------------------------------------------------------------- Commande : npx vitest run src/lib/__tests__/auth-providers.test.ts \ src/components/atoms/__tests__/UserAvatar.test.tsx OK src/lib/__tests__/auth-providers.test.ts (4 tests) OK src/components/atoms/__tests__/UserAvatar.test.tsx (7 tests) Test Files : 2 passed (2) Tests : 11 passed (11) Couverture des tests : - mapLinkedInProfileToUser : claim OIDC `picture` -> `image` ; id<-sub, name, email ; defaut JOB_SEEKER/hasSelectedRole=false ; `image` null quand `picture` absent. - UserAvatar / getAvatarInitials : "Dupont Pierre"->"DP", "pierre"->"P", null/""->"DP" ; priorite manuel > provider > initiales ; rendu rond + fond colore quand aucune photo. -------------------------------------------------------------------------------- 2) TYPECHECK (tsc --noEmit) — FICHIERS TOUCHES -------------------------------------------------------------------------------- Commande : npx tsc --noEmit -p tsconfig.json (puis filtre sur les fichiers du diff) Fichiers du ticket : 0 erreur - src/lib/auth-providers.ts : clean - src/components/atoms/UserAvatar.tsx : clean - src/components/atoms/ConnectionButton.tsx : clean Une (1) erreur subsiste dans src/lib/auth.ts(46) — typage Prisma de `subscription.createMany` dans ensureDefaultSubscriptions. VERIFIE PRE-EXISTANT : ce bloc est IDENTIQUE sur origin/dev et n'est PAS touche par le diff #124 (le diff ne touche que l'import du helper et le provider LinkedIn). => hors perimetre, non bloquant pour ce ticket. (Le reste de la base affiche des erreurs tsc pre-existantes hors perimetre — non liees a #124.) -------------------------------------------------------------------------------- 3) INSPECTION SOURCE — MAPPING CRITERES D'ACCEPTATION -------------------------------------------------------------------------------- AC1 Photo LinkedIn recuperee auto a la connexion, affichee en haut a droite -> OK. auth.ts: provider LinkedIn, scope `openid profile email ...` deja demande ; profile() delegue a mapLinkedInProfileToUser() qui mappe `picture` -> `image` (auth-providers.ts l.41), comme Google. ConnectionButton.tsx (avatar en-tete, coin haut-droit) rend . AC2 Sans photo LinkedIn : icone ronde, initiales "DP", fond colore -> OK. UserAvatar.tsx l.70-81 : div rounded-full bg-sky-100 text-sky-700, initiales via getAvatarInitials (defaut "DP"). Preuve visuelle: 124-avatar-states.png. AC3 Photo manuelle GetYourJob prime toujours sur l'auto (LinkedIn/Google) -> OK. Double garantie : (a) structurel : l'image provider n'est ecrite qu'a la creation du compte (PrismaAdapter) et jamais reecrite a la reconnexion (auth.ts) ; (b) affichage : UserAvatar.tsx l.53 resolvedImageUrl = profileImageUrl || image -> l'upload manuel (DeveloperProfile.profileImageUrl) passe avant le provider. AC4 Comportement coherent avec Google (meme logique fallback + priorite) -> OK. Meme forme de retour profile() que GoogleProvider ; meme composant UserAvatar et meme chaine de priorite quel que soit le provider. AC5 Aucun message de confirmation demande a l'utilisateur -> OK. Aucun prompt/modal sur le chemin de recuperation/affichage de la photo ; mapping + rendu purement automatiques (auth-providers.ts / UserAvatar.tsx). -------------------------------------------------------------------------------- 4) PIECES JOINTES -------------------------------------------------------------------------------- - 124-rapport-technique-qa.txt (ce fichier) - 124-avatar-states.png (preuve visuelle des 3 etats : manuel / provider / "DP") -------------------------------------------------------------------------------- VERDICT : PASS (5/5 criteres OK). Ticket maintenu en QA. ================================================================================