Commit 7bc64b9b authored by jan.koester's avatar jan.koester
Browse files

test

parent fa4f23f4
Loading
Loading
Loading
Loading
+18 −0
Changes for tests/CMakeLists.txt: 18 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -2,3 +2,21 @@ include_directories(
    ${CMAKE_SOURCE_DIR}/src
)

# Standalone regression driver for editor/src/htmlimport.cpp -- see its own
# doc comment. Not gated behind BUILD_EDITOR since it only needs htmlimport.cpp
# itself, not the rest of the editor executable.
add_executable(htmlimport_smoke
    htmlimport_smoke.cpp
    ${CMAKE_SOURCE_DIR}/editor/src/htmlimport.cpp
)
target_include_directories(htmlimport_smoke PRIVATE ${CMAKE_SOURCE_DIR}/editor/src)
target_link_libraries(htmlimport_smoke PRIVATE
    htmlpp::htmlpp
    httppp::httppp
    tinyxml2::tinyxml2
    ZLIB::ZLIB
)

enable_testing()
add_test(NAME htmlimport_smoke COMMAND htmlimport_smoke)
+157 −0
Changes for tests/htmlimport_smoke.cpp: 157 added lines, 0 removed lines.
Original line number Diff line number Diff line
/*******************************************************************************
Copyright (c) 2026, Jan Koester jan.koester@gmx.net
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in the
      documentation and/or other materials provided with the distribution.
    * Neither the name of the <organization> nor the
      names of its contributors may be used to endorse or promote products
      derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*******************************************************************************/

// Standalone regression driver for editor/src/htmlimport.cpp's HTML->widget-
// XML conversion -- there is no test framework wired up anywhere in this repo
// (see tests/CMakeLists.txt), so this is a plain executable (like
// libhtmlpp's own test/*.cpp) rather than a gtest/ctest suite. Run it
// directly (or via `ctest -R htmlimport_smoke` since it's registered as a
// test) after any change to htmlimport.cpp -- especially its CSS rule
// matching/shorthand-normalization/widget-mapping logic -- and fix any
// FAILs before merging.

#include <iostream>

#include "../editor/src/htmlimport.h"

#define Red     "\033[0;31m"
#define Green   "\033[0;32m"
#define NOCOLOR "\033[0m"

static int testCount = 0;
static int passCount = 0;

static void check(bool cond, const char *desc) {
    ++testCount;
    if (cond) {
        ++passCount;
        std::cout << Green << "  PASS: " << desc << NOCOLOR << std::endl;
    } else {
        std::cout << Red   << "  FAIL: " << desc << NOCOLOR << std::endl;
    }
}

static std::string importXml(const std::string &html) {
    std::string outXml, outCss, outJs;
    blogi::htmlimport::convertHtmlToWidgetXml(html, outXml, outCss, outJs);
    return outXml;
}

int main(){
    // --- Inline style ---
    std::cout << "=== inline style ===" << std::endl;
    {
        std::string xml = importXml("<p style=\"color:red\">hi</p>");
        check(xml.find("font_color=\"red\"") != std::string::npos,
              "inline style color maps to TextBox font_color");
    }

    // --- <style> block matching by class ---
    std::cout << "=== <style> block, class selector ===" << std::endl;
    {
        std::string html =
            "<html><head><style>.foo { color: blue; }</style></head>"
            "<body><p class=\"foo\">hi</p></body></html>";
        std::string xml = importXml(html);
        check(xml.find("font_color=\"blue\"") != std::string::npos,
              "<style> block rule matched by class maps to TextBox font_color");
    }

    // --- <style> block matching by id, compound selector ---
    std::cout << "=== <style> block, id + compound selector ===" << std::endl;
    {
        std::string html =
            "<html><head><style>p.foo#bar { font-size: 22px; }</style></head>"
            "<body><p class=\"foo\" id=\"bar\">hi</p></body></html>";
        std::string xml = importXml(html);
        check(xml.find("font_size=\"22px\"") != std::string::npos,
              "<style> block rule matched by tag.class#id compound");
    }

    // --- @media block ends up in the matching widget's CustomCss ---
    std::cout << "=== @media block ===" << std::endl;
    {
        std::string html =
            "<html><head><style>@media (max-width: 600px) { .foo { color: red; } }"
            "</style></head><body><div class=\"foo\">hi</div></body></html>";
        std::string xml = importXml(html);
        check(xml.find("@media") != std::string::npos &&
              xml.find("max-width: 600px") != std::string::npos,
              "@media block matching an element's class ends up in its CustomCss");
    }

    // --- Longhand border combined into the border_style shorthand attr ---
    std::cout << "=== longhand border -> border_style ===" << std::endl;
    {
        std::string html =
            "<div style=\"border-width:1px;border-style:solid;border-color:#000\">hi</div>";
        std::string xml = importXml(html);
        check(xml.find("border_style=\"1px solid #000\"") != std::string::npos,
              "longhand border-width/style/color combine into border_style");
        check(xml.find("border-width") == std::string::npos,
              "constituent border-width doesn't leak into CustomCss once combined");
    }

    // --- Longhand padding (all 4 sides) combined into the padding attr ---
    std::cout << "=== longhand padding, all 4 sides ===" << std::endl;
    {
        std::string html =
            "<div style=\"padding-top:1px;padding-right:2px;"
            "padding-bottom:3px;padding-left:4px\">hi</div>";
        std::string xml = importXml(html);
        check(xml.find("padding=\"1px 2px 3px 4px\"") != std::string::npos,
              "all-four-sides longhand padding combines into the padding shorthand attr");
    }

    // --- Longhand padding (partial -- only 2 of 4 sides) is left alone ---
    std::cout << "=== longhand padding, partial (not all 4 sides) ===" << std::endl;
    {
        std::string html =
            "<div class=\"partial\" style=\"padding-top:1px;padding-left:4px\">hi</div>";
        std::string xml = importXml(html);
        check(xml.find("padding=\"") == std::string::npos,
              "partial longhand padding is NOT guessed into the padding shorthand attr");
        check(xml.find("padding-top") != std::string::npos,
              "partial longhand padding instead falls through to CustomCss");
    }

    // --- font-weight / font-style reach the widget's own attributes ---
    std::cout << "=== font-weight / font-style ===" << std::endl;
    {
        std::string html = "<p style=\"font-weight:bold;font-style:italic\">hi</p>";
        std::string xml = importXml(html);
        check(xml.find("font_weight=\"bold\"") != std::string::npos,
              "font-weight reaches the TextBox's font_weight attribute (previously silently dropped)");
        check(xml.find("font_style=\"italic\"") != std::string::npos,
              "font-style reaches the TextBox's font_style attribute (previously silently dropped)");
    }

    // --- Summary ---
    std::cout << "\n=== " << passCount << "/" << testCount << " tests passed ===" << std::endl;

    return (passCount == testCount) ? 0 : -1;
}