Update test suite (#2181)

* pyscript.web tests pass with upytest.
* Refactor of old integration tests to new Python tests.
* Added comprehensive test suite for Python based `pyscript` module.
* Add integration tests to Makefile (and CI)
* Remove un-needed upload action.
* Ensure fails are properly logged as an array. Remove the explicit test step, since this is already built into the build step.
* Bump polyscript.

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Andrea Giammarchi <andrea.giammarchi@gmail.com>
This commit is contained in:
Nicholas Tollervey
2024-09-25 16:23:59 +01:00
committed by GitHub
parent ae66d13d57
commit 06138bbb48
91 changed files with 2390 additions and 7707 deletions

View File

@@ -0,0 +1,24 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="../../dist/core.css">
<script type="module" src="../../dist/core.js"></script>
</head>
<body>
<script type="mpy">
from pyscript import window, document, fetch, when
@when('click', '#click')
async def click(event):
text = await fetch(window.location.href).text()
document.getElementById('output').append(text)
document.documentElement.classList.add('ok')
document.getElementById('click').click()
</script>
<button id="click">click</button>
<pre id="output"></pre>
</body>
</html>

View File

@@ -0,0 +1,25 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>PyScript Next Plugin</title>
<link rel="stylesheet" href="../../dist/core.css">
<script type="module" src="../../dist/core.js"></script>
<mpy-config src="config-url/config.json"></mpy-config>
<script type="mpy">
from pyscript import config
if config["files"]["{TO}"] != "./runtime":
raise Exception("wrong config tree")
from runtime import test
</script>
<script type="mpy" worker>
from pyscript import config
if config["files"]["{TO}"] != "./runtime":
raise Exception("wrong config tree")
from runtime import test
</script>
</head>
</html>

View File

@@ -0,0 +1,7 @@
{
"files":{
"{FROM}": "./src",
"{TO}": "./runtime",
"{FROM}/test.py": "{TO}/test.py"
}
}

View File

@@ -0,0 +1,8 @@
from pyscript import RUNNING_IN_WORKER, document
classList = document.documentElement.classList
if RUNNING_IN_WORKER:
classList.add("worker")
else:
classList.add("main")

View File

@@ -0,0 +1,23 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="../../dist/core.css">
<script type="module" src="../../dist/core.js"></script>
</head>
<body>
<script type="mpy">
from pyscript import config, document
if config["type"] is "mpy":
document.documentElement.classList.add("mpy")
</script>
<script type="py">
from pyscript import config, document
if config["type"] is "py":
document.documentElement.classList.add("py")
</script>
</body>
</html>

View File

@@ -0,0 +1 @@
print("a")

View File

@@ -0,0 +1,5 @@
{
"fetch": [{
"files": ["./a.py"]
}]
}

View File

@@ -0,0 +1,95 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" href="../../../dist/core.css">
</head>
<body>
<script type="module">
import fetch from 'https://esm.run/@webreflection/fetch';
globalThis.fetch_text = await fetch("config.json").text();
globalThis.fetch_json = JSON.stringify(await fetch("config.json").json());
globalThis.fetch_buffer = new Uint8Array((await fetch("config.json").arrayBuffer())).length;
document.head.appendChild(
Object.assign(
document.createElement('script'),
{
type: 'module',
src: '../../../dist/core.js'
}
)
);
</script>
<script type="mpy" async>
import js, json
from pyscript import document, fetch
fetch_text = await (await fetch("config.json")).text()
if (fetch_text != js.fetch_text):
raise Exception("fetch_text")
fetch_text = await fetch("config.json").text()
if (fetch_text != js.fetch_text):
raise Exception("fetch_text")
fetch_json = await (await fetch("config.json")).json()
if (json.dumps(fetch_json).replace(" ", "") != js.fetch_json):
raise Exception("fetch_json")
fetch_json = await fetch("config.json").json()
if (json.dumps(fetch_json).replace(" ", "") != js.fetch_json):
raise Exception("fetch_json")
fetch_buffer = await (await fetch("config.json")).arrayBuffer()
if (len(fetch_buffer) != js.fetch_buffer):
raise Exception("fetch_buffer")
fetch_buffer = await fetch("config.json").arrayBuffer()
if (len(fetch_buffer) != js.fetch_buffer):
raise Exception("fetch_buffer")
print(await (await fetch("config.json")).bytearray())
print(await (await fetch("config.json")).blob())
if (await fetch("shenanigans.nope")).ok == False:
document.documentElement.classList.add('mpy')
</script>
<script type="py" async>
import js, json
from pyscript import document, fetch
fetch_text = await (await fetch("config.json")).text()
if (fetch_text != js.fetch_text):
raise Exception("fetch_text")
fetch_text = await fetch("config.json").text()
if (fetch_text != js.fetch_text):
raise Exception("fetch_text")
fetch_json = await (await fetch("config.json")).json()
if (json.dumps(fetch_json).replace(" ", "") != js.fetch_json):
raise Exception("fetch_json")
fetch_json = await fetch("config.json").json()
if (json.dumps(fetch_json).replace(" ", "") != js.fetch_json):
raise Exception("fetch_json")
fetch_buffer = await (await fetch("config.json")).arrayBuffer()
if (len(fetch_buffer) != js.fetch_buffer):
raise Exception("fetch_buffer")
fetch_buffer = await fetch("config.json").arrayBuffer()
if (len(fetch_buffer) != js.fetch_buffer):
raise Exception("fetch_buffer")
print(await (await fetch("config.json")).bytearray())
print(await (await fetch("config.json")).blob())
if (await fetch("shenanigans.nope")).ok == False:
document.documentElement.classList.add('py')
</script>
</body>
</html>

View File

@@ -0,0 +1,26 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>PyScript FFI</title>
<link rel="stylesheet" href="../../dist/core.css">
<script type="module" src="../../dist/core.js"></script>
</head>
<body>
<script type="mpy">
from pyscript import document
from pyscript.ffi import to_js
document.documentElement.classList.add(
to_js({"ok": "mpy"}).ok
)
</script>
<script type="py">
from pyscript import document
from pyscript.ffi import to_js
document.documentElement.classList.add(
to_js({"ok": "py"}).ok
)
</script>
</body>
</html>

View File

@@ -0,0 +1,60 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>PyScript Next Plugin Bug?</title>
<link rel="stylesheet" href="../../dist/core.css">
<script type="module">
addEventListener('mpy:done', () => {
document.documentElement.classList.add('done');
});
import { hooks } from "../../dist/core.js";
// Main
hooks.main.onReady.add((wrap, element) => {
console.log("main", "onReady");
if (location.search === '?debug') {
console.debug("main", "wrap", wrap);
console.debug("main", "element", element);
}
});
hooks.main.onBeforeRun.add(() => {
console.log("main", "onBeforeRun");
});
hooks.main.codeBeforeRun.add('print("main", "codeBeforeRun")');
hooks.main.codeAfterRun.add('print("main", "codeAfterRun")');
hooks.main.onAfterRun.add(() => {
console.log("main", "onAfterRun");
});
// Worker
hooks.worker.onReady.add((wrap, xworker) => {
console.log("worker", "onReady");
if (location.search === '?debug') {
console.debug("worker", "wrap", wrap);
console.debug("worker", "xworker", xworker);
}
});
hooks.worker.onBeforeRun.add(() => {
console.log("worker", "onBeforeRun");
});
hooks.worker.codeBeforeRun.add('print("worker", "codeBeforeRun")');
hooks.worker.codeAfterRun.add('print("worker", "codeAfterRun")');
hooks.worker.onAfterRun.add(() => {
console.log("worker", "onAfterRun");
});
</script>
</head>
<body>
<script type="mpy" async="false" worker>
from pyscript import document
print("actual code in worker")
document.documentElement.classList.add('worker')
</script>
<script type="mpy" async="false">
print("actual code in main")
</script>
</body>
</html>

View File

@@ -0,0 +1,6 @@
const { error } = console;
console.error = (...args) => {
error(...args);
document.documentElement.classList.add('errored');
};

View File

@@ -0,0 +1,16 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" href="../../../dist/core.css">
<script type="module" src="./error.js"></script>
<script type="module" src="../../../dist/core.js"></script>
</head>
<body>
<script type="mpy-editor" setup>
print("Hello Editor")
raise Exception("failure")
</script>
</body>
</html>

View File

@@ -0,0 +1,28 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="../../dist/core.css">
<script type="module">
import { storage } from '../../dist/storage.js';
const store = await storage('js-storage');
store.test = [1, 2, 3].map(String);
await store.sync();
// be sure the store is not empty before bootstrap
import('../../dist/core.js');
</script>
</head>
<body>
<script type="mpy">
from pyscript import storage, document
store = await storage("js-storage")
if ",".join(store["test"]) == "1,2,3":
document.documentElement.classList.add("ok")
</script>
</body>
</html>

View File

@@ -0,0 +1,39 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="../../dist/core.css">
<script type="module" src="../../dist/core.js"></script>
</head>
<body>
<mpy-config>
[js_modules.main]
"./js_modules.js" = "random_js"
</mpy-config>
<mpy-script>
from pyscript.js_modules.random_js import default as value
from pyscript.js_modules import random_js
from pyscript import js_modules
print("mpy", value)
print("mpy", random_js.default)
print("mpy", js_modules.random_js.default)
</mpy-script>
<py-config>
[js_modules.main]
"./js_modules.js" = "random_js"
</py-config>
<py-script>
from pyscript.js_modules.random_js import default as value
from pyscript.js_modules import random_js
from pyscript import js_modules, document
print("py", value)
print("py", random_js.default)
print("py", js_modules.random_js.default)
document.documentElement.classList.add('done')
</py-script>
</body>
</html>

View File

@@ -0,0 +1 @@
export default Math.random();

View File

@@ -0,0 +1,29 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="../../../dist/core.css">
<script type="module">
import '../../../dist/core.js';
addEventListener('py:progress', ({ detail }) => {
document.body.append(
detail,
document.createElement('br'),
);
});
</script>
</head>
<body>
<py-config>
packages = ["matplotlib"]
</py-config>
<script type="py" worker>
from pyscript import document
from sys import version
document.body.append(document.createElement('hr'), version)
document.documentElement.classList.add('ok')
</script>
</body>
</html>

View File

@@ -0,0 +1,30 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>PyScript Next</title>
<script>
addEventListener('mpy:done', () => {
document.documentElement.classList.add('done');
});
</script>
<link rel="stylesheet" href="../../dist/core.css">
<script type="module" src="../../dist/core.js"></script>
</head>
<body>
<script type="mpy">
from pyscript import display
display("Hello", "M-PyScript Main 1", append=False)
</script>
<mpy-script>
from pyscript import display
display("Hello", "M-PyScript Main 2", append=False)
</mpy-script>
<mpy-script worker>
from pyscript import display, document
display("Hello", "M-PyScript Worker", append=False)
document.documentElement.classList.add('worker')
</mpy-script>
</body>
</html>

View File

@@ -0,0 +1,14 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>PyTerminal Main</title>
<link rel="stylesheet" href="../../dist/core.css">
<script type="module" src="../../dist/core.js"></script>
<style>.xterm { padding: .5rem; }</style>
</head>
<body>
<py-script src="terminal.py" terminal></py-script>
</body>
</html>

View File

@@ -0,0 +1,15 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>PyTerminal Main</title>
<link rel="stylesheet" href="../../dist/core.css">
<script type="module" src="../../dist/core.js"></script>
<style>.xterm { padding: .5rem; }</style>
</head>
<body>
<script type="py" src="terminal.py" worker terminal></script>
<script type="mpy" src="terminal.py" worker terminal></script>
</body>
</html>

View File

@@ -0,0 +1,18 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>PyTerminal</title>
<link rel="stylesheet" href="../../dist/core.css">
<script type="module" src="../../dist/core.js"></script>
<style>.xterm { padding: .5rem; }</style>
</head>
<body>
<script type="mpy" worker terminal>
print("µpython")
import code
code.interact()
</script>
</body>
</html>

View File

@@ -0,0 +1,27 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>PyTerminal Main</title>
<link rel="stylesheet" href="../../dist/core.css">
<script type="module" src="../../dist/core.js"></script>
<style>.xterm { padding: .5rem; }</style>
</head>
<body>
<script type="mpy" worker terminal>
from pyscript import document
document.documentElement.classList.add("first")
import code
code.interact()
</script>
<script type="py" worker terminal>
from pyscript import document
document.documentElement.classList.add("second")
import code
code.interact()
</script>
</body>
</html>

View File

@@ -0,0 +1,46 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>@pyscript/core storage</title>
<link rel="stylesheet" href="../../dist/core.css">
<script type="module" src="../../dist/core.js"></script>
</head>
<body>
<script type="mpy" async>
from random import random
from pyscript import storage
store = await storage(name="test")
print("before", len(store))
for k in store:
if isinstance(store[k], memoryview):
print(f" {k}: {store[k].hex()} as hex()")
else:
print(f" {k}: {store[k]}")
store["ba"] = bytearray([0, 1, 2, 3, 4])
store["mv"] = memoryview(bytearray([5, 6, 7, 8, 9]))
store["random"] = ("some", random(), True)
store["key"] = "value"
print("now", len(store))
for k in store:
print(f" {k}: {store[k]}")
del store["key"]
# store.clear()
print("after", len(store))
for k in store:
print(f" {k}: {store[k]}")
await store.sync()
import js
js.document.documentElement.classList.add("ok")
</script>
</body>
</html>

View File

@@ -0,0 +1,8 @@
from pyscript import document
classList = document.documentElement.classList
if not __terminal__:
classList.add("error")
else:
classList.add("ok")

View File

@@ -0,0 +1,2 @@
[files]
"./test.py" = "./test.py"

View File

@@ -0,0 +1,30 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<script type="module" src="../../../dist/core.js"></script>
</head>
<body>
<script type="mpy" async>
from pyscript import create_named_worker
await create_named_worker("./worker.py", name="micropython_version", type="mpy")
</script>
<script type="mpy" config="./config.toml" async>
from test import test
await test("mpy")
</script>
<script type="py" config="./config.toml" async>
from test import test
await test("py")
</script>
<script type="py" name="pyodide_version" worker>
def pyodide_version():
import sys
return sys.version
__export__ = ['pyodide_version']
</script>
</body>
</html>

View File

@@ -0,0 +1,29 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width,initial-scale=1.0" />
<title>named workers</title>
<script type="module" src="../../../dist/core.js"></script>
</head>
<body>
<script type="mpy" async>
from pyscript import workers
await (await workers["mpy"]).greetings()
await (await workers["py"]).greetings()
</script>
<script type="mpy" worker name="mpy">
def greetings():
print("micropython")
__export__ = ['greetings']
</script>
<script type="py" worker name="py">
def greetings():
print("pyodide")
__export__ = ['greetings']
</script>
</body>
</html>

View File

@@ -0,0 +1,19 @@
from pyscript import document, workers
async def test(interpreter):
# accessed as item
named = await workers.micropython_version
version = await named.micropython_version()
document.body.append(version)
document.body.append(document.createElement("hr"))
# accessed as attribute
named = await workers["pyodide_version"]
version = await named.pyodide_version()
document.body.append(version)
document.body.append(document.createElement("hr"))
document.documentElement.classList.add(interpreter)

View File

@@ -0,0 +1,7 @@
def micropython_version():
import sys
return sys.version
__export__ = ["micropython_version"]