diff options
author | Ali Mohammad Pur <ali.mpfard@gmail.com> | 2021-05-18 18:46:54 +0430 |
---|---|---|
committer | Linus Groh <mail@linusgroh.de> | 2021-05-18 18:48:15 +0100 |
commit | d897abf4c2e7be4c3aab8fba9869221c19207497 (patch) | |
tree | bf7595de69b83409790fb792695c6a791b09d630 | |
parent | f137c1bfaac5714197dcba58c0f1f08d2761d133 (diff) | |
download | serenity-d897abf4c2e7be4c3aab8fba9869221c19207497.zip |
LibWeb: Implement test-web in terms of LibTest/JavaScriptTestRunner
This deduplicates the test-js copy-ism :^)
26 files changed, 607 insertions, 1123 deletions
diff --git a/Tests/LibWeb/CMakeLists.txt b/Tests/LibWeb/CMakeLists.txt index 0a0aa280c8..4ddba42a05 100644 --- a/Tests/LibWeb/CMakeLists.txt +++ b/Tests/LibWeb/CMakeLists.txt @@ -1,3 +1,2 @@ -add_executable(test-web test-web.cpp) -target_link_libraries(test-web LibCore LibWeb) +serenity_testjs_test(test-web.cpp test-web LIBS LibWeb) install(TARGETS test-web RUNTIME DESTINATION bin) diff --git a/Tests/LibWeb/test-web.cpp b/Tests/LibWeb/test-web.cpp index b6b193fb54..8155e2c881 100644 --- a/Tests/LibWeb/test-web.cpp +++ b/Tests/LibWeb/test-web.cpp @@ -4,664 +4,125 @@ * SPDX-License-Identifier: BSD-2-Clause */ -#include <AK/Function.h> -#include <AK/JsonObject.h> -#include <AK/JsonValue.h> -#include <AK/QuickSort.h> #include <AK/URL.h> -#include <LibCore/ArgsParser.h> -#include <LibCore/DirIterator.h> -#include <LibCore/File.h> #include <LibGUI/Application.h> #include <LibGUI/BoxLayout.h> #include <LibGUI/Widget.h> #include <LibGUI/Window.h> -#include <LibJS/Interpreter.h> -#include <LibJS/Lexer.h> -#include <LibJS/Parser.h> -#include <LibJS/Runtime/Array.h> -#include <LibJS/Runtime/JSONObject.h> -#include <LibTest/Results.h> +#include <LibTest/JavaScriptTestRunner.h> +#include <LibWeb/Bindings/MainThreadVM.h> #include <LibWeb/HTML/Parser/HTMLDocumentParser.h> #include <LibWeb/InProcessWebView.h> #include <LibWeb/Loader/ResourceLoader.h> -#include <signal.h> -#include <sys/time.h> -#define TOP_LEVEL_TEST_NAME "__$$TOP_LEVEL$$__" +using namespace Test::JS; -struct ParserError { - JS::Parser::Error error; - String hint; -}; +TEST_ROOT("Userland/Libraries/LibWeb/Tests"); -struct JSFileResult { - String name; - Optional<ParserError> error {}; - double time_taken { 0 }; - // A failed test takes precedence over a skipped test, which both have - // precedence over a passed test - Test::Result most_severe_test_result { Test::Result::Pass }; - Vector<Test::Suite> suites {}; - Vector<String> logged_messages {}; -}; +RefPtr<Web::InProcessWebView> g_page_view; +RefPtr<GUI::Application> g_app; +Optional<URL> next_page_to_load; +Vector<Function<void(JS::Object&)>> after_initial_load_hooks; +Vector<Function<void(JS::Object&)>> before_initial_load_hooks; -Function<void(const URL&)> g_on_page_change; - -class TestRunnerObject final : public JS::Object { - JS_OBJECT(TestRunnerObject, JS::Object); - -public: - explicit TestRunnerObject(JS::GlobalObject&); - virtual void initialize(JS::GlobalObject&) override; - virtual ~TestRunnerObject() override; - -private: - JS_DECLARE_NATIVE_FUNCTION(change_page); -}; - -TestRunnerObject::TestRunnerObject(JS::GlobalObject& global_object) - : Object(*global_object.object_prototype()) -{ -} - -void TestRunnerObject::initialize(JS::GlobalObject& global_object) -{ - Object::initialize(global_object); - define_native_function("changePage", change_page, 1); -} - -TestRunnerObject::~TestRunnerObject() +TESTJS_MAIN_HOOK() { + g_vm = Web::Bindings::main_thread_vm(); + g_app = GUI::Application::construct(g_test_argc, g_test_argv); + auto window = GUI::Window::construct(); + auto& main_widget = window->set_main_widget<GUI::Widget>(); + main_widget.set_fill_with_background_color(true); + main_widget.set_layout<GUI::VerticalBoxLayout>(); + auto& view = main_widget.add<Web::InProcessWebView>(); + view.set_document(Web::DOM::Document::create()); + g_page_view = view; } -JS_DEFINE_NATIVE_FUNCTION(TestRunnerObject::change_page) +TESTJS_GLOBAL_FUNCTION(load_local_page, loadLocalPage) { - auto url = vm.argument(0).to_string(global_object); + auto name = vm.argument(0).to_string(global_object); if (vm.exception()) return {}; - if (g_on_page_change) - g_on_page_change(url); + // Clear the hooks + before_initial_load_hooks.clear(); + after_initial_load_hooks.clear(); + // Set the load URL + if (name.starts_with('/')) + next_page_to_load = URL::create_with_file_protocol(name); + else + next_page_to_load = URL::create_with_file_protocol(LexicalPath::join(g_test_root, "Pages", name).string()); return JS::js_undefined(); } -class TestRunner { -public: - TestRunner(String web_test_root, String js_test_root, Web::InProcessWebView& page_view, bool print_times) - : m_web_test_root(move(web_test_root)) - , m_js_test_root(move(js_test_root)) - , m_print_times(print_times) - , m_page_view(page_view) - { - } - - void run(); - -private: - JSFileResult run_file_test(const String& test_path); - void print_file_result(const JSFileResult& file_result) const; - void print_test_results() const; - - String m_web_test_root; - String m_js_test_root; - bool m_print_times; - - double m_total_elapsed_time_in_ms { 0 }; - Test::Counts m_counts; - - RefPtr<Web::InProcessWebView> m_page_view; - - RefPtr<JS::Program> m_js_test_common; - RefPtr<JS::Program> m_web_test_common; -}; - -static void cleanup_and_exit() -{ - // Clear the taskbar progress. -#ifdef __serenity__ - fprintf(stderr, "\033]9;-1;\033\\"); -#endif - exit(1); -} - -#if 0 -static void handle_sigabrt(int) +TESTJS_GLOBAL_FUNCTION(after_initial_page_load, afterInitialPageLoad) { - dbgln("test-web: SIGABRT received, cleaning up."); - cleanup_and_exit(); -} -#endif - -static double get_time_in_ms() -{ - struct timeval tv1; - auto return_code = gettimeofday(&tv1, nullptr); - VERIFY(return_code >= 0); - return static_cast<double>(tv1.tv_sec) * 1000.0 + static_cast<double>(tv1.tv_usec) / 1000.0; -} - -template<typename Callback> -void iterate_directory_recursively(const String& directory_path, Callback callback) -{ - Core::DirIterator directory_iterator(directory_path, Core::DirIterator::Flags::SkipDots); - - while (directory_iterator.has_next()) { - auto file_path = directory_iterator.next_full_path(); - if (Core::File::is_directory(file_path)) { - iterate_directory_recursively(file_path, callback); - } else { - callback(move(file_path)); - } + auto function = vm.argument(0); + if (!function.is_function()) { + dbgln("afterInitialPageLoad argument is not a function"); + vm.throw_exception<JS::TypeError>(global_object, JS::ErrorType::NotA, "Function"); + return {}; } -} - -static Vector<String> get_test_paths(const String& test_root) -{ - Vector<String> paths; - iterate_directory_recursively(test_root, [&](const String& file_path) { - if (!file_path.ends_with("test-common.js") && !file_path.ends_with(".html") && !file_path.ends_with(".ts")) - paths.append(file_path); + after_initial_load_hooks.append([fn = JS::make_handle(&function.as_function()), &vm](auto& page_object) { + [[maybe_unused]] auto unused = vm.call(const_cast<JS::Function&>(*fn.cell()), JS::js_undefined(), &page_object); }); - - quick_sort(paths); - - return paths; -} - -void TestRunner::run() -{ - size_t progress_counter = 0; - auto test_paths = get_test_paths(m_web_test_root); - - g_on_page_change = [this](auto& page_to_load) { - if (!page_to_load.is_valid()) { - printf("Invalid page URL (%s) on page change", page_to_load.to_string().characters()); - cleanup_and_exit(); - } - - VERIFY(m_page_view->document()); - - // We want to keep the same document since the interpreter is tied to the document, - // and we don't want to lose the test state. So, we just clear the document and - // give a new parser the existing document to work on. - m_page_view->document()->remove_all_children(); - - Web::LoadRequest request; - request.set_url(page_to_load); - - Web::ResourceLoader::the().load_sync( - request, - [&](auto data, auto&, auto) { - Web::HTML::HTMLDocumentParser parser(*m_page_view->document(), data, "utf-8"); - parser.run(page_to_load); - }, - [page_to_load](auto& error, auto) { - printf("Failed to load test page: %s (%s)", page_to_load.to_string().characters(), error.characters()); - cleanup_and_exit(); - }); - }; - - for (auto& path : test_paths) { - ++progress_counter; - print_file_result(run_file_test(path)); -#ifdef __serenity__ - fprintf(stderr, "\033]9;%zu;%zu;\033\\", progress_counter, test_paths.size()); -#endif - } - -#ifdef __serenity__ - fprintf(stderr, "\033]9;-1;\033\\"); -#endif - - print_test_results(); -} - -static Result<NonnullRefPtr<JS::Program>, ParserError> parse_file(const String& file_path) -{ - auto file = Core::File::construct(file_path); - auto result = file->open(Core::OpenMode::ReadOnly); - if (!result) { - printf("Failed to open the following file: \"%s\"\n", file_path.characters()); - cleanup_and_exit(); - } - - auto contents = file->read_all(); - String test_file_string(reinterpret_cast<const char*>(contents.data()), contents.size()); - file->close(); - - auto parser = JS::Parser(JS::Lexer(test_file_string)); - auto program = parser.parse_program(); - - if (parser.has_errors()) { - auto error = parser.errors()[0]; - return Result<NonnullRefPtr<JS::Program>, ParserError>(ParserError { error, error.source_location_hint(test_file_string) }); - } - - return Result<NonnullRefPtr<JS::Program>, ParserError>(program); + return JS::js_undefined(); } -static Optional<JsonValue> get_test_results(JS::Interpreter& interpreter) +TESTJS_GLOBAL_FUNCTION(before_initial_page_load, beforeInitialPageLoad) { - auto result = interpreter.vm().get_variable("__TestResults__", interpreter.global_object()); - auto json_string = JS::JSONObject::stringify_impl(interpreter.global_object(), result, JS::js_undefined(), JS::js_undefined()); - - auto json = JsonValue::from_string(json_string); - if (!json.has_value()) + auto function = vm.argument(0); + if (!function.is_function()) { + dbgln("beforeInitialPageLoad argument is not a function"); + vm.throw_exception<JS::TypeError>(global_object, JS::ErrorType::NotA, "Function"); return {}; + } - return json.value(); + before_initial_load_hooks.append([fn = JS::make_handle(&function.as_function()), &vm](auto& page_object) { + [[maybe_unused]] auto unused = vm.call(const_cast<JS::Function&>(*fn.cell()), JS::js_undefined(), &page_object); + }); + return JS::js_undefined(); } -JSFileResult TestRunner::run_file_test(const String& test_path) +TESTJS_GLOBAL_FUNCTION(wait_for_page_to_load, waitForPageToLoad) { - double start_time = get_time_in_ms(); - VERIFY(m_page_view->document()); - auto& old_interpreter = m_page_view->document()->interpreter(); + // Create a new parser and immediately get its document to replace the old interpreter. + auto document = Web::DOM::Document::create(); - if (!m_js_test_common) { - auto result = parse_file(String::formatted("{}/test-common.js", m_js_test_root)); - if (result.is_error()) { - printf("Unable to parse %s/test-common.js\n", m_js_test_root.characters()); - printf("%s\n", result.error().error.to_string().characters()); - printf("%s\n", result.error().hint.characters()); - cleanup_and_exit(); - } - m_js_test_common = result.value(); - } - - if (!m_web_test_common) { - auto result = parse_file(String::formatted("{}/test-common.js", m_web_test_root)); - if (result.is_error()) { - printf("Unable to parse %s/test-common.js\n", m_web_test_root.characters()); - printf("%s\n", result.error().error.to_string().characters()); - printf("%s\n", result.error().hint.characters()); - cleanup_and_exit(); - } - m_web_test_common = result.value(); - } - - auto file_program = parse_file(test_path); - if (file_program.is_error()) - return { test_path, file_program.error() }; - - // Setup the test on the current page to get "__PageToLoad__". - old_interpreter.run(old_interpreter.global_object(), *m_web_test_common); - old_interpreter.run(old_interpreter.global_object(), *file_program.value()); - auto page_to_load = URL(old_interpreter.vm().get_variable("__PageToLoad__", old_interpreter.global_object()).as_string().string()); - if (!page_to_load.is_valid()) { - printf("Invalid page URL for %s", test_path.characters()); - cleanup_and_exit(); - } - - JSFileResult file_result; + // Run the "before" hooks + for (auto& entry : before_initial_load_hooks) + entry(document->interpreter().global_object()); + // Set the load hook Web::LoadRequest request; - request.set_url(page_to_load); + request.set_url(next_page_to_load.value()); - Web::ResourceLoader::the().load_sync( + auto& loader = Web::ResourceLoader::the(); + loader.load_sync( request, [&](auto data, auto&, auto) { - // Create a new parser and immediately get its document to replace the old interpreter. - auto document = Web::DOM::Document::create(); Web::HTML::HTMLDocumentParser parser(document, data, "utf-8"); - auto& new_interpreter = parser.document().interpreter(); - - // FIXME: This is a hack while we're refactoring Interpreter/VM stuff. - JS::VM::InterpreterExecutionScope scope(new_interpreter); - - // Setup the test environment and call "__BeforeInitialPageLoad__" - new_interpreter.global_object().define_property( - "libweb_tester", - new_interpreter.heap().allocate<TestRunnerObject>(new_interpreter.global_object(), new_interpreter.global_object()), - JS::Attribute::Enumerable | JS::Attribute::Configurable); - new_interpreter.run(new_interpreter.global_object(), *m_js_test_common); - new_interpreter.run(new_interpreter.global_object(), *m_web_test_common); - new_interpreter.run(new_interpreter.global_object(), *file_program.value()); - - auto& before_initial_page_load = new_interpreter.vm().get_variable("__BeforeInitialPageLoad__", new_interpreter.global_object()).as_function(); - [[maybe_unused]] auto rc_before = new_interpreter.vm().call(before_initial_page_load, JS::js_undefined()); - if (new_interpreter.exception()) - new_interpreter.vm().clear_exception(); - // Now parse the HTML page. - parser.run(page_to_load); - m_page_view->set_document(&parser.document()); - - // Finally run the test by calling "__AfterInitialPageLoad__" - auto& after_initial_page_load = new_interpreter.vm().get_variable("__AfterInitialPageLoad__", new_interpreter.global_object()).as_function(); - [[maybe_unused]] auto rc_after = new_interpreter.vm().call(after_initial_page_load, JS::js_undefined()); - if (new_interpreter.exception()) - new_interpreter.vm().clear_exception(); - - auto test_json = get_test_results(new_interpreter); - if (!test_json.has_value()) { - printf("Received malformed JSON from test \"%s\"\n", test_path.characters()); - cleanup_and_exit(); + parser.run(next_page_to_load.value()); + g_page_view->set_document(&parser.document()); + if (vm.exception()) { + // FIXME: Should we do something about this? the document itself threw unhandled exceptions... + vm.clear_exception(); } - file_result = { test_path.substring(m_web_test_root.length() + 1, test_path.length() - m_web_test_root.length() - 1) }; - - // Collect logged messages - auto& arr = new_interpreter.vm().get_variable("__UserOutput__", new_interpreter.global_object()).as_array(); - for (auto& entry : arr.indexed_properties()) { - auto message = entry.value_and_attributes(&new_interpreter.global_object()).value; - file_result.logged_messages.append(message.to_string_without_side_effects()); + // Run the "after" hooks + for (auto& entry : after_initial_load_hooks) { + entry(document->interpreter().global_object()); + if (vm.exception()) + break; } - - test_json.value().as_object().for_each_member([&](const String& suite_name, const JsonValue& suite_value) { - Test::Suite suite { suite_name }; - - VERIFY(suite_value.is_object()); - - suite_value.as_object().for_each_member([&](const String& test_name, const JsonValue& test_value) { - Test::Case test { test_name, Test::Result::Fail, "" }; - - VERIFY(test_value.is_object()); - VERIFY(test_value.as_object().has("result")); - - auto result = test_value.as_object().get("result"); - VERIFY(result.is_string()); - auto result_string = result.as_string(); - if (result_string == "pass") { - test.result = Test::Result::Pass; - m_counts.tests_passed++; - } else if (result_string == "fail") { - test.result = Test::Result::Fail; - m_counts.tests_failed++; - suite.most_severe_test_result = Test::Result::Fail; - VERIFY(test_value.as_object().has("details")); - auto details = test_value.as_object().get("details"); - VERIFY(result.is_string()); - test.details = details.as_string(); - } else { - test.result = Test::Result::Skip; - if (suite.most_severe_test_result == Test::Result::Pass) - suite.most_severe_test_result = Test::Result::Skip; - m_counts.tests_skipped++; - } - - suite.tests.append(test); - }); - - if (suite.most_severe_test_result == Test::Result::Fail) { - m_counts.suites_failed++; - file_result.most_severe_test_result = Test::Result::Fail; - } else { - if (suite.most_severe_test_result == Test::Result::Skip && file_result.most_severe_test_result == Test::Result::Pass) - file_result.most_severe_test_result = Test::Result::Skip; - m_counts.suites_passed++; - } - - file_result.suites.append(suite); - }); - - m_counts.files_total++; - - file_result.time_taken = get_time_in_ms() - start_time; - m_total_elapsed_time_in_ms += file_result.time_taken; }, - [page_to_load](auto& error, auto) { - printf("Failed to load test page: %s (%s)", page_to_load.to_string().characters(), error.characters()); - cleanup_and_exit(); + [&](auto) { + dbgln("Load of resource {} failed", next_page_to_load.value()); + vm.throw_exception<Web::DOM::NetworkError>(global_object); }); - return file_result; -} - -enum Modifier { - BG_RED, - BG_GREEN, - FG_RED, - FG_GREEN, - FG_ORANGE, - FG_GRAY, - FG_BLACK, - FG_BOLD, - ITALIC, - CLEAR, -}; - -static void print_modifiers(Vector<Modifier> modifiers) -{ - for (auto& modifier : modifiers) { - auto code = [&]() -> String { - switch (modifier) { - case BG_RED: - return "\033[48;2;255;0;102m"; - case BG_GREEN: - return "\033[48;2;102;255;0m"; - case FG_RED: - return "\033[38;2;255;0;102m"; - case FG_GREEN: - return "\033[38;2;102;255;0m"; - case FG_ORANGE: - return "\033[38;2;255;102;0m"; - case FG_GRAY: - return "\033[38;2;135;139;148m"; - case FG_BLACK: - return "\033[30m"; - case FG_BOLD: - return "\033[1m"; - case ITALIC: - return "\033[3m"; - case CLEAR: - return "\033[0m"; - } - VERIFY_NOT_REACHED(); - }; - printf("%s", code().characters()); - } -} - -void TestRunner::print_file_result(const JSFileResult& file_result) const -{ - if (file_result.most_severe_test_result == Test::Result::Fail || file_result.error.has_value()) { - print_modifiers({ BG_RED, FG_BLACK, FG_BOLD }); - printf(" FAIL "); - print_modifiers({ CLEAR }); - } else { - if (m_print_times || file_result.most_severe_test_result != Test::Result::Pass) { - print_modifiers({ BG_GREEN, FG_BLACK, FG_BOLD }); - printf(" PASS "); - print_modifiers({ CLEAR }); - } else { - return; - } - } - - printf(" %s", file_result.name.characters()); - - if (m_print_times) { - print_modifiers({ CLEAR, ITALIC, FG_GRAY }); - if (file_result.time_taken < 1000) { - printf(" (%dms)\n", static_cast<int>(file_result.time_taken)); - } else { - printf(" (%.3fs)\n", file_result.time_taken / 1000.0); - } - print_modifiers({ CLEAR }); - } else { - printf("\n"); - } - - if (!file_result.logged_messages.is_empty()) { - print_modifiers({ FG_GRAY, FG_BOLD }); -#ifdef __serenity__ - printf(" âš Console output:\n"); -#else - // This emoji has a second invisible byte after it. The one above does not - printf(" âšī¸ Console output:\n"); -#endif - print_modifiers({ CLEAR, FG_GRAY }); - for (auto& message : file_result.logged_messages) - printf(" %s\n", message.characters()); - } - - if (file_result.error.has_value()) { - auto test_error = file_result.error.value(); - - print_modifiers({ FG_RED }); -#ifdef __serenity__ - printf(" â The file failed to parse\n\n"); -#else - // No invisible byte here, but the spacing still needs to be altered on the host - printf(" â The file failed to parse\n\n"); -#endif - print_modifiers({ FG_GRAY }); - for (auto& message : test_error.hint.split('\n', true)) { - printf(" %s\n", message.characters()); - } - print_modifiers({ FG_RED }); - printf(" %s\n\n", test_error.error.to_string().characters()); - - return; - } - - if (file_result.most_severe_test_result != Test::Result::Pass) { - for (auto& suite : file_result.suites) { - if (suite.most_severe_test_result == Test::Result::Pass) - continue; - - bool failed = suite.most_severe_test_result == Test::Result::Fail; - - print_modifiers({ FG_GRAY, FG_BOLD }); - - if (failed) { -#ifdef __serenity__ - printf(" â Suite: "); -#else - // No invisible byte here, but the spacing still needs to be altered on the host - printf(" â Suite: "); -#endif - } else { -#ifdef __serenity__ - printf(" â Suite: "); -#else - // This emoji has a second invisible byte after it. The one above does not - printf(" â ī¸ Suite: "); -#endif - } - - print_modifiers({ CLEAR, FG_GRAY }); - - if (suite.name == TOP_LEVEL_TEST_NAME) { - printf("<top-level>\n"); - } else { - printf("%s\n", suite.name.characters()); - } - print_modifiers({ CLEAR }); - - for (auto& test : suite.tests) { - if (test.result == Test::Result::Pass) - continue; - - print_modifiers({ FG_GRAY, FG_BOLD }); - printf(" Test: "); - if (test.result == Test::Result::Fail) { - print_modifiers({ CLEAR, FG_RED }); - printf("%s (failed):\n", test.name.characters()); - printf(" %s\n", test.details.characters()); - } else { - print_modifiers({ CLEAR, FG_ORANGE }); - printf("%s (skipped)\n", test.name.characters()); - } - print_modifiers({ CLEAR }); - } - } - } -} - -void TestRunner::print_test_results() const -{ - printf("\nTest Suites: "); - if (m_counts.suites_failed) { - print_modifiers({ FG_RED }); - printf("%d failed, ", m_counts.suites_failed); - print_modifiers({ CLEAR }); - } - if (m_counts.suites_passed) { - print_modifiers({ FG_GREEN }); - printf("%d passed, ", m_counts.suites_passed); - print_modifiers({ CLEAR }); - } - printf("%d total\n", m_counts.suites_failed + m_counts.suites_passed); - - printf("Tests: "); - if (m_counts.tests_failed) { - print_modifiers({ FG_RED }); - printf("%d failed, ", m_counts.tests_failed); - print_modifiers({ CLEAR }); - } - if (m_counts.tests_skipped) { - print_modifiers({ FG_ORANGE }); - printf("%d skipped, ", m_counts.tests_skipped); - print_modifiers({ CLEAR }); - } - if (m_counts.tests_passed) { - print_modifiers({ FG_GREEN }); - printf("%d passed, ", m_counts.tests_passed); - print_modifiers({ CLEAR }); - } - printf("%d total\n", m_counts.tests_failed + m_counts.tests_passed); - - printf("Files: %d total\n", m_counts.files_total); - - printf("Time: "); - if (m_total_elapsed_time_in_ms < 1000.0) { - printf("%dms\n\n", static_cast<int>(m_total_elapsed_time_in_ms)); - } else { - printf("%-.3fs\n\n", m_total_elapsed_time_in_ms / 1000.0); - } -} - -int main(int argc, char** argv) -{ - bool print_times = false; - bool show_window = false; - -#if 0 - struct sigaction act; - memset(&act, 0, sizeof(act)); - act.sa_flags = SA_NOCLDWAIT; - act.sa_handler = handle_sigabrt; - int rc = sigaction(SIGABRT, &act, nullptr); - if (rc < 0) { - perror("sigaction"); - return 1; - } -#endif - - Core::ArgsParser args_parser; - args_parser.add_option(print_times, "Show duration of each test", "show-time", 't'); - args_parser.add_option(show_window, "Show window while running tests", "window", 'w'); - args_parser.parse(argc, argv); - - auto app = GUI::Application::construct(argc, argv); - auto window = GUI::Window::construct(); - auto& main_widget = window->set_main_widget<GUI::Widget>(); - main_widget.set_fill_with_background_color(true); - main_widget.set_layout<GUI::VerticalBoxLayout>(); - auto& view = main_widget.add<Web::InProcessWebView>(); - - view.set_document(Web::DOM::Document::create()); - - if (show_window) { - window->set_title("LibWeb Test Window"); - window->resize(640, 480); - window->show(); - } - -#ifdef __serenity__ - TestRunner("/home/anon/web-tests", "/home/anon/js-tests", view, print_times).run(); -#else - char* serenity_source_dir = getenv("SERENITY_SOURCE_DIR"); - if (!serenity_source_dir) { - printf("test-web requires the SERENITY_SOURCE_DIR environment variable to be set"); - return 1; - } - TestRunner(String::formatted("{}/Userland/Libraries/LibWeb/Tests", serenity_source_dir), String::formatted("{}/Userland/Libraries/LibJS/Tests", serenity_source_dir), view, print_times).run(); -#endif - return 0; + return JS::js_undefined(); } diff --git a/Userland/Libraries/LibWeb/Tests/DOM/Comment.js b/Userland/Libraries/LibWeb/Tests/DOM/Comment.js index 0dab522e9c..354be07dad 100644 --- a/Userland/Libraries/LibWeb/Tests/DOM/Comment.js +++ b/Userland/Libraries/LibWeb/Tests/DOM/Comment.js @@ -1,15 +1,17 @@ -loadPage("file:///home/anon/web-tests/Pages/Comment.html"); +describe("Comments", () => { + loadLocalPage("Comment.html"); + afterInitialPageLoad(page => { + test("Basic functionality", () => { + const comment = page.document.body.firstChild.nextSibling; + expect(comment).not.toBeNull(); -afterInitialPageLoad(() => { - test("Basic functionality", () => { - const comment = document.body.firstChild.nextSibling; - expect(comment).not.toBeNull(); + // FIXME: Add this in once Comment's constructor is implemented. + //expect(comment).toBeInstanceOf(Comment); - // FIXME: Add this in once Comment's constructor is implemented. - //expect(comment).toBeInstanceOf(Comment); - - expect(comment.nodeName).toBe("#comment"); - expect(comment.data).toBe("This is a comment"); - expect(comment).toHaveLength(17); + expect(comment.nodeName).toBe("#comment"); + expect(comment.data).toBe("This is a comment"); + expect(comment).toHaveLength(17); + }); }); + waitForPageToLoad(); }); diff --git a/Userland/Libraries/LibWeb/Tests/DOM/Element.js b/Userland/Libraries/LibWeb/Tests/DOM/Element.js index 16606829aa..d92fbae200 100644 --- a/Userland/Libraries/LibWeb/Tests/DOM/Element.js +++ b/Userland/Libraries/LibWeb/Tests/DOM/Element.js @@ -1,39 +1,42 @@ -loadPage("file:///res/html/misc/innertext_textcontent.html"); +describe("Element", () => { + loadLocalPage("/res/html/misc/innertext_textcontent.html"); -afterInitialPageLoad(() => { - test("Element.innerText", () => { - var p = document.getElementsByTagName("p")[0]; - expect(p.innerText).toBe("This is a very small test page :^)"); + afterInitialPageLoad(page => { + test("Element.innerText", () => { + var p = page.document.getElementsByTagName("p")[0]; + expect(p.innerText).toBe("This is a very small test page :^)"); - // FIXME: Call this on p once that's supported. - var b = document.getElementsByTagName("b")[0]; - b.innerText = "foo"; - expect(b.innerText).toBe("foo"); - expect(p.innerText).toBe("This is a foo test page :^)"); + // FIXME: Call this on p once that's supported. + var b = page.document.getElementsByTagName("b")[0]; + b.innerText = "foo"; + expect(b.innerText).toBe("foo"); + expect(p.innerText).toBe("This is a foo test page :^)"); - p.innerText = "bar"; - expect(p.innerText).toBe("bar"); + p.innerText = "bar"; + expect(p.innerText).toBe("bar"); - var p = document.getElementById("source"); - // FIXME: The leading and trailing two spaces each are wrong. - // FIXME: The text should be affected by the text-transform:uppercase. - expect(p.innerText).toBe(` Take a look at + var p = page.document.getElementById("source"); + // FIXME: The leading and trailing two spaces each are wrong. + // FIXME: The text should be affected by the text-transform:uppercase. + expect(p.innerText).toBe(` Take a look at how this text is interpreted below. `); - }); + }); - test("Element.namespaceURI basics", () => { - const htmlNamespace = "http://www.w3.org/1999/xhtml"; - const p = document.getElementsByTagName("p")[0]; - expect(p.namespaceURI).toBe(htmlNamespace); + test("Element.namespaceURI basics", () => { + const htmlNamespace = "http://www.w3.org/1999/xhtml"; + const p = page.document.getElementsByTagName("p")[0]; + expect(p.namespaceURI).toBe(htmlNamespace); - // createElement always sets the namespace to the HTML namespace in HTML documents. - const svgElement = document.createElement("svg"); - expect(svgElement.namespaceURI).toBe(htmlNamespace); + // createElement always sets the namespace to the HTML namespace in HTML page.documents. + const svgElement = page.document.createElement("svg"); + expect(svgElement.namespaceURI).toBe(htmlNamespace); - const svgNamespace = "http://www.w3.org/2000/svg"; - p.innerHTML = "<svg></svg>"; - const domSVGElement = p.getElementsByTagName("svg")[0]; - expect(domSVGElement.namespaceURI).toBe(svgNamespace); + const svgNamespace = "http://www.w3.org/2000/svg"; + p.innerHTML = "<svg></svg>"; + const domSVGElement = p.getElementsByTagName("svg")[0]; + expect(domSVGElement.namespaceURI).toBe(svgNamespace); + }); }); + waitForPageToLoad(); }); diff --git a/Userland/Libraries/LibWeb/Tests/DOM/Node.js b/Userland/Libraries/LibWeb/Tests/DOM/Node.js index ddb02d19d0..12f8e12a57 100644 --- a/Userland/Libraries/LibWeb/Tests/DOM/Node.js +++ b/Userland/Libraries/LibWeb/Tests/DOM/Node.js @@ -1,62 +1,68 @@ -loadPage("file:///res/html/misc/innertext_textcontent.html"); - -afterInitialPageLoad(() => { - test("Node.textContent", () => { - var p = document.getElementsByTagName("p")[0]; - expect(p.textContent).toBe("This is a very small test page :^)"); - expect(p.firstChild.textContent).toBe("This is a "); - expect(p.firstChild.firstChild).toBe(null); - - p.firstChild.textContent = "foo"; - expect(p.firstChild.textContent).toBe("foo"); - expect(p.firstChild.firstChild).toBe(null); - expect(p.textContent).toBe("foovery small test page :^)"); - - p.textContent = "bar"; - expect(p.textContent).toBe("bar"); - expect(p.firstChild.textContent).toBe("bar"); - expect(p.firstChild.firstChild).toBe(null); - - var p = document.getElementById("source"); - expect(p.textContent).toBe(` +describe("Node", () => { + loadLocalPage("/res/html/misc/innertext_textcontent.html"); + + afterInitialPageLoad(page => { + test("Node.textContent", () => { + var p = page.document.getElementsByTagName("p")[0]; + expect(p.textContent).toBe("This is a very small test page :^)"); + expect(p.firstChild.textContent).toBe("This is a "); + expect(p.firstChild.firstChild).toBe(null); + + p.firstChild.textContent = "foo"; + expect(p.firstChild.textContent).toBe("foo"); + expect(p.firstChild.firstChild).toBe(null); + expect(p.textContent).toBe("foovery small test page :^)"); + + p.textContent = "bar"; + expect(p.textContent).toBe("bar"); + expect(p.firstChild.textContent).toBe("bar"); + expect(p.firstChild.firstChild).toBe(null); + + var p = page.document.getElementById("source"); + expect(p.textContent).toBe(` #source { color: red; } #text { text-transform: uppercase; } Take a look athow this textis interpreted below. HIDDEN TEXT `); - }); + }); - test("Node.isConnected", () => { - var element = document.createElement("p"); - expect(element.isConnected).toBeFalse(); + test("Node.isConnected", () => { + var element = page.document.createElement("p"); + expect(element.isConnected).toBeFalse(); - document.body.appendChild(element); - expect(element.isConnected).toBeTrue(); + page.document.body.appendChild(element); + expect(element.isConnected).toBeTrue(); - document.body.removeChild(element); - expect(element.isConnected).toBeFalse(); - }); + page.document.body.removeChild(element); + expect(element.isConnected).toBeFalse(); + }); - test("Node.compareDocumentPosition()", () => { - const head = document.head; - const body = document.body; + test("Node.compareDocumentPosition()", () => { + const head = page.document.head; + const body = page.document.body; - expect(head.compareDocumentPosition(head)).toBe(0); + expect(head.compareDocumentPosition(head)).toBe(0); - // FIXME: Can be uncommented once the IDL parser correctly implements nullable parameters. - // expect(head.compareDocumentPosition(null) & Node.DOCUMENT_POSITION_DISCONNECTED | Node.DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC). - // toBe(Node.DOCUMENT_POSITION_DISCONNECTED | Node.DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC); + // FIXME: Can be uncommented once the IDL parser correctly implements nullable parameters. + // expect(head.compareDocumentPosition(null) & Node.DOCUMENT_POSITION_DISCONNECTED | Node.DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC). + // toBe(Node.DOCUMENT_POSITION_DISCONNECTED | Node.DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC); - expect(head.compareDocumentPosition(body)).toBe(Node.DOCUMENT_POSITION_FOLLOWING); - expect(body.compareDocumentPosition(head)).toBe(Node.DOCUMENT_POSITION_PRECEDING); + expect(head.compareDocumentPosition(body)).toBe(page.Node.DOCUMENT_POSITION_FOLLOWING); + expect(body.compareDocumentPosition(head)).toBe(page.Node.DOCUMENT_POSITION_PRECEDING); - const source = document.getElementById("source"); - expect(source.compareDocumentPosition(body)).toBe( - Node.DOCUMENT_POSITION_CONTAINS | Node.DOCUMENT_POSITION_PRECEDING - ); - expect(body.compareDocumentPosition(source)).toBe( - Node.DOCUMENT_POSITION_CONTAINED_BY | Node.DOCUMENT_POSITION_FOLLOWING - ); - expect(source.compareDocumentPosition(head)).toBe(Node.DOCUMENT_POSITION_PRECEDING); + const source = page.document.getElementById("source"); + expect(source.compareDocumentPosition(body)).toBe( + page.Node.DOCUMENT_POSITION_CONTAINS | page.Node.DOCUMENT_POSITION_PRECEDING + ); + expect(body.compareDocumentPosition(source)).toBe( + page.Node.DOCUMENT_POSITION_CONTAINED_BY | page.Node.DOCUMENT_POSITION_FOLLOWING + ); + expect(source.compareDocumentPosition(head)).toBe( + page.Node.DOCUMENT_POSITION_PRECEDING + ); + }); }); + + waitForPageToLoad(); }); diff --git a/Userland/Libraries/LibWeb/Tests/DOM/Text.js b/Userland/Libraries/LibWeb/Tests/DOM/Text.js index 1557a59d3f..d2bb6b63e3 100644 --- a/Userland/Libraries/LibWeb/Tests/DOM/Text.js +++ b/Userland/Libraries/LibWeb/Tests/DOM/Text.js @@ -1,15 +1,18 @@ -loadPage("file:///res/html/misc/blank.html"); +describe("Text", () => { + loadLocalPage("/res/html/misc/blank.html"); -afterInitialPageLoad(() => { - test("Basic functionality", () => { - const title = document.getElementsByTagName("title")[0]; - expect(title).toBeDefined(); + afterInitialPageLoad(page => { + test("Basic functionality", () => { + const title = page.document.getElementsByTagName("title")[0]; + expect(title).toBeDefined(); - // FIXME: Add this in once Text's constructor is implemented. - //expect(title.firstChild).toBeInstanceOf(Text); + // FIXME: Add this in once Text's constructor is implemented. + //expect(title.firstChild).toBeInstanceOf(Text); - expect(title.firstChild.nodeName).toBe("#text"); - expect(title.firstChild.data).toBe("Blank"); - expect(title.firstChild.length).toBe(5); + expect(title.firstChild.nodeName).toBe("#text"); + expect(title.firstChild.data).toBe("Blank"); + expect(title.firstChild.length).toBe(5); + }); }); + waitForPageToLoad(); }); diff --git a/Userland/Libraries/LibWeb/Tests/DOM/document.createComment.js b/Userland/Libraries/LibWeb/Tests/DOM/document.createComment.js index a60d6bfcd5..1b67103110 100644 --- a/Userland/Libraries/LibWeb/Tests/DOM/document.createComment.js +++ b/Userland/Libraries/LibWeb/Tests/DOM/document.createComment.js @@ -1,13 +1,16 @@ -loadPage("file:///res/html/misc/blank.html"); +describe("createComment", () => { + loadLocalPage("/res/html/misc/blank.html"); -afterInitialPageLoad(() => { - test("Basic functionality", () => { - const comment = document.createComment("Create Comment Test"); + afterInitialPageLoad(page => { + test("Basic functionality", () => { + const comment = page.document.createComment("Create Comment Test"); - // FIXME: Add this in once Comment's constructor is implemented. - //expect(comment).toBeInstanceOf(Comment); - expect(comment.nodeName).toBe("#comment"); - expect(comment.data).toBe("Create Comment Test"); - expect(comment.length).toBe(19); + // FIXME: Add this in once Comment's constructor is implemented. + //expect(comment).toBeInstanceOf(Comment); + expect(comment.nodeName).toBe("#comment"); + expect(comment.data).toBe("Create Comment Test"); + expect(comment.length).toBe(19); + }); }); + waitForPageToLoad(); }); diff --git a/Userland/Libraries/LibWeb/Tests/DOM/document.createDocumentFragment.js b/Userland/Libraries/LibWeb/Tests/DOM/document.createDocumentFragment.js index bebc137313..ee3dc1843d 100644 --- a/Userland/Libraries/LibWeb/Tests/DOM/document.createDocumentFragment.js +++ b/Userland/Libraries/LibWeb/Tests/DOM/document.createDocumentFragment.js @@ -1,11 +1,15 @@ -loadPage("file:///res/html/misc/blank.html"); +describe("createDocumentFragment", () => { + loadLocalPage("/res/html/misc/blank.html"); -afterInitialPageLoad(() => { - test("Basic functionality", () => { - const fragment = document.createDocumentFragment(); + afterInitialPageLoad(page => { + test("Basic functionality", () => { + const fragment = page.document.createDocumentFragment(); - // FIXME: Add this in once DocumentFragment's constructor is implemented. - //expect(fragment).toBeInstanceOf(DocumentFragment); - expect(fragment.nodeName).toBe("#document-fragment"); + // FIXME: Add this in once DocumentFragment's constructor is implemented. + //expect(fragment).toBeInstanceOf(DocumentFragment); + expect(fragment.nodeName).toBe("#document-fragment"); + }); }); + + waitForPageToLoad(); }); diff --git a/Userland/Libraries/LibWeb/Tests/DOM/document.createTextNode.js b/Userland/Libraries/LibWeb/Tests/DOM/document.createTextNode.js index bef06a81c7..37c7b6808e 100644 --- a/Userland/Libraries/LibWeb/Tests/DOM/document.createTextNode.js +++ b/Userland/Libraries/LibWeb/Tests/DOM/document.createTextNode.js @@ -1,13 +1,15 @@ -loadPage("file:///res/html/misc/blank.html"); +describe("createTextNode", () => { + loadLocalPage("/res/html/misc/blank.html"); + afterInitialPageLoad(page => { + test("Basic functionality", () => { + const text = page.document.createTextNode("Create Text Test"); -afterInitialPageLoad(() => { - test("Basic functionality", () => { - const text = document.createTextNode("Create Text Test"); - - // FIXME: Add this in once Text's constructor is implemented. - //expect(text).toBeInstanceOf(Text); - expect(text.nodeName).toBe("#text"); - expect(text.data).toBe("Create Text Test"); - expect(text.length).toBe(16); + // FIXME: Add this in once Text's constructor is implemented. + //expect(text).toBeInstanceOf(Text); + expect(text.nodeName).toBe("#text"); + expect(text.data).toBe("Create Text Test"); + expect(text.length).toBe(16); + }); }); + waitForPageToLoad(); }); diff --git a/Userland/Libraries/LibWeb/Tests/DOM/document.doctype.js b/Userland/Libraries/LibWeb/Tests/DOM/document.doctype.js index 5da52014d1..32634aa551 100644 --- a/Userland/Libraries/LibWeb/Tests/DOM/document.doctype.js +++ b/Userland/Libraries/LibWeb/Tests/DOM/document.doctype.js @@ -1,18 +1,22 @@ -loadPage("file:///res/html/misc/blank.html"); - -afterInitialPageLoad(() => { - test("Basic functionality", () => { - expect(document.compatMode).toBe("CSS1Compat"); - expect(document.doctype).not.toBeNull(); - expect(document.doctype.name).toBe("html"); - expect(document.doctype.publicId).toBe(""); - expect(document.doctype.systemId).toBe(""); +describe("doctype", () => { + loadLocalPage("/res/html/misc/blank.html"); + afterInitialPageLoad(page => { + test("Basic functionality", () => { + expect(page.document.compatMode).toBe("CSS1Compat"); + expect(page.document.doctype).not.toBeNull(); + expect(page.document.doctype.name).toBe("html"); + expect(page.document.doctype.publicId).toBe(""); + expect(page.document.doctype.systemId).toBe(""); + }); }); + waitForPageToLoad(); - libweb_tester.changePage("file:///res/html/misc/blank-no-doctype.html"); - - test("Quirks mode", () => { - expect(document.compatMode).toBe("BackCompat"); - expect(document.doctype).toBeNull(); + loadLocalPage("/res/html/misc/blank-no-doctype.html"); + afterInitialPageLoad(page => { + test("Quirks mode", () => { + expect(page.document.compatMode).toBe("BackCompat"); + expect(page.document.doctype).toBeNull(); + }); }); + waitForPageToLoad(); }); diff --git a/Userland/Libraries/LibWeb/Tests/DOM/document.documentElement.js b/Userland/Libraries/LibWeb/Tests/DOM/document.documentElement.js index 9ce06282de..3b4591e66e 100644 --- a/Userland/Libraries/LibWeb/Tests/DOM/document.documentElement.js +++ b/Userland/Libraries/LibWeb/Tests/DOM/document.documentElement.js @@ -1,16 +1,20 @@ -loadPage("file:///res/html/misc/blank.html"); +describe("documentElement", () => { + loadLocalPage("/res/html/misc/blank.html"); -afterInitialPageLoad(() => { - test("Basic functionality", () => { - expect(document.documentElement).not.toBeNull(); - // FIXME: Add this in once HTMLHtmlElement's constructor is implemented. - //expect(document.documentElement).toBeInstanceOf(HTMLHtmlElement); - expect(document.documentElement.nodeName).toBe("HTML"); - }); + afterInitialPageLoad(page => { + test("Basic functionality", () => { + expect(page.document.documentElement).not.toBeNull(); + // FIXME: Add this in once HTMLHtmlElement's constructor is implemented. + //expect(document.documentElement).toBeInstanceOf(HTMLHtmlElement); + expect(page.document.documentElement.nodeName).toBe("HTML"); + }); - // FIXME: Add this in once removeChild is implemented. - test.skip("Nullable", () => { - document.removeChild(document.documentElement); - expect(document.documentElement).toBeNull(); + // FIXME: Add this in once removeChild is implemented. + test.skip("Nullable", () => { + page.document.removeChild(page.document.documentElement); + expect(page.document.documentElement).toBeNull(); + }); }); + + waitForPageToLoad(); }); diff --git a/Userland/Libraries/LibWeb/Tests/DOM/mixins/NonElementParentNode.js b/Userland/Libraries/LibWeb/Tests/DOM/mixins/NonElementParentNode.js index c567c7b96a..23bcb84d2d 100644 --- a/Userland/Libraries/LibWeb/Tests/DOM/mixins/NonElementParentNode.js +++ b/Userland/Libraries/LibWeb/Tests/DOM/mixins/NonElementParentNode.js @@ -1,19 +1,22 @@ -loadPage("file:///home/anon/web-tests/Pages/ParentNode.html"); +describe("NonElementParentNode", () => { + loadLocalPage("ParentNode.html"); -afterInitialPageLoad(() => { - test("getElementById basics", () => { - const unique = document.getElementById("unique"); - expect(unique).not.toBeNull(); - expect(unique.nodeName).toBe("DIV"); - expect(unique.id).toBe("unique"); + afterInitialPageLoad(page => { + test("getElementById basics", () => { + const unique = page.document.getElementById("unique"); + expect(unique).not.toBeNull(); + expect(unique.nodeName).toBe("DIV"); + expect(unique.id).toBe("unique"); - const caseSensitive = document.getElementById("Unique"); - expect(caseSensitive).toBeNull(); + const caseSensitive = page.document.getElementById("Unique"); + expect(caseSensitive).toBeNull(); - const firstDuplicate = document.getElementById("dupeId"); - expect(firstDuplicate).not.toBeNull(); - expect(firstDuplicate.nodeName).toBe("DIV"); - expect(firstDuplicate.id).toBe("dupeId"); - expect(firstDuplicate.innerHTML).toBe("First ID"); + const firstDuplicate = page.document.getElementById("dupeId"); + expect(firstDuplicate).not.toBeNull(); + expect(firstDuplicate.nodeName).toBe("DIV"); + expect(firstDuplicate.id).toBe("dupeId"); + expect(firstDuplicate.innerHTML).toBe("First ID"); + }); }); + waitForPageToLoad(); }); diff --git a/Userland/Libraries/LibWeb/Tests/DOM/mixins/ParentNode.js b/Userland/Libraries/LibWeb/Tests/DOM/mixins/ParentNode.js index c1fa39f760..dab3c35111 100644 --- a/Userland/Libraries/LibWeb/Tests/DOM/mixins/ParentNode.js +++ b/Userland/Libraries/LibWeb/Tests/DOM/mixins/ParentNode.js @@ -1,25 +1,28 @@ -loadPage("file:///home/anon/web-tests/Pages/ParentNode.html"); +describe("ParentNode", () => { + loadLocalPage("ParentNode.html"); -afterInitialPageLoad(() => { - test("querySelector basics", () => { - const firstDuplicateElement = document.querySelector(".duplicate"); - expect(firstDuplicateElement).not.toBeNull(); - expect(firstDuplicateElement.nodeName).toBe("DIV"); - expect(firstDuplicateElement.innerHTML).toBe("First"); + afterInitialPageLoad(page => { + test("querySelector basics", () => { + const firstDuplicateElement = page.document.querySelector(".duplicate"); + expect(firstDuplicateElement).not.toBeNull(); + expect(firstDuplicateElement.nodeName).toBe("DIV"); + expect(firstDuplicateElement.innerHTML).toBe("First"); - const noElement = document.querySelector(".nonexistent"); - expect(noElement).toBeNull(); - }); + const noElement = page.document.querySelector(".nonexistent"); + expect(noElement).toBeNull(); + }); - test("querySelectorAll basics", () => { - const allDuplicates = document.querySelectorAll(".duplicate"); - expect(allDuplicates).toHaveLength(2); - expect(allDuplicates[0].nodeName).toBe("DIV"); - expect(allDuplicates[0].innerHTML).toBe("First"); - expect(allDuplicates[1].nodeName).toBe("DIV"); - expect(allDuplicates[1].innerHTML).toBe("Second"); + test("querySelectorAll basics", () => { + const allDuplicates = page.document.querySelectorAll(".duplicate"); + expect(allDuplicates).toHaveLength(2); + expect(allDuplicates[0].nodeName).toBe("DIV"); + expect(allDuplicates[0].innerHTML).toBe("First"); + expect(allDuplicates[1].nodeName).toBe("DIV"); + expect(allDuplicates[1].innerHTML).toBe("Second"); - const noElements = document.querySelectorAll(".nonexistent"); - expect(noElements).toHaveLength(0); + const noElements = page.document.querySelectorAll(".nonexistent"); + expect(noElements).toHaveLength(0); + }); }); + waitForPageToLoad(); }); diff --git a/Userland/Libraries/LibWeb/Tests/HTML/HTMLElement.js b/Userland/Libraries/LibWeb/Tests/HTML/HTMLElement.js index bdfb2d10e3..1081c6ca23 100644 --- a/Userland/Libraries/LibWeb/Tests/HTML/HTMLElement.js +++ b/Userland/Libraries/LibWeb/Tests/HTML/HTMLElement.js @@ -1,9 +1,12 @@ -loadPage("file:///res/html/misc/welcome.html"); +describe("HTMLElement", () => { + loadLocalPage("/res/html/misc/welcome.html"); -afterInitialPageLoad(() => { - test("contentEditable attribute", () => { - expect(document.body.contentEditable).toBe("inherit"); - expect(document.firstChild.nextSibling.nodeName).toBe("HTML"); - expect(document.firstChild.nextSibling.contentEditable).toBe("true"); + afterInitialPageLoad(page => { + test("contentEditable attribute", () => { + expect(page.document.body.contentEditable).toBe("inherit"); + expect(page.document.firstChild.nextSibling.nodeName).toBe("HTML"); + expect(page.document.firstChild.nextSibling.contentEditable).toBe("true"); + }); }); + waitForPageToLoad(); }); diff --git a/Userland/Libraries/LibWeb/Tests/HTML/HTMLTableElement.js b/Userland/Libraries/LibWeb/Tests/HTML/HTMLTableElement.js index 11d31e4e5c..89c2eaf8df 100644 --- a/Userland/Libraries/LibWeb/Tests/HTML/HTMLTableElement.js +++ b/Userland/Libraries/LibWeb/Tests/HTML/HTMLTableElement.js @@ -1,118 +1,121 @@ -loadPage("file:///home/anon/web-tests/Pages/Table.html"); - -afterInitialPageLoad(() => { - test("empty table attributes", () => { - let table = document.getElementById("empty-table"); - expect(table).not.toBeNull(); - - expect(table.caption).toBe(null); - expect(table.tHead).toBe(null); - expect(table.tFoot).toBe(null); - - expect(table.tBodies).toHaveLength(0); - expect(table.rows).toHaveLength(0); - }); - - test("full table attributes", () => { - let table = document.getElementById("full-table"); - expect(table).not.toBeNull(); - - expect(table.caption.nodeName).toBe("CAPTION"); - expect(table.tHead.nodeName).toBe("THEAD"); - expect(table.tFoot.nodeName).toBe("TFOOT"); - - expect(table.tBodies.length).toBe(1); - expect(table.rows.length).toBe(3); - }); - - test("create/delete caption", () => { - let table = document.createElement("table"); - expect(table).not.toBeNull(); - - expect(table.caption).toBeNull(); - table.createCaption(); - expect(table.caption).not.toBeNull(); - table.deleteCaption(); - expect(table.caption).toBeNull(); - }); - - test("create/delete thead", () => { - let table = document.createElement("table"); - expect(table).not.toBeNull(); - - expect(table.tHead).toBeNull(); - table.createTHead(); - expect(table.tHead).not.toBeNull(); - table.deleteTHead(); - expect(table.tHead).toBeNull(); - }); - - test("create/delete tfoot", () => { - let table = document.createElement("table"); - expect(table).not.toBeNull(); - - expect(table.tFoot).toBeNull(); - table.createTFoot(); - expect(table.tFoot).not.toBeNull(); - table.deleteTFoot(); - expect(table.tFoot).toBeNull(); - }); - - test("insert rows", () => { - let table = document.createElement("table"); - expect(table).not.toBeNull(); - - // We hardcode the default value in a few places, due to the WrapperGenerator's bug with default values - const defaultValue = -1; - - expect(table.rows.length).toBe(0); - - // insertRow with an index > number of rows will throw - expect(() => { - table.insertRow(1); - }).toThrow(); - - // Inserting a row into an empty table will create a <tbody> and <tr> - let rowFirst = table.insertRow(defaultValue); - rowFirst.innerText = "row_first"; - expect(table.firstElementChild.nodeName).toBe("TBODY"); - expect(table.firstElementChild.firstElementChild.nodeName).toBe("TR"); - expect(table.firstElementChild.firstElementChild.innerText).toBe("row_first"); - - for (let i = 0; i < 10; i++) { - let row = table.insertRow(defaultValue); - row.innerText = "row" + i; - } - expect(table.rows.length).toBe(11); - - // insertRow with the default value - let rowDefault = table.insertRow(defaultValue); - rowDefault.innerText = "row_default"; - expect(table.rows[table.rows.length - 1].innerText).toBe("row_default"); - }); - - test("delete rows", () => { - let table = document.createElement("table"); - expect(table).not.toBeNull(); - - // We hardcode the default value in a few places, due to the WrapperGenerator's bug with default values - const defaultValue = -1; - - // deleteRow with an index > number of rows will throw - expect(table.deleteRow).toThrow(); - - for (let i = 0; i < 10; i++) { - let row = table.insertRow(defaultValue); - row.innerText = "row" + i; - } - // deleteRow with with no argument will delete the last row - expect(table.rows[table.rows.length - 1].innerText).toBe("row9"); - table.deleteRow(defaultValue); - expect(table.rows[table.rows.length - 1].innerText).toBe("row8"); - - // We can delete a row with a specific index - expect(table.rows[5].innerText).toBe("row5"); - table.deleteRow(5); - expect(table.rows[5].innerText).toBe("row6"); +describe("HTMLTableElement", () => { + loadLocalPage("Table.html"); + + afterInitialPageLoad(page => { + test("empty table attributes", () => { + let table = page.document.getElementById("empty-table"); + expect(table).not.toBeNull(); + + expect(table.caption).toBe(null); + expect(table.tHead).toBe(null); + expect(table.tFoot).toBe(null); + + expect(table.tBodies).toHaveLength(0); + expect(table.rows).toHaveLength(0); + }); + + test("full table attributes", () => { + let table = page.document.getElementById("full-table"); + expect(table).not.toBeNull(); + + expect(table.caption.nodeName).toBe("CAPTION"); + expect(table.tHead.nodeName).toBe("THEAD"); + expect(table.tFoot.nodeName).toBe("TFOOT"); + + expect(table.tBodies.length).toBe(1); + expect(table.rows.length).toBe(3); + }); + + test("create/delete caption", () => { + let table = page.document.createElement("table"); + expect(table).not.toBeNull(); + + expect(table.caption).toBeNull(); + table.createCaption(); + expect(table.caption).not.toBeNull(); + table.deleteCaption(); + expect(table.caption).toBeNull(); + }); + + test("create/delete thead", () => { + let table = page.document.createElement("table"); + expect(table).not.toBeNull(); + + expect(table.tHead).toBeNull(); + table.createTHead(); + expect(table.tHead).not.toBeNull(); + table.deleteTHead(); + expect(table.tHead).toBeNull(); + }); + + test("create/delete tfoot", () => { + let table = page.document.createElement("table"); + expect(table).not.toBeNull(); + + expect(table.tFoot).toBeNull(); + table.createTFoot(); + expect(table.tFoot).not.toBeNull(); + table.deleteTFoot(); + expect(table.tFoot).toBeNull(); + }); + + test("insert rows", () => { + let table = page.document.createElement("table"); + expect(table).not.toBeNull(); + + // We hardcode the default value in a few places, due to the WrapperGenerator's bug with default values + const defaultValue = -1; + + expect(table.rows.length).toBe(0); + + // insertRow with an index > number of rows will throw + expect(() => { + table.insertRow(1); + }).toThrow(); + + // Inserting a row into an empty table will create a <tbody> and <tr> + let rowFirst = table.insertRow(defaultValue); + rowFirst.innerText = "row_first"; + expect(table.firstElementChild.nodeName).toBe("TBODY"); + expect(table.firstElementChild.firstElementChild.nodeName).toBe("TR"); + expect(table.firstElementChild.firstElementChild.innerText).toBe("row_first"); + + for (let i = 0; i < 10; i++) { + let row = table.insertRow(defaultValue); + row.innerText = "row" + i; + } + expect(table.rows.length).toBe(11); + + // insertRow with the default value + let rowDefault = table.insertRow(defaultValue); + rowDefault.innerText = "row_default"; + expect(table.rows[table.rows.length - 1].innerText).toBe("row_default"); + }); + + test("delete rows", () => { + let table = page.document.createElement("table"); + expect(table).not.toBeNull(); + + // We hardcode the default value in a few places, due to the WrapperGenerator's bug with default values + const defaultValue = -1; + + // deleteRow with an index > number of rows will throw + expect(table.deleteRow).toThrow(); + + for (let i = 0; i < 10; i++) { + let row = table.insertRow(defaultValue); + row.innerText = "row" + i; + } + // deleteRow with with no argument will delete the last row + expect(table.rows[table.rows.length - 1].innerText).toBe("row9"); + table.deleteRow(defaultValue); + expect(table.rows[table.rows.length - 1].innerText).toBe("row8"); + + // We can delete a row with a specific index + expect(table.rows[5].innerText).toBe("row5"); + table.deleteRow(5); + expect(table.rows[5].innerText).toBe("row6"); + }); }); + waitForPageToLoad(); }); diff --git a/Userland/Libraries/LibWeb/Tests/HTML/HTMLTemplateElement.js b/Userland/Libraries/LibWeb/Tests/HTML/HTMLTemplateElement.js index 2d668d40a6..bd33e03cb4 100644 --- a/Userland/Libraries/LibWeb/Tests/HTML/HTMLTemplateElement.js +++ b/Userland/Libraries/LibWeb/Tests/HTML/HTMLTemplateElement.js @@ -1,27 +1,30 @@ -loadPage("file:///home/anon/web-tests/Pages/Template.html"); +describe("HTMLTemplateElement", () => { + loadLocalPage("Template.html"); -afterInitialPageLoad(() => { - test("Basic functionality", () => { - const template = document.getElementById("template"); - expect(template).not.toBeNull(); + afterInitialPageLoad(page => { + test("Basic functionality", () => { + const template = page.document.getElementById("template"); + expect(template).not.toBeNull(); - // The contents of a template element are not children of the actual element. - // The document fragment is not a child of the element either. - expect(template.firstChild).toBeNull(); + // The contents of a template element are not children of the actual element. + // The document fragment is not a child of the element either. + expect(template.firstChild).toBeNull(); - // FIXME: Add this in once DocumentFragment's constructor is implemented. - //expect(template.content).toBeInstanceOf(DocumentFragment); - expect(template.content.nodeName).toBe("#document-fragment"); + // FIXME: Add this in once page.DocumentFragment's constructor is implemented. + //expect(template.content).toBeInstanceOf(page.DocumentFragment); + expect(template.content.nodeName).toBe("#document-fragment"); - const templateDiv = template.content.getElementById("templatediv"); - expect(templateDiv.nodeName).toBe("DIV"); - expect(templateDiv.textContent).toBe("Hello template!"); - }); + const templateDiv = template.content.getElementById("templatediv"); + expect(templateDiv.nodeName).toBe("DIV"); + expect(templateDiv.textContent).toBe("Hello template!"); + }); - test("Templates are inert (e.g. scripts won't run)", () => { - // The page has a template element with a script element in it. - // Templates are inert, for example, they won't run scripts. - // That script will set "templateScriptRan" to true if it ran. - expect(window.templateScriptRan).toBeUndefined(); + test("Templates are inert (e.g. scripts won't run)", () => { + // The page has a template element with a script element in it. + // Templates are inert, for example, they won't run scripts. + // That script will set "templateScriptRan" to true if it ran. + expect(page.window.templateScriptRan).toBeUndefined(); + }); }); + waitForPageToLoad(); }); diff --git a/Userland/Libraries/LibWeb/Tests/HTML/document.body.js b/Userland/Libraries/LibWeb/Tests/HTML/document.body.js index 71cf6f37de..629bc47c7b 100644 --- a/Userland/Libraries/LibWeb/Tests/HTML/document.body.js +++ b/Userland/Libraries/LibWeb/Tests/HTML/document.body.js @@ -1,55 +1,58 @@ -loadPage("file:///res/html/misc/blank.html"); - -afterInitialPageLoad(() => { - test("Basic functionality", () => { - expect(document.body).not.toBeNull(); - // FIXME: Add this in once HTMLBodyElement's constructor is implemented. - //expect(document.body).toBeInstanceOf(HTMLBodyElement); - expect(document.body.nodeName).toBe("BODY"); - }); - - // FIXME: Add this in once set_body is fully implemented. - test.skip("Setting body to a new body element", () => { - // Add something to body to see if it's gone afterwards - const p = document.createElement("p"); - document.body.appendChild(p); - - expect(document.body.firstChild).toBe(p); - - const newBody = document.createElement("body"); - document.body = newBody; - - expect(document.body).not.toBeNull(); - expect(document.body.nodeName).toBe("BODY"); - - // FIXME: Add this in once HTMLBodyElement's constructor is implemented. - //expect(document.body).toBeInstanceOf(HTMLBodyElement); - - expect(document.body.firstChild).toBeNull(); - }); - - // FIXME: Add this in once set_body is fully implemented. - test.skip("Setting body to a new frameset element", () => { - const newFrameSet = document.createElement("frameset"); - document.body = newFrameSet; - - expect(document.body).not.toBeNull(); - expect(document.body.nodeName).toBe("FRAMESET"); - - // FIXME: Add this in once HTMLFrameSetElement's constructor is implemented. - //expect(document.body).toBeInstanceOf(HTMLFrameSetElement); - }); - - // FIXME: Add this in once set_body is fully implemented. - test.skip("Setting body to an element that isn't body/frameset", () => { - expect(() => { - document.body = document.createElement("div"); - }).toThrow(DOMException); - }); - - // FIXME: Add this in once removeChild is implemented. - test.skip("Nullable", () => { - document.documentElement.removeChild(document.body); - expect(document.body).toBeNull(); +describe("body", () => { + loadLocalPage("/res/html/misc/blank.html"); + + afterInitialPageLoad(page => { + test("Basic functionality", () => { + expect(page.document.body).not.toBeNull(); + // FIXME: Add this in once HTMLBodyElement's constructor is implemented. + //expect(page.document.body).toBeInstanceOf(HTMLBodyElement); + expect(page.document.body.nodeName).toBe("BODY"); + }); + + // FIXME: Add this in once set_body is fully implemented. + test.skip("Setting body to a new body element", () => { + // Add something to body to see if it's gone afterwards + const p = page.document.createElement("p"); + page.document.body.appendChild(p); + + expect(page.document.body.firstChild).toBe(p); + + const newBody = page.document.createElement("body"); + page.document.body = newBody; + + expect(page.document.body).not.toBeNull(); + expect(page.document.body.nodeName).toBe("BODY"); + + // FIXME: Add this in once HTMLBodyElement's constructor is implemented. + //expect(page.document.body).toBeInstanceOf(HTMLBodyElement); + + expect(page.document.body.firstChild).toBeNull(); + }); + + // FIXME: Add this in once set_body is fully implemented. + test.skip("Setting body to a new frameset element", () => { + const newFrameSet = page.document.createElement("frameset"); + page.document.body = newFrameSet; + + expect(page.document.body).not.toBeNull(); + expect(page.document.body.nodeName).toBe("FRAMESET"); + + // FIXME: Add this in once HTMLFrameSetElement's constructor is implemented. + //expect(page.document.body).toBeInstanceOf(HTMLFrameSetElement); + }); + + // FIXME: Add this in once set_body is fully implemented. + test.skip("Setting body to an element that isn't body/frameset", () => { + expect(() => { + page.document.body = page.document.createElement("div"); + }).toThrow(DOMException); + }); + + // FIXME: Add this in once removeChild is implemented. + test.skip("Nullable", () => { + page.document.page.documentElement.removeChild(page.document.body); + expect(page.document.body).toBeNull(); + }); }); + waitForPageToLoad(); }); diff --git a/Userland/Libraries/LibWeb/Tests/HTML/document.head.js b/Userland/Libraries/LibWeb/Tests/HTML/document.head.js index 22c5adbc18..8bf8fd1a20 100644 --- a/Userland/Libraries/LibWeb/Tests/HTML/document.head.js +++ b/Userland/Libraries/LibWeb/Tests/HTML/document.head.js @@ -1,16 +1,19 @@ -loadPage("file:///res/html/misc/blank.html"); +describe("head", () => { + loadLocalPage("/res/html/misc/blank.html"); -afterInitialPageLoad(() => { - test("Basic functionality", () => { - expect(document.head).not.toBeNull(); - // FIXME: Add this in once HTMLHeadElement's constructor is implemented. - //expect(document.head).toBeInstanceOf(HTMLHeadElement); - expect(document.head.nodeName).toBe("HEAD"); - }); + afterInitialPageLoad(page => { + test("Basic functionality", () => { + expect(page.document.head).not.toBeNull(); + // FIXME: Add this in once HTMLHeadElement's constructor is implemented. + //expect(page.document.head).toBeInstanceOf(HTMLHeadElement); + expect(page.document.head.nodeName).toBe("HEAD"); + }); - // FIXME: Add this in once removeChild is implemented. - test.skip("Nullable", () => { - document.documentElement.removeChild(document.head); - expect(document.head).toBeNull(); + // FIXME: Add this in once removeChild is implemented. + test.skip("Nullable", () => { + page.document.documentElement.removeChild(page.document.head); + expect(page.document.head).toBeNull(); + }); }); + waitForPageToLoad(); }); diff --git a/Userland/Libraries/LibWeb/Tests/HTML/document.readyState.js b/Userland/Libraries/LibWeb/Tests/HTML/document.readyState.js index 12b6c1d8df..0126538a08 100644 --- a/Userland/Libraries/LibWeb/Tests/HTML/document.readyState.js +++ b/Userland/Libraries/LibWeb/Tests/HTML/document.readyState.js @@ -1,31 +1,34 @@ -loadPage("file:///res/html/misc/blank.html"); +describe("readyState", () => { + loadLocalPage("/res/html/misc/blank.html"); -beforeInitialPageLoad(() => { - window.events = []; + beforeInitialPageLoad(page => { + window.events = []; - document.addEventListener("readystatechange", () => { - window.events.push(document.readyState); - }); + page.document.addEventListener("readystatechange", () => { + window.events.push(page.document.readyState); + }); - document.addEventListener("DOMContentLoaded", () => { - test("Ready state should be 'interactive' when 'DOMContentLoaded' fires", () => { - expect(document.readyState).toBe("interactive"); + page.document.addEventListener("DOMContentLoaded", () => { + test("Ready state should be 'interactive' when 'DOMContentLoaded' fires", () => { + expect(page.document.readyState).toBe("interactive"); + }); }); - }); - test("Ready state should be 'loading' initially", () => { - expect(document.readyState).toBe("loading"); + test("Ready state should be 'loading' initially", () => { + expect(page.document.readyState).toBe("loading"); + }); }); -}); -afterInitialPageLoad(() => { - test("'interactive' should come before 'complete' and both should have happened", () => { - expect(window.events).toHaveLength(2); - expect(window.events[0]).toBe("interactive"); - expect(window.events[1]).toBe("complete"); - }); + afterInitialPageLoad(page => { + test("'interactive' should come before 'complete' and both should have happened", () => { + expect(page.window.events).toHaveLength(2); + expect(page.window.events[0]).toBe("interactive"); + expect(page.window.events[1]).toBe("complete"); + }); - test("Ready state should be 'complete' after loading", () => { - expect(document.readyState).toBe("complete"); + test("Ready state should be 'complete' after loading", () => { + expect(page.document.readyState).toBe("complete"); + }); }); + waitForPageToLoad(); }); diff --git a/Userland/Libraries/LibWeb/Tests/Pages/Comment.html b/Userland/Libraries/LibWeb/Tests/Pages/Comment.html index 84ae91695f..d3088da903 100644 --- a/Userland/Libraries/LibWeb/Tests/Pages/Comment.html +++ b/Userland/Libraries/LibWeb/Tests/Pages/Comment.html @@ -1,8 +1,7 @@ <!DOCTYPE html> <html> -<head> -</head> -<body> -<!--This is a comment--> -</body> + <head> </head> + <body> + <!--This is a comment--> + </body> </html> diff --git a/Userland/Libraries/LibWeb/Tests/Pages/ParentNode.html b/Userland/Libraries/LibWeb/Tests/Pages/ParentNode.html index 536b5ab35d..818326b80d 100644 --- a/Userland/Libraries/LibWeb/Tests/Pages/ParentNode.html +++ b/Userland/Libraries/LibWeb/Tests/Pages/ParentNode.html @@ -1,12 +1,11 @@ <!DOCTYPE html> <html> -<head> -</head> -<body> - <div class="duplicate">First</div> - <div class="duplicate">Second</div> - <div id="unique"></div> - <div id="dupeId">First ID</div> - <div id="dupeId">Second ID</div> -</body> + <head> </head> + <body> + <div class="duplicate">First</div> + <div class="duplicate">Second</div> + <div id="unique"></div> + <div id="dupeId">First ID</div> + <div id="dupeId">Second ID</div> + </body> </html> diff --git a/Userland/Libraries/LibWeb/Tests/Pages/Table.html b/Userland/Libraries/LibWeb/Tests/Pages/Table.html index 9e2fa1f1e6..8c32422b83 100644 --- a/Userland/Libraries/LibWeb/Tests/Pages/Table.html +++ b/Userland/Libraries/LibWeb/Tests/Pages/Table.html @@ -1,28 +1,25 @@ <!DOCTYPE html> <html> -<head> -</head> -<body> -<table id="empty-table"></table> -<table id="full-table"> - <caption>A Caption</caption> - <thead> - <th>Head Cell</th> - </thead> - <tbody> - <tr> - <td> - Body Cell - </td> - </tr> - </tbody> - <tfoot> - <tr> - <td> - Footer Cell - </td> - </tr> - </tfoot> -</table> -</body> + <head> </head> + <body> + <table id="empty-table"></table> + <table id="full-table"> + <caption> + A Caption + </caption> + <thead> + <th>Head Cell</th> + </thead> + <tbody> + <tr> + <td>Body Cell</td> + </tr> + </tbody> + <tfoot> + <tr> + <td>Footer Cell</td> + </tr> + </tfoot> + </table> + </body> </html> diff --git a/Userland/Libraries/LibWeb/Tests/Pages/Template.html b/Userland/Libraries/LibWeb/Tests/Pages/Template.html index e4478f408f..3c1abe3a79 100644 --- a/Userland/Libraries/LibWeb/Tests/Pages/Template.html +++ b/Userland/Libraries/LibWeb/Tests/Pages/Template.html @@ -1,14 +1,13 @@ <!DOCTYPE html> <html> -<head> -</head> -<body> -<template id="template"> - <div id="templatediv">Hello template!</div> - <script> - // I shouldn't be run. - window.templateScriptRan = true; - </script> -</template> -</body> + <head> </head> + <body> + <template id="template"> + <div id="templatediv">Hello template!</div> + <script> + // I shouldn't be run. + window.templateScriptRan = true; + </script> + </template> + </body> </html> diff --git a/Userland/Libraries/LibWeb/Tests/Window/Base64.js b/Userland/Libraries/LibWeb/Tests/Window/Base64.js index c272d70b74..f37c5a7c5c 100644 --- a/Userland/Libraries/LibWeb/Tests/Window/Base64.js +++ b/Userland/Libraries/LibWeb/Tests/Window/Base64.js @@ -1,19 +1,22 @@ -loadPage("file:///res/html/misc/blank.html"); +describe("Base64", () => { + loadLocalPage("/res/html/misc/blank.html"); -afterInitialPageLoad(() => { - test("atob", () => { - expect(atob("YQ==")).toBe("a"); - expect(atob("YWE=")).toBe("aa"); - expect(atob("YWFh")).toBe("aaa"); - expect(atob("YWFhYQ==")).toBe("aaaa"); - expect(atob("/w==")).toBe("\xff"); - }); + afterInitialPageLoad(page => { + test("atob", () => { + expect(page.atob("YQ==")).toBe("a"); + expect(page.atob("YWE=")).toBe("aa"); + expect(page.atob("YWFh")).toBe("aaa"); + expect(page.atob("YWFhYQ==")).toBe("aaaa"); + expect(page.atob("/w==")).toBe("\xff"); + }); - test("btoa", () => { - expect(btoa("a")).toBe("YQ=="); - expect(btoa("aa")).toBe("YWE="); - expect(btoa("aaa")).toBe("YWFh"); - expect(btoa("aaaa")).toBe("YWFhYQ=="); - expect(btoa("\xff")).toBe("/w=="); + test("btoa", () => { + expect(page.btoa("a")).toBe("YQ=="); + expect(page.btoa("aa")).toBe("YWE="); + expect(page.btoa("aaa")).toBe("YWFh"); + expect(page.btoa("aaaa")).toBe("YWFhYQ=="); + expect(page.btoa("\xff")).toBe("/w=="); + }); }); + waitForPageToLoad(); }); diff --git a/Userland/Libraries/LibWeb/Tests/Window/window.window_frames_self.js b/Userland/Libraries/LibWeb/Tests/Window/window.window_frames_self.js index 1d7799843e..7ebf169f29 100644 --- a/Userland/Libraries/LibWeb/Tests/Window/window.window_frames_self.js +++ b/Userland/Libraries/LibWeb/Tests/Window/window.window_frames_self.js @@ -1,8 +1,11 @@ -loadPage("file:///res/html/misc/blank.html"); +describe("window_frames_self", () => { + loadLocalPage("/res/html/misc/blank.html"); -afterInitialPageLoad(() => { - test("window.{window,frames,self} all return the Window object", () => { - expect(window.window).toBe(window.frames); - expect(window.window).toBe(window.self); + afterInitialPageLoad(page => { + test("window.{window,frames,self} all return the Window object", () => { + expect(page.window.window).toBe(page.window.frames); + expect(page.window.window).toBe(page.window.self); + }); }); + waitForPageToLoad(); }); diff --git a/Userland/Libraries/LibWeb/Tests/test-common.js b/Userland/Libraries/LibWeb/Tests/test-common.js deleted file mode 100644 index 7fc4f914bf..0000000000 --- a/Userland/Libraries/LibWeb/Tests/test-common.js +++ /dev/null @@ -1,31 +0,0 @@ -// NOTE: The tester loads in LibJS's test-common to prevent duplication. - -// NOTE: "window.libweb_tester" is set to a special tester object. -// See libweb_tester.d.ts for definitions. - -let __PageToLoad__; - -// This tells the tester which page to load. -// This will only be checked when we look at which page the test wants to use. -// Subsequent calls to loadPage in before/after initial load will be ignored. -let loadPage; - -let __BeforeInitialPageLoad__ = () => {}; - -// This function will be called just before loading the initial page. -// This is useful for injecting event listeners. -// Defaults to an empty function. -let beforeInitialPageLoad; - -let __AfterInitialPageLoad__ = () => {}; - -// This function will be called just after loading the initial page. -// This is where the main bulk of the tests should be. -// Defaults to an empty function. -let afterInitialPageLoad; - -(() => { - loadPage = page => (__PageToLoad__ = page); - beforeInitialPageLoad = callback => (__BeforeInitialPageLoad__ = callback); - afterInitialPageLoad = callback => (__AfterInitialPageLoad__ = callback); -})(); |