const assert = require("./assert.js"); require("./_utils.js"); const { fetch } = globalThis; const tick = (ms = 10) => new Promise(($) => setTimeout($, ms)); const clear = (python) => { for (const [key, value] of Object.entries(python)) { if (typeof value === "object") python[key] = null; else python[key] = ""; } }; const patchFetch = (callback) => { Object.defineProperty(globalThis, "fetch", { configurable: true, get() { try { return callback; } finally { globalThis.fetch = fetch; } }, }); }; const { parseHTML } = require("linkedom"); const { document, window } = parseHTML("..."); globalThis.document = document; globalThis.Element = window.Element; globalThis.MutationObserver = window.MutationObserver; globalThis.XPathResult = {}; globalThis.XPathEvaluator = window.XPathEvaluator || class XPathEvaluator { createExpression() { return { evaluate: () => [] }; } }; const { registerPlugin } = require("../cjs"); (async () => { // shared 3rd party mocks const { python: pyodide, setTarget, loadPyodide, } = await import("./mocked/pyodide.mjs"); const { python: micropython } = await import("./mocked/micropython.mjs"); // shared helpers const div = document.createElement("div"); const shadowRoot = div.attachShadow({ mode: "open" }); const content = ` import sys import js js.document.currentScript.target.textContent = sys.version `; const { URL } = globalThis; globalThis.URL = function (href) { return { href }; }; globalThis.location = { href: "" }; // all tests for (const test of [ async function versionedRuntime() { document.head.innerHTML = ``; await tick(); assert(pyodide.content, content); assert(pyodide.target.tagName, "PY-SCRIPT"); }, async function basicExpectations() { document.head.innerHTML = ``; await tick(); assert(pyodide.content, content); assert(pyodide.target.tagName, "PY-SCRIPT"); }, async function foreignRuntime() { document.head.innerHTML = ``; await tick(); assert(pyodide.content, content); assert(pyodide.target.tagName, "PY-SCRIPT"); }, async function basicMicroPython() { document.head.innerHTML = ``; await tick(); assert(micropython.content, content); assert(micropython.target.tagName, "MPY-SCRIPT"); const script = document.head.firstElementChild; document.body.appendChild(script); await tick(); assert(script.nextSibling, micropython.target); micropython.target = null; }, async function exernalResourceInShadowRoot() { patchFetch(() => Promise.resolve({ text: () => Promise.resolve("OK") }), ); shadowRoot.innerHTML = ` `.trim(); await tick(); assert(pyodide.content, "OK"); assert(pyodide.target.tagName, "MY-PLUGIN"); }, async function explicitTargetNode() { setTarget(div); shadowRoot.innerHTML = ` `.trim(); await tick(); assert(pyodide.target, div); }, async function explicitTargetAsString() { setTarget("my-plugin"); shadowRoot.innerHTML = ` `.trim(); await tick(); assert(pyodide.target.tagName, "MY-PLUGIN"); }, async function jsonConfig() { const packages = {}; patchFetch(() => Promise.resolve({ json: () => ({ packages }) })); shadowRoot.innerHTML = ``; await tick(); assert(pyodide.packages, packages); }, async function tomlConfig() { const jsonPackages = JSON.stringify({ packages: { a: Math.random() }, }); patchFetch(() => Promise.resolve({ text: () => Promise.resolve(jsonPackages) }), ); shadowRoot.innerHTML = ``; // there are more promises in here let's increase the tick delay to avoid flaky tests await tick(20); assert( JSON.stringify({ packages: pyodide.packages }), jsonPackages, ); }, async function fetchConfig() { const jsonPackages = JSON.stringify({ fetch: [ { files: ["./a.py", "./b.py"] }, { from: "utils" }, { from: "/utils", files: ["c.py"] }, ], }); patchFetch(() => Promise.resolve({ arrayBuffer: () => Promise.resolve([]), text: () => Promise.resolve(jsonPackages), }), ); shadowRoot.innerHTML = ` `; await tick(10); }, async function testDefaultRuntime() { const py = await pyscript.env.py; const keys = Object.keys(loadPyodide()).join(","); assert(Object.keys(py).join(","), keys); const unique = await pyscript.env.unique; assert(Object.keys(unique).join(","), keys); }, async function pyEvents() { shadowRoot.innerHTML = ` `; await tick(20); }, ]) { await test(); clear(pyodide); clear(micropython); } globalThis.URL = URL; })();