package loki import ( "os" "strconv" "strings" "testing" "time" ) // TestCDPSmoke pilote un vrai Chrome de bout en bout : lancement, navigation, // snapshot d'accessibilité, click, screenshot. Coûteux et dépendant d'un // navigateur installé → ne tourne QUE si LOKI_CU_SMOKE=1. func TestCDPSmoke(t *testing.T) { if os.Getenv("LOKI_CU_SMOKE") != "1" { t.Skip("smoke test désactivé (LOKI_CU_SMOKE=1 pour l'activer)") } if chromePath() == "" { t.Skip("aucun navigateur détecté") } s, err := cdpGet() if err != nil { t.Fatalf("cdpGet: %v", err) } defer cdpShutdown() if err := s.navigate("https://example.com"); err != nil { t.Fatalf("navigate: %v", err) } snap, err := s.snapshot() if err != nil { t.Fatalf("snapshot: %v", err) } t.Logf("snapshot:\n%s", snap) if !strings.Contains(strings.ToLower(snap), "example") { t.Errorf("titre 'example' attendu dans le snapshot, absent") } if !strings.Contains(snap, "link") { t.Errorf("le lien 'More information' devrait apparaître comme [n] link") } // browser_find doit retrouver le lien par son texte. found, err := s.find("more") if err != nil { t.Fatalf("find: %v", err) } if !strings.Contains(strings.ToLower(found), "link") { t.Errorf("browser_find('more') devrait trouver le lien, got: %s", found) } // Le screenshot doit produire des octets PNG non vides. png, err := s.screenshot() if err != nil { t.Fatalf("screenshot: %v", err) } if len(png) < 100 { t.Errorf("screenshot suspicieusement petit: %d octets", len(png)) } t.Logf("screenshot: %d octets", len(png)) } // TestCDPTypeReplacesField vérifie le fix du test IONOS #4 : browser_type(ref) cible le // BON champ et REMPLACE son contenu, même avec deux champs et une valeur existante. func TestCDPTypeReplacesField(t *testing.T) { if os.Getenv("LOKI_CU_SMOKE") != "1" { t.Skip("smoke test désactivé (LOKI_CU_SMOKE=1 pour l'activer)") } if chromePath() == "" { t.Skip("aucun navigateur détecté") } s, err := cdpGet() if err != nil { t.Fatalf("cdpGet: %v", err) } defer cdpShutdown() // Deux champs texte injectés dans la page courante ; le 2e contient « ancien ». if _, err := s.eval(`document.body.innerHTML='';'ok'`); err != nil { t.Fatalf("inject: %v", err) } if _, err := s.snapshot(); err != nil { // pose les data-loki-ref t.Fatalf("snapshot: %v", err) } // Retrouve le numéro du 2e champ (celui à remplacer). val, err := s.eval(`document.querySelector('#b').getAttribute('data-loki-ref')`) if err != nil { t.Fatalf("eval ref: %v", err) } ref, _ := strconv.Atoi(strings.Trim(string(val), `"`)) if ref == 0 { t.Fatalf("pas de ref sur #b (snapshot: %s)", val) } if err := s.typeInto(ref, "nouveau"); err != nil { t.Fatalf("typeInto: %v", err) } got, _ := s.eval(`document.querySelector('#b').value`) if v := strings.Trim(string(got), `"`); v != "nouveau" { t.Errorf("champ #b = %q, attendu \"nouveau\" (remplacement raté)", v) } // Le premier champ ne doit PAS avoir été touché. got2, _ := s.eval(`document.querySelector('#a').value`) if v := strings.Trim(string(got2), `"`); v != "" { t.Errorf("champ #a = %q, attendu vide (mauvais ciblage)", v) } } // TestCDPSnapshotHygiene vérifie que le snapshot (1) masque la valeur d'un champ // mot de passe et (2) ne liste pas les conteneurs non-actionnables (un