From 4cbf5affc5643f53ab78b3a8829c77e3d8106ce3 Mon Sep 17 00:00:00 2001
From: Matthieu Marcillaud <marcimat@rezo.net>
Date: Mon, 10 Jul 2023 10:25:07 +0200
Subject: [PATCH] tests: tests liens en PHPUnit

---
 ecrire/tests/Texte/LiensTest.php              | 206 ++++++++++++++++++
 ecrire/tests/legacy/unit/propre/liens.php     | 198 -----------------
 .../legacy/unit/propre/liens_classes.php      |  75 -------
 3 files changed, 206 insertions(+), 273 deletions(-)
 create mode 100644 ecrire/tests/Texte/LiensTest.php
 delete mode 100644 ecrire/tests/legacy/unit/propre/liens.php
 delete mode 100644 ecrire/tests/legacy/unit/propre/liens_classes.php

diff --git a/ecrire/tests/Texte/LiensTest.php b/ecrire/tests/Texte/LiensTest.php
new file mode 100644
index 0000000000..fc81af9e08
--- /dev/null
+++ b/ecrire/tests/Texte/LiensTest.php
@@ -0,0 +1,206 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * Test unitaire de la fonction interdire_script du fichier inc/texte.php
+ */
+
+namespace Spip\Test\Texte;
+
+use PHPUnit\Framework\Attributes\DataProvider;
+use PHPUnit\Framework\TestCase;
+
+class LiensTest extends TestCase
+{
+	public static function setUpBeforeClass(): void {
+		include_spip('inc/texte');
+		include_spip('inc/lang');
+	}
+
+	public function testLiensHrefLangAutomatique() {
+		$article = sql_fetsel(
+			['id_article', 'lang'],
+			'spip_articles',
+			[
+				'statut = ' . sql_quote('publie'),
+				'lang != ' . sql_quote('')
+			],
+			limit: '0,1',
+		);
+
+		$id_article = $article['id_article'];
+		$lang = $article['lang'];
+
+		// on se met dans une autre langue que celle de l'article
+		lang_select($lang === 'eo' ? 'fa' : 'eo');
+
+		$case = '[->' . $id_article . ']';
+		$propre = propre($case);
+		$this->assertEquals(
+			$lang,
+			extraire_attribut($propre, 'hreflang'),
+			sprintf('hreflang automatique errone dans "%s". Propre: "%s"', $case, $propre)
+		);
+	}
+
+	#[DataProvider('providerLiensClassCss')]
+	public function testLiensClassCss(string $table, ?string $short) {
+		$id = sql_getfetsel(id_table_objet($table), $table, "statut='publie'", limit: '0,1');
+		$type = objet_type($table);
+		if (!$id) {
+			$this->markTestSkipped(sprintf('Necessite un·e %s publié', $type));
+		}
+		$cases = ["[->$type{$id}]"];
+		if ($short) {
+			$cases[] = "[->$short{$id}]";
+		}
+		foreach ($cases as $case) {
+			$propre = propre($case);
+			$classes = extraire_attribut($propre, 'class');
+			$err = sprintf('Classe CSS "%s" errone dans "%s". Propre: "%s"', (string) $classes, $case, $propre);
+			$this->assertNotNull($classes, $err);
+			$this->assertStringContainsString('spip_in', $classes, $err);
+			$this->assertStringNotContainsString('spip_out', $classes, $err);
+		}
+	}
+
+	public static function providerLiensClassCss(): array {
+		return [
+			'article' => [
+				'table' => 'spip_articles',
+				'short' => 'art',
+			],
+			'rubrique' => [
+				'table' => 'spip_rubriques',
+				'short' => 'rub',
+			],
+			'site' => [
+				'table' => 'spip_syndic',
+				'short' => null,
+			],
+		];
+	}
+
+	#[DataProvider('providerLiens')]
+	public function testLiens($case, $url, $hreflang, $title, $text) {
+		lang_select('eo');
+		$propre = propre($case);
+		$this->assertEquals(
+			$url,
+			extraire_attribut($propre, 'href'),
+			sprintf('URL mal extraite de "%s". Propre: "%s"', $case, $propre)
+		);
+		$this->assertEquals(
+			$hreflang,
+			extraire_attribut($propre, 'hreflang'),
+			sprintf('Hreflang erroné dans "%s". Propre: "%s"', $case, $propre)
+		);
+		$this->assertEquals(
+			$title,
+			extraire_attribut($propre, 'title'),
+			sprintf('Title erroné dans "%s". Propre: "%s"', $case, $propre)
+		);
+		$this->assertEquals(
+			$text,
+			supprimer_tags($propre),
+			sprintf('Texte du lien abîmé dans "%s". Propre: "%s"', $case, $propre)
+		);
+	}
+
+	public static function providerLiens(): array {
+		return [
+			'hreflang incorrect spécifié ignoré' => [
+				'case' => '[bla {blabla}->url]',
+				'url' => 'url',
+				'hreflang' => null,
+				'title' => null,
+				'text' => 'bla blabla'
+			],
+			'hreflang correct spécifié pris en compte' => [
+				'case' => '[bla{en}->url]',
+				'url' => 'url',
+				'hreflang' => 'en',
+				'title' => null,
+				'text' => 'bla'
+			],
+			'title spécifié pris en compte' => [
+				'case' => '[bla|bulle de savon{eo}->url]',
+				'url' => 'url',
+				'hreflang' => 'eo',
+				'title' => 'bulle de savon',
+				'text' => 'bla'
+			],
+			'title comme une langue devient hreflang aussi' => [
+				'case' => '[bla|fa->url]',
+				'url' => 'url',
+				'hreflang' => 'fa',
+				'title' => 'fa',
+				'text' => 'bla'
+			],
+			'title autre qu’une langue ne contamine pas hreflang' => [
+				'case' => '[bla|bulle de savon->url]',
+				'url' => 'url',
+				'hreflang' => null,
+				'title' => 'bulle de savon',
+				'text' => 'bla'
+			],
+			'multi dans liens' => [
+				'case' => '[<multi>[fr]X[eo]Y[fa]Z</multi>->url]',
+				'url' => 'url',
+				'hreflang' => null,
+				'title' => null,
+				'text' => 'Y'
+			],
+		];
+	}
+
+	#[DataProvider('providerLiensAutomatiques')]
+	public function testLiensAutomatiques($case, $url) {
+		$propre = propre($case);
+		$this->assertEquals(
+			$url,
+			extraire_attribut(extraire_balise($propre, 'a'), 'href'),
+			sprintf('Erreur lien dans "%s". Propre: "%s"', $case, $propre)
+		);
+	}
+
+	public static function providerLiensAutomatiques(): array {
+		return [
+			'sans protocole' => [
+				'case' => 'un superbe www.monsite.tld, pas mal',
+				'url' => 'http://www.monsite.tld',
+			],
+			'protocole http' => [
+				'case' => 'un superbe http://www.monsite.tld, pas mal',
+				'url' => 'http://www.monsite.tld',
+			],
+			'protocole https' => [
+				'case' => 'un superbe https://www.monsite.tld, pas mal',
+				'url' => 'https://www.monsite.tld',
+			],
+		];
+	}
+
+	public function testLiensAvecAncre() {
+		$case = '[uneancre<-] a [->www.monsite.tld]';
+		$url = 'http://www.monsite.tld';
+		$propre = propre($case);
+		$this->assertEquals(
+			$url,
+			extraire_attribut(extraire_balises($propre, 'a')[1], 'href'),
+			sprintf('Erreur lien dans "%s". Propre: "%s"', $case, $propre)
+		);
+	}
+
+	public function testLienModele() {
+		$case = '<flv|url=http://rezo.net/>';
+		$propre = propre($case);
+		$expected = '<p><tt>&lt;flv|url=http://rezo.net/&gt;</tt></p>';
+		$this->assertEquals(
+			$expected,
+			$propre,
+			sprintf('Erreur lien dans "%s". Propre: "%s"', $case, $propre)
+		);
+	}
+}
diff --git a/ecrire/tests/legacy/unit/propre/liens.php b/ecrire/tests/legacy/unit/propre/liens.php
deleted file mode 100644
index 0b319b1224..0000000000
--- a/ecrire/tests/legacy/unit/propre/liens.php
+++ /dev/null
@@ -1,198 +0,0 @@
-<?php
-
-declare(strict_types=1);
-
-define('_ESPACE_PRIVE', 1); // pour tester le modele inexistant, qui sera sinon ignore
-
-$test = 'liens';
-
-$remonte = __DIR__ . '/';
-
-while (!is_file($remonte . 'test.inc')) {
-	$remonte .= '../';
-}
-
-require $remonte . 'test.inc';
-
-include_spip('inc/texte');
-
-include_spip('inc/lang');
-
-$s = spip_query("SELECT * FROM spip_articles WHERE statut='publie' AND lang>'' LIMIT 0,1");
-
-$t = sql_fetch($s);
-
-// on se met dans une autre langue que celle de l'article
-
-$la_langue = 'eo';
-
-if ($t['lang'] === 'eo') {
-	$la_langue = 'fa';
-}
-
-lang_select($la_langue);
-
-$p0 = '[->' . $t['id_article'] . ']';
-
-$p1 = '[bla {blabla}->url]'; // blabla ne peut pas etre un hreflang
-
-$p2 = '[bla{en}->url]';
-
-$p3 = '[bla|bulle de savon{eo}->url]';
-
-$p4 = '[bla|fa->url]'; // fa est hreflang ET title
-
-$p5 = '[bla|bulle de savon->url]';
-
-$p6 = '[<multi>[fr]X[eo]Y[fa]Z</multi>->url]';
-
-$p7 = '[uneancre<-] a [->www.monsite.tld]';
-
-$p8 = 'un superbe www.monsite.tld, pas mal';
-
-$p9 = 'un superbe http://www.monsite.tld, pas mal';
-
-$p10 = 'un superbe https://www.monsite.tld, pas mal';
-
-$p11 = '<flv|url=http://rezo.net/>';
-
-$err = [];
-
-if (extraire_attribut(propre($p0), 'hreflang') !== $t['lang']) {
-	$err[] = "hreflang automatique errone dans {$p0} : " . PtoBR(propre($p0));
-}
-
-if (extraire_attribut(propre($p1), 'href') !== 'url') {
-	$err[] = "url mal extrait de {$p1}";
-}
-
-if (extraire_attribut(propre($p1), 'hreflang') === 'blabla') {
-	$err[] = "hreflang errone dans {$p1}";
-}
-
-if (supprimer_tags(propre($p1)) !== 'bla blabla') {
-	$err[] = "texte du lien abime dans {$p1}";
-}
-
-if (extraire_attribut(propre($p2), 'href') !== 'url') {
-	$err[] = "url mal extrait de {$p2}";
-}
-
-if (extraire_attribut(propre($p2), 'hreflang') !== 'en') {
-	$err[] = "hreflang errone dans {$p2}";
-}
-
-if (supprimer_tags(propre($p2)) !== 'bla') {
-	$err[] = "texte du lien abime dans {$p2}";
-}
-
-if (extraire_attribut(propre($p3), 'href') !== 'url') {
-	$err[] = "url mal extrait de {$p3}";
-}
-
-if (extraire_attribut(propre($p3), 'hreflang') !== 'eo') {
-	$err[] = "hreflang errone dans {$p3}";
-}
-
-if (extraire_attribut(propre($p3), 'title') !== 'bulle de savon') {
-	$err[] = "title errone dans {$p3}";
-}
-
-if (supprimer_tags(propre($p3)) !== 'bla') {
-	$err[] = "texte du lien abime dans {$p3}";
-}
-
-if (extraire_attribut(propre($p4), 'href') !== 'url') {
-	$err[] = "url mal extrait de {$p4}";
-}
-
-if (extraire_attribut(propre($p4), 'hreflang') !== 'fa') {
-	$err[] = "hreflang errone dans {$p4}";
-}
-
-if (extraire_attribut(propre($p4), 'title') !== 'fa') {
-	$err[] = "title errone dans {$p4}";
-}
-
-if (supprimer_tags(propre($p4)) !== 'bla') {
-	$err[] = "texte du lien abime dans {$p4}";
-}
-
-if (extraire_attribut(propre($p5), 'href') !== 'url') {
-	$err[] = "url mal extrait de {$p5}";
-}
-
-if (extraire_attribut(propre($p5), 'hreflang') !== null) {
-	$err[] = "hreflang errone dans {$p5}";
-}
-
-if (extraire_attribut(propre($p5), 'title') !== 'bulle de savon') {
-	$err[] = "title errone dans {$p5}";
-}
-
-if (supprimer_tags(propre($p5)) !== 'bla') {
-	$err[] = "texte du lien abime dans {$p5}";
-}
-
-if (supprimer_tags(propre($p6)) !== ($la_langue === 'eo' ? 'Y' : 'Z')) {
-	$err[] = "multi abime dans {$p6}";
-}
-
-# (('<multi>[fr]X[en]Y</multi>')); => pre_typo
-
-$balises_p7 = extraire_balises(propre($p7), 'a');
-
-if (
-	'http://www.monsite.tld'
-		!== $a = extraire_attribut(array_pop($balises_p7), 'href')
-) {
-	$err[] = $a . ': erreur sur le lien ' . $p7;
-}
-
-if (
-	'http://www.monsite.tld'
-		!== $a = extraire_attribut(extraire_balise(propre($p8), 'a'), 'href')
-) {
-	$err[] = $a . ': erreur sur le lien ' . $p8;
-}
-
-if (
-	'http://www.monsite.tld'
-		!== $a = extraire_attribut(extraire_balise(propre($p9), 'a'), 'href')
-) {
-	$err[] = $a . ': erreur sur le lien ' . $p9;
-}
-
-if (
-	'https://www.monsite.tld'
-		!== $a = extraire_attribut(extraire_balise(propre($p10), 'a'), 'href')
-) {
-	$err[] = $a . ': erreur sur le lien ' . $p10;
-}
-
-if (
-	'https://www.monsite.tld'
-		!== $a = extraire_attribut(extraire_balise(propre($p10), 'a'), 'href')
-) {
-	$err[] = $a . ': erreur sur le lien ' . $p10;
-}
-
-if (
-	!in_array(
-		$a = propre($p11),
-		[
-			'<p><flv|url=http://rezo.net/></p>',
-			'<p><tt>&lt;flv|url=http://rezo.net/&gt;</tt></p>',
-			'<pre>&lt;flv|url=http://rezo.net/&gt;</pre>',
-		],
-		true
-	)
-) {
-	$err[] = $a . ': erreur sur le modele ' . $p11;
-}
-
-if ($err) {
-	var_dump($err);
-} else {
-	echo 'OK';
-}
diff --git a/ecrire/tests/legacy/unit/propre/liens_classes.php b/ecrire/tests/legacy/unit/propre/liens_classes.php
deleted file mode 100644
index 5e6290fef0..0000000000
--- a/ecrire/tests/legacy/unit/propre/liens_classes.php
+++ /dev/null
@@ -1,75 +0,0 @@
-<?php
-
-declare(strict_types=1);
-
-$err = [];
-
-$test = 'liens_classes';
-
-$remonte = __DIR__ . '/';
-
-while (!is_file($remonte . 'test.inc')) {
-	$remonte .= '../';
-}
-
-require $remonte . 'test.inc';
-
-include_spip('inc/texte');
-
-include_spip('inc/lang');
-
-$id = sql_getfetsel('id_article', 'spip_articles', "statut='publie'", '', '', '0,1');
-
-if (!$id) {
-	echo 'NA Necessite un article publie<br />';
-}
-
-$p0 = "[->art{$id}]";
-
-if (
-	!($c = extraire_attribut(propre($p0), 'class'))
-	|| !str_contains($c, 'spip_in')
-	|| str_contains($c, 'spip_out')
-) {
-	$err[] = "Classe {$c} errone dans {$p0} : " . PtoBR(propre($p0));
-}
-
-$id = sql_getfetsel('id_rubrique', 'spip_rubriques', "statut='publie'", '', '', '0,1');
-
-if (!$id) {
-	echo 'NA Necessite une rubrique publiee<br />';
-}
-
-$p0 = "[->rub{$id}]";
-
-if (
-	!($c = extraire_attribut(propre($p0), 'class'))
-	|| !str_contains($c, 'spip_in')
-	|| str_contains($c, 'spip_out')
-) {
-	$err[] = "Classe {$c} errone dans {$p0} : " . PtoBR(propre($p0));
-}
-
-$id = sql_getfetsel('id_syndic', 'spip_syndic', "statut='publie'", '', '', '0,1');
-
-if (!$id) {
-	echo 'NA Necessite un site publie<br />';
-}
-
-$p0 = "[->site{$id}]";
-
-if (
-	!($c = extraire_attribut(propre($p0), 'class'))
-	|| str_contains($c, 'spip_in')
-	|| !str_contains($c, 'spip_out')
-) {
-	$err[] = "Classe {$c} errone dans {$p0} : " . PtoBR(propre($p0));
-}
-
-// si le tableau $err est pas vide ca va pas
-
-if (count($err) > 0) {
-	echo '<dl><dt>' . implode('</dt><dt>', $err) . '</dt></dl>';
-} else {
-	echo 'OK';
-}
-- 
GitLab