Skip to content

Commit

Permalink
Make arguments of Native functions optional (#1678)
Browse files Browse the repository at this point in the history
* Make node optional in Native.fromNode, defaults to window.document

* Make window optional in Native.fromWindow, defaults to window
  • Loading branch information
Jym77 authored Sep 2, 2024
1 parent eedabfa commit f26c0ec
Show file tree
Hide file tree
Showing 5 changed files with 52 additions and 8 deletions.
9 changes: 9 additions & 0 deletions .changeset/neat-papayas-vanish.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
"@siteimprove/alfa-dom": patch
---

**Added:** `Navive.fromNode` can now be called with no argument, in which case it will default to `window.document`.

It is not possible to provide options this way.

This is useful in settings where the serialisation must be injected into another context (e.g. headless browser), to avoid specifically fetching the document or using a bundler to inject `() => Native.fromNode(window.document)` to read it from inside the other context.
7 changes: 7 additions & 0 deletions .changeset/rude-hornets-buy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"@siteimprove/alfa-device": patch
---

**Added:** `Native.fromWindow` can now be called with no argument and will default to `globalThis.window`.

This is useful in injection contexts where grabbing the window beforehand to inject it is tricky, and bundling a function that wraps `() => Native.fromWindow(window)` to properly serialise it is inconvenient.
16 changes: 10 additions & 6 deletions packages/alfa-device/src/native.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,25 +20,29 @@ import type { Device, Preference } from "./index.js";
* @internal
*/
export namespace Native {
export function fromWindow(window: globalThis.Window): Device.JSON {
export function fromWindow(
myWindow: globalThis.Window = window,
): Device.JSON {
return toDevice();

function toDevice(): Device.JSON {
const {
documentElement: { clientWidth, clientHeight },
} = window.document;
} = myWindow.document;

return {
type: "screen",
viewport: {
width: clientWidth,
height: clientHeight,
orientation: window.matchMedia("(orientation: landscape)").matches
orientation: myWindow.matchMedia("(orientation: landscape)").matches
? "landscape"
: "portrait",
},
display: { resolution: window.devicePixelRatio, scan: "progressive" },
scripting: { enabled: !window.matchMedia("(scripting: none)").matches },
display: { resolution: myWindow.devicePixelRatio, scan: "progressive" },
scripting: {
enabled: !myWindow.matchMedia("(scripting: none)").matches,
},
preferences: [...toPreferences()],
};
}
Expand All @@ -62,7 +66,7 @@ export namespace Native {
// It seems we need to manually query each preference individually.
for (const name of Object.keys(preferences) as Array<Preference.Name>) {
for (const value of preferences[name]) {
if (window.matchMedia(`(${name}: ${value})`).matches) {
if (myWindow.matchMedia(`(${name}: ${value})`).matches) {
yield { name, value };
}
}
Expand Down
4 changes: 2 additions & 2 deletions packages/alfa-dom/src/native.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ export namespace Native {
): Promise<Comment.JSON>;

export async function fromNode(
node: globalThis.Document,
node?: globalThis.Document,
options?: Options,
): Promise<Document.JSON>;

Expand All @@ -78,7 +78,7 @@ export namespace Native {
): Promise<Node.JSON>;

export async function fromNode(
node: globalThis.Node,
node: globalThis.Node = globalThis.window.document,
options?: Options,
): Promise<Node.JSON> {
const { withCrossOrigin = false } = options ?? {};
Expand Down
24 changes: 24 additions & 0 deletions packages/alfa-dom/test/native.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,30 @@ test("Native.fromNode() builds a simple document", async (t) => {
);
});

test("Native.fromNode() uses global document if none is provided", async (t) => {
const html = "<div id='hello' class='foo'>Hello</div>";
// JSDOM DOMWindow is indeed not really compatible with globalThis.window but
// for the part we use here, it is sufficient.
globalThis.window = new JSDOM(html).window as any;
const actual = Node.from(await Native.fromNode()).toJSON();

t.deepEqual(
actual,
h
.document([
<html>
<head></head>
<body>
<div id="hello" class="foo">
Hello
</div>
</body>
</html>,
])
.toJSON(),
);
});

test("Native.fromNode() builds a document with element's style", async (t) => {
const actual = await makeJSON("<div style='color: red'>Hello</div>");

Expand Down

0 comments on commit f26c0ec

Please sign in to comment.