From c2a2552e4656fba2a1379af212a5cb8908c0a824 Mon Sep 17 00:00:00 2001 From: Luke Date: Mon, 17 Aug 2020 21:04:46 +0100 Subject: [PATCH] LibWeb: Add more document tests, add comment, text and mixin tests Also adds a TypeScript definition file for the test runner object. --- Libraries/LibWeb/CMakeLists.txt | 1 + Libraries/LibWeb/DOM/ParentNode.cpp | 9 +-- Libraries/LibWeb/Tests/DOM/Comment.js | 15 +++++ Libraries/LibWeb/Tests/DOM/Text.js | 7 ++- .../Tests/DOM/document.createComment.js | 13 +++++ .../DOM/document.createDocumentFragment.js | 11 ++++ .../Tests/DOM/document.createTextNode.js | 13 +++++ .../LibWeb/Tests/DOM/document.doctype.js | 4 +- .../Tests/DOM/document.documentElement.js | 10 +++- .../Tests/DOM/mixins/NonElementParentNode.js | 19 +++++++ .../LibWeb/Tests/DOM/mixins/ParentNode.js | 25 +++++++++ Libraries/LibWeb/Tests/HTML/document.body.js | 55 +++++++++++++++++++ Libraries/LibWeb/Tests/HTML/document.head.js | 16 ++++++ Libraries/LibWeb/Tests/Pages/Comment.html | 8 +++ Libraries/LibWeb/Tests/Pages/ParentNode.html | 12 ++++ Libraries/LibWeb/Tests/libweb_tester.d.ts | 16 ++++++ Libraries/LibWeb/Tests/test-common.js | 3 +- Userland/test-web.cpp | 2 +- 18 files changed, 224 insertions(+), 15 deletions(-) create mode 100644 Libraries/LibWeb/Tests/DOM/Comment.js create mode 100644 Libraries/LibWeb/Tests/DOM/document.createComment.js create mode 100644 Libraries/LibWeb/Tests/DOM/document.createDocumentFragment.js create mode 100644 Libraries/LibWeb/Tests/DOM/document.createTextNode.js create mode 100644 Libraries/LibWeb/Tests/DOM/mixins/NonElementParentNode.js create mode 100644 Libraries/LibWeb/Tests/DOM/mixins/ParentNode.js create mode 100644 Libraries/LibWeb/Tests/HTML/document.body.js create mode 100644 Libraries/LibWeb/Tests/HTML/document.head.js create mode 100644 Libraries/LibWeb/Tests/Pages/Comment.html create mode 100644 Libraries/LibWeb/Tests/Pages/ParentNode.html create mode 100644 Libraries/LibWeb/Tests/libweb_tester.d.ts diff --git a/Libraries/LibWeb/CMakeLists.txt b/Libraries/LibWeb/CMakeLists.txt index eadee3dd8e..87b2084f32 100644 --- a/Libraries/LibWeb/CMakeLists.txt +++ b/Libraries/LibWeb/CMakeLists.txt @@ -34,6 +34,7 @@ set(SOURCES DOM/EventListener.cpp DOM/EventTarget.cpp DOM/Node.cpp + DOM/ParentNode.cpp DOM/Position.cpp DOM/TagNames.cpp DOM/Text.cpp diff --git a/Libraries/LibWeb/DOM/ParentNode.cpp b/Libraries/LibWeb/DOM/ParentNode.cpp index 31a84b9017..4d668883db 100644 --- a/Libraries/LibWeb/DOM/ParentNode.cpp +++ b/Libraries/LibWeb/DOM/ParentNode.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2020, Andreas Kling + * Copyright (c) 2020, Luke Wilde * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -31,13 +31,6 @@ namespace Web::DOM { -void ParentNode::remove_all_children() -{ - while (RefPtr child = first_child()) { - remove_child(*child); - } -} - RefPtr ParentNode::query_selector(const StringView& selector_text) { auto selector = parse_selector(CSS::ParsingContext(*this), selector_text); diff --git a/Libraries/LibWeb/Tests/DOM/Comment.js b/Libraries/LibWeb/Tests/DOM/Comment.js new file mode 100644 index 0000000000..0dab522e9c --- /dev/null +++ b/Libraries/LibWeb/Tests/DOM/Comment.js @@ -0,0 +1,15 @@ +loadPage("file:///home/anon/web-tests/Pages/Comment.html"); + +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); + + expect(comment.nodeName).toBe("#comment"); + expect(comment.data).toBe("This is a comment"); + expect(comment).toHaveLength(17); + }); +}); diff --git a/Libraries/LibWeb/Tests/DOM/Text.js b/Libraries/LibWeb/Tests/DOM/Text.js index 055b05ee73..1557a59d3f 100644 --- a/Libraries/LibWeb/Tests/DOM/Text.js +++ b/Libraries/LibWeb/Tests/DOM/Text.js @@ -2,7 +2,12 @@ loadPage("file:///res/html/misc/blank.html"); afterInitialPageLoad(() => { test("Basic functionality", () => { - var title = document.getElementsByTagName("title")[0]; + const title = document.getElementsByTagName("title")[0]; + expect(title).toBeDefined(); + + // 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); diff --git a/Libraries/LibWeb/Tests/DOM/document.createComment.js b/Libraries/LibWeb/Tests/DOM/document.createComment.js new file mode 100644 index 0000000000..a60d6bfcd5 --- /dev/null +++ b/Libraries/LibWeb/Tests/DOM/document.createComment.js @@ -0,0 +1,13 @@ +loadPage("file:///res/html/misc/blank.html"); + +afterInitialPageLoad(() => { + test("Basic functionality", () => { + const comment = 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); + }); +}); diff --git a/Libraries/LibWeb/Tests/DOM/document.createDocumentFragment.js b/Libraries/LibWeb/Tests/DOM/document.createDocumentFragment.js new file mode 100644 index 0000000000..bebc137313 --- /dev/null +++ b/Libraries/LibWeb/Tests/DOM/document.createDocumentFragment.js @@ -0,0 +1,11 @@ +loadPage("file:///res/html/misc/blank.html"); + +afterInitialPageLoad(() => { + test("Basic functionality", () => { + const fragment = document.createDocumentFragment(); + + // FIXME: Add this in once DocumentFragment's constructor is implemented. + //expect(fragment).toBeInstanceOf(DocumentFragment); + expect(fragment.nodeName).toBe("#document-fragment"); + }); +}); diff --git a/Libraries/LibWeb/Tests/DOM/document.createTextNode.js b/Libraries/LibWeb/Tests/DOM/document.createTextNode.js new file mode 100644 index 0000000000..bef06a81c7 --- /dev/null +++ b/Libraries/LibWeb/Tests/DOM/document.createTextNode.js @@ -0,0 +1,13 @@ +loadPage("file:///res/html/misc/blank.html"); + +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); + }); +}); diff --git a/Libraries/LibWeb/Tests/DOM/document.doctype.js b/Libraries/LibWeb/Tests/DOM/document.doctype.js index 161da491a3..5da52014d1 100644 --- a/Libraries/LibWeb/Tests/DOM/document.doctype.js +++ b/Libraries/LibWeb/Tests/DOM/document.doctype.js @@ -3,7 +3,7 @@ loadPage("file:///res/html/misc/blank.html"); afterInitialPageLoad(() => { test("Basic functionality", () => { expect(document.compatMode).toBe("CSS1Compat"); - expect(document.doctype).not.toBe(null); + expect(document.doctype).not.toBeNull(); expect(document.doctype.name).toBe("html"); expect(document.doctype.publicId).toBe(""); expect(document.doctype.systemId).toBe(""); @@ -13,6 +13,6 @@ afterInitialPageLoad(() => { test("Quirks mode", () => { expect(document.compatMode).toBe("BackCompat"); - expect(document.doctype).toBe(null); + expect(document.doctype).toBeNull(); }); }); diff --git a/Libraries/LibWeb/Tests/DOM/document.documentElement.js b/Libraries/LibWeb/Tests/DOM/document.documentElement.js index a9b084e78e..86d885c709 100644 --- a/Libraries/LibWeb/Tests/DOM/document.documentElement.js +++ b/Libraries/LibWeb/Tests/DOM/document.documentElement.js @@ -2,7 +2,15 @@ loadPage("file:///res/html/misc/blank.html"); afterInitialPageLoad(() => { test("Basic functionality", () => { - expect(document.documentElement).not.toBe(null); + 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"); }); + + // FIXME: Add this in once removeChild is implemented. + test.skip("Nullable", () => { + document.removeChild(document.documentElement); + expect(document.documentElement).toBeNull(); + }); }); diff --git a/Libraries/LibWeb/Tests/DOM/mixins/NonElementParentNode.js b/Libraries/LibWeb/Tests/DOM/mixins/NonElementParentNode.js new file mode 100644 index 0000000000..5b269025f4 --- /dev/null +++ b/Libraries/LibWeb/Tests/DOM/mixins/NonElementParentNode.js @@ -0,0 +1,19 @@ +loadPage("file:///home/anon/web-tests/Pages/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"); + + const caseSensitive = 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"); + }); +}); diff --git a/Libraries/LibWeb/Tests/DOM/mixins/ParentNode.js b/Libraries/LibWeb/Tests/DOM/mixins/ParentNode.js new file mode 100644 index 0000000000..3558c0352f --- /dev/null +++ b/Libraries/LibWeb/Tests/DOM/mixins/ParentNode.js @@ -0,0 +1,25 @@ +loadPage("file:///home/anon/web-tests/Pages/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"); + + const noElement = 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"); + + const noElements = document.querySelectorAll(".nonexistent"); + expect(noElements).toHaveLength(0); + }); +}); diff --git a/Libraries/LibWeb/Tests/HTML/document.body.js b/Libraries/LibWeb/Tests/HTML/document.body.js new file mode 100644 index 0000000000..d099b4e49c --- /dev/null +++ b/Libraries/LibWeb/Tests/HTML/document.body.js @@ -0,0 +1,55 @@ +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(); + }); +}); diff --git a/Libraries/LibWeb/Tests/HTML/document.head.js b/Libraries/LibWeb/Tests/HTML/document.head.js new file mode 100644 index 0000000000..5d997fe3dd --- /dev/null +++ b/Libraries/LibWeb/Tests/HTML/document.head.js @@ -0,0 +1,16 @@ +loadPage("file:///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"); + }); + + // FIXME: Add this in once removeChild is implemented. + test.skip("Nullable", () => { + document.documentElement.removeChild(document.head); + expect(document.head).toBeNull(); + }); +}); diff --git a/Libraries/LibWeb/Tests/Pages/Comment.html b/Libraries/LibWeb/Tests/Pages/Comment.html new file mode 100644 index 0000000000..84ae91695f --- /dev/null +++ b/Libraries/LibWeb/Tests/Pages/Comment.html @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/Libraries/LibWeb/Tests/Pages/ParentNode.html b/Libraries/LibWeb/Tests/Pages/ParentNode.html new file mode 100644 index 0000000000..536b5ab35d --- /dev/null +++ b/Libraries/LibWeb/Tests/Pages/ParentNode.html @@ -0,0 +1,12 @@ + + + + + +
First
+
Second
+
+
First ID
+
Second ID
+ + diff --git a/Libraries/LibWeb/Tests/libweb_tester.d.ts b/Libraries/LibWeb/Tests/libweb_tester.d.ts new file mode 100644 index 0000000000..23570e70f8 --- /dev/null +++ b/Libraries/LibWeb/Tests/libweb_tester.d.ts @@ -0,0 +1,16 @@ +// NOTE: This file is only for syntax highlighting, documentation, etc. + +interface LibwebTester { + /** + * Changes the page to the specified URL. Everything afterwards will refer to the new page. + * @param url Page to load. + */ + changePage(url: string): void; +} + +interface Window { + /** + * Special test object used to ease test development for LibWeb. + */ + readonly libweb_tester: LibwebTester; +} diff --git a/Libraries/LibWeb/Tests/test-common.js b/Libraries/LibWeb/Tests/test-common.js index 54d0b830c6..f0abf3f8c5 100644 --- a/Libraries/LibWeb/Tests/test-common.js +++ b/Libraries/LibWeb/Tests/test-common.js @@ -1,8 +1,7 @@ // NOTE: The tester loads in LibJS's test-common to prevent duplication. // NOTE: "window.libweb_tester" is set to a special tester object. -// The object currently provides the following functions: -// - changePage(url) - change page to given URL. Everything afterwards will refer to the new page. +// See libweb_tester.d.ts for definitions. let __PageToLoad__; diff --git a/Userland/test-web.cpp b/Userland/test-web.cpp index bdf011e625..a83ce8ace1 100644 --- a/Userland/test-web.cpp +++ b/Userland/test-web.cpp @@ -193,7 +193,7 @@ static Vector get_test_paths(const String& test_root) Vector paths; iterate_directory_recursively(test_root, [&](const String& file_path) { - if (!file_path.ends_with("test-common.js")) + if (!file_path.ends_with("test-common.js") && !file_path.ends_with(".html") && !file_path.ends_with(".ts")) paths.append(file_path); });