diff --git a/Ladybird/CMakeLists.txt b/Ladybird/CMakeLists.txt index d40237a50d..410714c147 100644 --- a/Ladybird/CMakeLists.txt +++ b/Ladybird/CMakeLists.txt @@ -113,7 +113,7 @@ qt_add_executable(headless-browser Utilities.cpp) target_include_directories(headless-browser PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) -target_link_libraries(headless-browser PRIVATE Qt::Core LibWeb LibWebView LibWebSocket LibCrypto LibFileSystem LibGemini LibHTTP LibJS LibGfx LibMain LibTLS LibIPC LibJS) +target_link_libraries(headless-browser PRIVATE Qt::Core LibWeb LibWebView LibWebSocket LibCrypto LibFileSystem LibGemini LibHTTP LibJS LibGfx LibMain LibTLS LibIPC LibJS LibDiff) set_target_properties(ladybird PROPERTIES MACOSX_BUNDLE_GUI_IDENTIFIER org.SerenityOS.Ladybird diff --git a/Meta/Lagom/CMakeLists.txt b/Meta/Lagom/CMakeLists.txt index 3dc71a7e35..3f710a8be0 100644 --- a/Meta/Lagom/CMakeLists.txt +++ b/Meta/Lagom/CMakeLists.txt @@ -379,6 +379,7 @@ if (BUILD_LAGOM) Compress Crypto DNS + Diff Gemini Gfx GL diff --git a/Userland/Utilities/CMakeLists.txt b/Userland/Utilities/CMakeLists.txt index 89d08be635..0c0e0aa95d 100644 --- a/Userland/Utilities/CMakeLists.txt +++ b/Userland/Utilities/CMakeLists.txt @@ -95,7 +95,7 @@ target_link_libraries(gml-format PRIVATE LibGUI) target_link_libraries(grep PRIVATE LibFileSystem LibRegex) target_link_libraries(gunzip PRIVATE LibCompress) target_link_libraries(gzip PRIVATE LibCompress) -target_link_libraries(headless-browser PRIVATE LibCrypto LibFileSystem LibGemini LibGfx LibHTTP LibTLS LibWeb LibWebView LibWebSocket LibIPC LibJS) +target_link_libraries(headless-browser PRIVATE LibCrypto LibFileSystem LibGemini LibGfx LibHTTP LibTLS LibWeb LibWebView LibWebSocket LibIPC LibJS LibDiff) target_link_libraries(icc PRIVATE LibGfx LibVideo) target_link_libraries(image PRIVATE LibGfx) target_link_libraries(image2bin PRIVATE LibGfx) diff --git a/Userland/Utilities/headless-browser.cpp b/Userland/Utilities/headless-browser.cpp index c9e055a19a..e203c2b723 100644 --- a/Userland/Utilities/headless-browser.cpp +++ b/Userland/Utilities/headless-browser.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -229,12 +230,59 @@ static ErrorOr run_test(HeadlessWebContentView& view, StringView inp auto expectation = TRY(String::from_utf8(StringView(TRY(expectation_file->read_until_eof()).bytes()))); auto actual = result.release_value(); - actual = TRY(actual.trim("\n"sv, TrimMode::Right)); - expectation = TRY(expectation.trim("\n"sv, TrimMode::Right)); + auto actual_trimmed = TRY(actual.trim("\n"sv, TrimMode::Right)); + auto expectation_trimmed = TRY(expectation.trim("\n"sv, TrimMode::Right)); - if (actual == expectation) + if (actual_trimmed == expectation_trimmed) return TestResult::Pass; + bool color_output = isatty(STDOUT_FILENO); + + dbgln("Test failed: {}", input_path); + + auto hunks = Diff::from_text(expectation, actual); + for (auto const& hunk : hunks) { + auto original_start = hunk.original_start_line; + auto target_start = hunk.target_start_line; + auto num_added = hunk.added_lines.size(); + auto num_removed = hunk.removed_lines.size(); + + StringBuilder builder; + // Source line(s) + builder.appendff("{}", original_start); + if (num_removed > 1) + builder.appendff(",{}", original_start + num_removed - 1); + + // Action + if (num_added > 0 && num_removed > 0) + builder.append('c'); + else if (num_added > 0) + builder.append('a'); + else + builder.append('d'); + + // Target line(s) + builder.appendff("{}", target_start); + if (num_added > 1) + builder.appendff(",{}", target_start + num_added - 1); + + outln("Hunk: {}", builder.string_view()); + for (auto const& line : hunk.removed_lines) { + if (color_output) + outln("\033[31;1m< {}\033[0m", line); + else + outln("< {}", line); + } + if (num_added > 0 && num_removed > 0) + outln("---"); + for (auto const& line : hunk.added_lines) { + if (color_output) + outln("\033[32;1m> {}\033[0m", line); + else + outln("> {}", line); + } + } + return TestResult::Fail; }