<?php
/**
* SeekQuarry/Yioop --
* Open Source Pure PHP Search Engine, Crawler, and Indexer
*
* Copyright (C) 2009 - 2026 Chris Pollett chris@pollett.org
*
* LICENSE:
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* END LICENSE
*
* @author Chris Pollett chris@pollett.org
* @license https://www.gnu.org/licenses/ GPL3
* @link https://www.seekquarry.com/
* @copyright 2009 - 2026
* @filesource
*/
namespace seekquarry\yioop\tests;
use seekquarry\yioop\library\JavascriptUnitTest;
use seekquarry\yioop\library\WikiParser;
/**
* Checks that the Javascript wiki parser in scripts/help.js renders wiki
* inputs to the same html the server-side WikiParser produces. The two
* parsers are a port of one another and are meant to agree character for
* character, so the server parser renders each input to get the html the
* Javascript parser is expected to match. There are two groups of cases:
* the code block cases Chris reported, where a multi-line code example used
* to leak its close code tag and a code block wrapping a pre tag used to
* break on its line breaks, and a broader group covering headings,
* emphasis, links, lists, tables, and other everyday markup. In a browser
* each group shows a pass or fail table; from the command line the
* JavascriptUnitTest runner replays the same check under node.
*
* @author Chris Pollett
*/
class WikiParserJavascriptTest extends JavascriptUnitTest
{
/**
* Checks the code and pre block cases Chris reported plus the plain
* inline code and pre cases they grew out of.
*
* @return string html and Javascript that checks each case in a
* browser or, from the command line, under node
*/
public function codeBlockTestCase()
{
$inputs = [
["inline code", "see <code>foo</code> here\n"],
["pre block", "<pre>x</pre>\n"],
["user agent code block",
"<code>\n Mozilla/5.0 (compatible; NAME_FROM_THIS_FIELD; " .
"YOUR_SITES_URL/bot)\n</code>\n"],
["code around pre on one line",
"<code><pre>lalala</pre></code>\n"],
["code around pre on many lines",
"<code>\n<pre>\nlalala\n</pre>\n</code>\n"],
["text after a pre close", "<pre>foo</pre> and more\n"],
];
return $this->renderCases("wikiParserCodeBlock",
"codeBlockTestCase", $inputs);
}
/**
* Checks a broad set of everyday wiki markup so the port is exercised
* beyond the code block cases.
*
* @return string html and Javascript that checks each case in a
* browser or, from the command line, under node
*/
public function parseCorpusTestCase()
{
$inputs = [
["heading", "== Sub =="],
["italic", "''i''"],
["bold", "'''b'''"],
["internal link", "[[Page|text]]"],
["external link", "[[http://x/|e]]"],
["nested list", "* a\n** b\n"],
["ordered list", "# one\n# two\n"],
["definition list", "; term : def\n"],
["table", "{|\n! H\n|-\n| c\n|}\n"],
["nowiki", "<nowiki><b>x</b></nowiki>\n"],
["indent", ": in\n"],
["horizontal rule", "----\n"],
["multibyte", "café ⚙\n"],
];
return $this->renderCases("wikiParserCorpus",
"parseCorpusTestCase", $inputs);
}
/**
* Renders the server parser output for each input and builds the html
* and Javascript block that, in a browser or under node, renders each
* input again with the Javascript parser and reports whether it matches
* the server output. Each input is a name paired with a wiki source.
*
* @param string $container_id id of the div the result table is added
* under
* @param string $test_name name shown for this group of cases
* @param array $inputs list of name and wiki source pairs to check
* @return string the html and Javascript block for this group of cases
*/
private function renderCases($container_id, $test_name, $inputs)
{
$parser = new WikiParser("/b/");
$cases = [];
foreach ($inputs as $input) {
$cases[] = ["name" => $input[0], "source" => $input[1],
"expected" => $parser->parse($input[1], false, false, 0)];
}
$wiki_cases = json_encode($cases);
ob_start();
?>
<div id="<?= $container_id ?>">
</div>
<script src="../scripts/basic.js" ></script>
<script src="../scripts/help.js" ></script>
<script src="../scripts/javascript_unit_test.js" ></script>
<script>
var wiki_cases = <?= $wiki_cases ?>;
var results = [];
for (let index = 0; index < wiki_cases.length; index++) {
let parser = new WikiParser("/b/", false);
let rendered = parser.parse(wiki_cases[index].source, false);
results.push({ name: wiki_cases[index].name,
pass: rendered === wiki_cases[index].expected });
}
reportUnitTestResults("<?= $container_id ?>", "<?= $test_name ?>",
results);
</script>
<?php
$out_data = ob_get_contents();
ob_end_clean();
return $out_data;
}
}