/ tests / QrCodeJavascriptTest.php
<?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\QrCode;

/**
 * Holds the two encoders to the same answer. The symbol a page shows while
 * it is being written is drawn in the browser and the one it shows once it
 * is saved is drawn on the server, so a reader would meet two different
 * symbols if the two ever disagreed. Each case draws the same text both
 * ways and compares the grids square by square.
 */
class QrCodeJavascriptTest extends JavascriptUnitTest
{
    /**
     * Nothing is set up before a case.
     */
    public function setUp()
    {
    }
    /**
     * Nothing is left behind after a case.
     */
    public function tearDown()
    {
    }
    /**
     * The same text drawn on the server and in the browser must come out
     * as the same squares, at every size the two of them make.
     *
     * @return string the html and Javascript that checks itself, either in
     *      a browser or, from the command line, under node
     */
    public function sameSymbolBothWaysTestCase()
    {
        $texts = ["short", "HELLO WORLD",
            "https://www.seekquarry.com/", str_repeat("a", 100),
            str_repeat("b", 180)];
        $cases = [];
        foreach ($texts as $text) {
            $grid = QrCode::grid($text);
            $rows = [];
            foreach ($grid as $row) {
                $line = "";
                foreach ($row as $square) {
                    $line .= $square ? "1" : "0";
                }
                $rows[] = $line;
            }
            $cases[] = ["name" => "size " . count($grid) . " across",
                "text" => $text, "expected" => $rows];
        }
        return $this->renderCases("qr-both-ways", "Same Symbol Both Ways",
            $cases);
    }
    /**
     * Builds the block of html and Javascript that draws each text again
     * in the browser and reports whether every square matches what the
     * server drew.
     *
     * @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 $cases each case's name, text, and the server's rows
     * @return string the html and Javascript block for this group
     */
    private function renderCases($container_id, $test_name, $cases)
    {
        $qr_cases = json_encode($cases);
        ob_start();
        ?>
        <div id="<?= $container_id ?>">
        </div>
        <script src="../scripts/basic.js" ></script>
        <script src="../scripts/qr.js" ></script>
        <script src="../scripts/javascript_unit_test.js" ></script>
        <script>
        var qr_cases = <?= $qr_cases ?>;
        var results = [];
        for (let index = 0; index < qr_cases.length; index++) {
            let grid = qrGrid(qr_cases[index].text);
            let rows = [];
            for (let row = 0; row < grid.length; row++) {
                let line = "";
                for (let column = 0; column < grid[row].length; column++) {
                    line += grid[row][column] ? "1" : "0";
                }
                rows.push(line);
            }
            let same = (rows.length == qr_cases[index].expected.length);
            for (let row = 0; same && row < rows.length; row++) {
                if (rows[row] !== qr_cases[index].expected[row]) {
                    same = false;
                }
            }
            results.push({ name: qr_cases[index].name, pass: same });
        }
        reportUnitTestResults("<?= $container_id ?>", "<?= $test_name ?>",
            results);
        </script>
        <?php
        $out_data = ob_get_contents();
        ob_end_clean();
        return $out_data;
    }
}
X