fix: markdown double-encoding and robust date/API access

This commit is contained in:
2026-07-27 01:55:21 +04:00
parent d9da213341
commit d81dd71a46
3 changed files with 156 additions and 36 deletions
+67
View File
@@ -56,6 +56,21 @@ assertEquals(
'formatDate affiche les années au pluriel'
);
// --- formatDate : dates malformées (repli sur la chaîne brute) ---------------
assertEquals(
'pas une date',
formatDate('pas une date'),
'formatDate retourne la chaîne brute si la date est invalide'
);
assertEquals(
'2024-13-45T99:99:99Z',
formatDate('2024-13-45T99:99:99Z'),
'formatDate retourne une date ISO malformée telle quelle'
);
assertEquals('', formatDate(''), 'formatDate retourne une chaîne vide telle quelle');
assertEquals(' ', formatDate(' '), 'formatDate retourne une chaîne blanche telle quelle');
// --- formatVideosData -------------------------------------------------------
$rawVideos = [
@@ -125,6 +140,58 @@ assertEquals('', $videos[1]['description'], 'formatVideosData met une descriptio
assertEquals([], $videos[1]['tags'], 'formatVideosData met des tags vides par défaut');
assertFalse($videos[1]['isLive'], 'formatVideosData met isLive à false par défaut');
// --- formatVideosData : données API incomplètes -------------------------------
$incompleteVideos = formatVideosData([
[
// Sans uuid : doit être ignorée
'name' => 'Sans uuid',
'duration' => 10,
],
[
// uuid vide : doit être ignorée aussi
'uuid' => '',
'name' => 'Uuid vide',
],
[
// uuid seul : valeurs par défaut partout ailleurs
'uuid' => 'ghi-789',
],
[
// channel présent mais sans displayName ni avatars
'uuid' => 'jkl-012',
'channel' => ['name' => 'compte'],
],
]);
assertEquals(2, count($incompleteVideos), 'formatVideosData ignore les entrées sans uuid');
assertEquals('ghi-789', $incompleteVideos[0]['id'], 'formatVideosData conserve l\'uuid seul');
assertEquals('', $incompleteVideos[0]['title'], 'formatVideosData met un titre vide par défaut');
assertEquals(0, $incompleteVideos[0]['duration'], 'formatVideosData met une durée à 0 par défaut');
assertEquals('', $incompleteVideos[0]['channel'], 'formatVideosData met une chaîne vide par défaut');
assertEquals(0, $incompleteVideos[0]['views'], 'formatVideosData met les vues à 0 par défaut');
assertEquals('', $incompleteVideos[0]['date'], 'formatVideosData met une date vide par défaut');
assertNull($incompleteVideos[0]['aspectRatio'], 'formatVideosData met aspectRatio à null par défaut');
assertFalse($incompleteVideos[0]['isLive'], 'formatVideosData met isLive à false par défaut');
assertEquals(
'img/default-thumbnail.jpg',
$incompleteVideos[0]['thumbnail'],
'formatVideosData met la vignette par défaut pour une entrée minimale'
);
assertEquals(
'img/default-avatar.png',
$incompleteVideos[0]['channelAvatar'],
'formatVideosData met l\'avatar par défaut pour une entrée minimale'
);
assertEquals('', $incompleteVideos[1]['channel'], 'formatVideosData met une chaîne vide si displayName absent');
assertEquals(
'img/default-avatar.png',
$incompleteVideos[1]['channelAvatar'],
'formatVideosData met l\'avatar par défaut si le tableau avatars est absent'
);
// --- truncateText (includes/structured-data.php) ----------------------------
assertEquals('court', truncateText('court', 200), 'truncateText laisse un texte court intact');
+34 -11
View File
@@ -1,9 +1,6 @@
<?php
/**
* Tests unitaires pour markdown_to_html (includes/lib/markdown.php)
*
* Les sorties attendues reflètent le comportement actuel de la fonction,
* y compris ses particularités (voir la note sur les listes à puces).
*/
// --- Échappement XSS ---------------------------------------------------------
@@ -63,21 +60,47 @@ assertEquals(
'markdown_to_html ne transforme pas un numéro de version en lien'
);
// --- Listes ------------------------------------------------------------------
// --- URLs contenant « & » : pas de double encodage ---------------------------
// Note : la passe des listes numérotées s'applique aussi aux <li> déjà
// produits par la passe des puces, d'où un double enveloppement <ul><ol>.
// C'est le comportement actuel, verrouillé ici contre toute régression.
// Le texte est échappé une seule fois : « & » devient « &amp; », jamais « &amp;amp; »
assertEquals(
"<ul><ol><li>a</li>\n<li>b</li></ol></ul>",
markdown_to_html("- a\n- b"),
'markdown_to_html convertit les listes à puces (double enveloppement actuel)'
'Voir <a href="https://exemple.com/page?a=1&amp;b=2" target="_blank" rel="noopener noreferrer">https://exemple.com/page?a=1&amp;b=2</a> suite',
markdown_to_html('Voir https://exemple.com/page?a=1&b=2 suite'),
'markdown_to_html n\'encode pas deux fois le & des URLs brutes'
);
assertEquals(
"<ol><li>a</li>\n<li>b</li></ol>",
'<a href="https://exemple.com/?x=1&amp;y=2" target="_blank" rel="noopener noreferrer">lien</a>',
markdown_to_html('[lien](https://exemple.com/?x=1&y=2)'),
'markdown_to_html n\'encode pas deux fois le & des liens Markdown'
);
assertNotContains(
'&amp;amp;',
markdown_to_html('https://exemple.com/page?a=1&b=2'),
'markdown_to_html ne produit jamais de &amp;amp;'
);
// --- Listes ------------------------------------------------------------------
assertEquals(
"<ul>\n<li>a</li>\n<li>b</li>\n</ul>",
markdown_to_html("- a\n- b"),
'markdown_to_html convertit les listes à puces en <ul> uniquement'
);
assertEquals(
"<ol>\n<li>a</li>\n<li>b</li>\n</ol>",
markdown_to_html("1. a\n2. b"),
'markdown_to_html convertit les listes numérotées en <ol>'
);
assertEquals(
"<ul>\n<li>a</li>\n</ul><br />\n<ol>\n<li>b</li>\n</ol><br />\n<ul>\n<li>c</li>\n</ul>",
markdown_to_html("- a\n1. b\n- c"),
'markdown_to_html sépare les listes de types différents'
);
assertEquals(
"<ul>\n<li>a</li>\n</ul><br />\ntexte",
markdown_to_html("- a\ntexte"),
'markdown_to_html ferme la liste avant le texte qui suit'
);
// --- Retours à la ligne ------------------------------------------------------