diff --git a/Userland/Utilities/headless-browser.cpp b/Userland/Utilities/headless-browser.cpp index 99dddfadc4c..5795d13a966 100644 --- a/Userland/Utilities/headless-browser.cpp +++ b/Userland/Utilities/headless-browser.cpp @@ -501,9 +501,10 @@ static ErrorOr collect_ref_tests(Vector& tests, StringView path) return {}; } -static ErrorOr run_tests(HeadlessWebContentView& view, StringView test_root_path, StringView test_glob, bool dump_failed_ref_tests, bool dump_gc_graph) +static ErrorOr run_tests(HeadlessWebContentView* view, StringView test_root_path, StringView test_glob, bool dump_failed_ref_tests, bool dump_gc_graph, bool dry_run) { - view.clear_content_filters(); + if (view) + view->clear_content_filters(); TRY(load_test_config(test_root_path)); @@ -526,17 +527,26 @@ static ErrorOr run_tests(HeadlessWebContentView& view, StringView test_root bool is_tty = isatty(STDOUT_FILENO); - outln("Running {} tests...", tests.size()); + if (dry_run) + outln("Found {} tests...", tests.size()); + else + outln("Running {} tests...", tests.size()); + for (size_t i = 0; i < tests.size(); ++i) { auto& test = tests[i]; - if (is_tty) { + if (is_tty && !dry_run) { // Keep clearing and reusing the same line if stdout is a TTY. out("\33[2K\r"); } out("{}/{}: {}", i + 1, tests.size(), LexicalPath::relative_path(test.input_path, test_root_path)); + if (dry_run) { + outln(""); + continue; + } + if (is_tty) fflush(stdout); else @@ -548,7 +558,7 @@ static ErrorOr run_tests(HeadlessWebContentView& view, StringView test_root continue; } - test.result = TRY(run_test(view, test.input_path, test.expectation_path, test.mode, dump_failed_ref_tests)); + test.result = TRY(run_test(*view, test.input_path, test.expectation_path, test.mode, dump_failed_ref_tests)); switch (*test.result) { case TestResult::Pass: ++pass_count; @@ -565,6 +575,9 @@ static ErrorOr run_tests(HeadlessWebContentView& view, StringView test_root } } + if (dry_run) + return 0; + if (is_tty) outln("\33[2K\rDone!"); @@ -578,7 +591,7 @@ static ErrorOr run_tests(HeadlessWebContentView& view, StringView test_root } if (dump_gc_graph) { - auto path = view.dump_gc_graph(); + auto path = view->dump_gc_graph(); if (path.is_error()) { warnln("Failed to dump GC graph: {}", path.error()); } else { @@ -601,6 +614,7 @@ struct Application : public WebView::Application { args_parser.add_option(dump_text, "Dump text and exit", "dump-text", 'T'); args_parser.add_option(test_root_path, "Run tests in path", "run-tests", 'R', "test-root-path"); args_parser.add_option(test_glob, "Only run tests matching the given glob", "filter", 'f', "glob"); + args_parser.add_option(test_dry_run, "List the tests that would be run, without running them", "dry-run"); args_parser.add_option(dump_failed_ref_tests, "Dump screenshots of failing ref tests", "dump-failed-ref-tests", 'D'); args_parser.add_option(dump_gc_graph, "Dump GC graph", "dump-gc-graph", 'G'); args_parser.add_option(resources_folder, "Path of the base resources folder (defaults to /res)", "resources", 'r', "resources-root-path"); @@ -626,6 +640,7 @@ struct Application : public WebView::Application { bool is_layout_test_mode { false }; StringView test_root_path; ByteString test_glob; + bool test_dry_run { false }; }; Application::Application(Badge, Main::Arguments&) @@ -646,13 +661,17 @@ ErrorOr serenity_main(Main::Arguments arguments) // FIXME: Allow passing the window size as an argument. static constexpr Gfx::IntSize window_size { 800, 600 }; - auto view = TRY(HeadlessWebContentView::create(move(theme), window_size, app->resources_folder)); - if (!app->test_root_path.is_empty()) { + OwnPtr view; + if (!app->test_dry_run) + view = TRY(HeadlessWebContentView::create(move(theme), window_size, app->resources_folder)); + auto test_glob = ByteString::formatted("*{}*", app->test_glob); - return run_tests(*view, app->test_root_path, test_glob, app->dump_failed_ref_tests, app->dump_gc_graph); + return run_tests(view, app->test_root_path, test_glob, app->dump_failed_ref_tests, app->dump_gc_graph, app->test_dry_run); } + auto view = TRY(HeadlessWebContentView::create(move(theme), window_size, app->resources_folder)); + VERIFY(!WebView::Application::chrome_options().urls.is_empty()); auto const& url = WebView::Application::chrome_options().urls.first(); if (!url.is_valid()) {