mirror of
https://github.com/rendercv/rendercv.git
synced 2026-04-17 13:33:53 -04:00
131 lines
3.4 KiB
Python
131 lines
3.4 KiB
Python
import pathlib
|
|
import shutil
|
|
import subprocess
|
|
import sys
|
|
|
|
import pytest
|
|
|
|
PROJECT_ROOT = pathlib.Path(__file__).parent.parent
|
|
|
|
|
|
@pytest.fixture
|
|
def js_runtime(tmp_path: pathlib.Path) -> str:
|
|
"""Provide a JS runtime with pyodide installed in tmp.
|
|
|
|
Why:
|
|
The Pyodide test needs a JS runtime with the pyodide npm package.
|
|
Node.js is preferred, but if unavailable, bun is used (or installed
|
|
on the fly since it's a single ~13MB download). Pyodide is installed
|
|
into tmp_path so node_modules never touches the repo.
|
|
|
|
Returns:
|
|
Absolute path to the JS runtime binary.
|
|
"""
|
|
node = shutil.which("node")
|
|
if node is not None:
|
|
# On Windows, npm is a .cmd batch script that requires shell=True
|
|
shell = sys.platform == "win32"
|
|
subprocess.run(
|
|
["npm", "init", "-y"],
|
|
cwd=tmp_path,
|
|
check=True,
|
|
capture_output=True,
|
|
timeout=120,
|
|
shell=shell,
|
|
)
|
|
subprocess.run(
|
|
["npm", "install", "pyodide"],
|
|
cwd=tmp_path,
|
|
check=True,
|
|
capture_output=True,
|
|
timeout=300,
|
|
shell=shell,
|
|
)
|
|
return node
|
|
|
|
bun = shutil.which("bun")
|
|
if bun is None:
|
|
# Install bun into tmp
|
|
bun_dir = tmp_path / "bun"
|
|
subprocess.run(
|
|
[
|
|
"bash",
|
|
"-c",
|
|
f"curl -fsSL https://bun.sh/install | BUN_INSTALL={bun_dir} bash",
|
|
],
|
|
check=True,
|
|
capture_output=True,
|
|
timeout=120,
|
|
)
|
|
bun = str(bun_dir / "bin" / "bun")
|
|
|
|
subprocess.run(
|
|
[bun, "add", "pyodide"],
|
|
cwd=tmp_path,
|
|
check=True,
|
|
capture_output=True,
|
|
timeout=120,
|
|
)
|
|
return bun
|
|
|
|
|
|
def test_rendercv_installs_in_pyodide(tmp_path: pathlib.Path, js_runtime: str) -> None:
|
|
# Build the wheel into tmp
|
|
subprocess.run(
|
|
["uv", "build", "--wheel", "--out-dir", str(tmp_path / "dist")],
|
|
cwd=PROJECT_ROOT,
|
|
check=True,
|
|
capture_output=True,
|
|
timeout=60,
|
|
)
|
|
wheel = next((tmp_path / "dist").glob("rendercv-*-py3-none-any.whl"))
|
|
|
|
# Use forward slashes so the path works on Windows too
|
|
wheel_posix_path = wheel.resolve().as_posix()
|
|
|
|
script = tmp_path / "test.mjs"
|
|
script.write_text(f"""\
|
|
import fs from "node:fs";
|
|
import {{ loadPyodide }} from "pyodide";
|
|
|
|
async function main() {{
|
|
const pyodide = await loadPyodide();
|
|
|
|
// Copy wheel into Pyodide's virtual filesystem to avoid file:// URL
|
|
// issues on Windows
|
|
const wheelData = fs.readFileSync("{wheel_posix_path}");
|
|
pyodide.FS.writeFile("/tmp/{wheel.name}", wheelData);
|
|
|
|
await pyodide.loadPackage("micropip");
|
|
|
|
await pyodide.runPythonAsync(`
|
|
import micropip
|
|
|
|
# Pre-install email-validator because micropip may not resolve
|
|
# pydantic[email] extras notation correctly
|
|
await micropip.install("email-validator")
|
|
|
|
# Install rendercv from Pyodide's virtual filesystem
|
|
await micropip.install("emfs:/tmp/{wheel.name}")
|
|
|
|
# Verify import works
|
|
import rendercv
|
|
`);
|
|
}}
|
|
|
|
main().catch(err => {{
|
|
console.error(err.message);
|
|
process.exit(1);
|
|
}});
|
|
""")
|
|
|
|
# Run test
|
|
result = subprocess.run(
|
|
[js_runtime, str(script)],
|
|
capture_output=True,
|
|
text=True,
|
|
timeout=300,
|
|
check=False,
|
|
)
|
|
assert result.returncode == 0, f"Pyodide install failed:\n{result.stderr}"
|