Skip to content

Commit 054fffc

Browse files
committed
Add SingleFile NODE_MODULES_DIR regression test
1 parent c277e04 commit 054fffc

2 files changed

Lines changed: 106 additions & 1 deletion

File tree

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[project]
22
name = "abx-plugins"
3-
version = "1.9.11"
3+
version = "1.9.12"
44
description = "ArchiveBox-compatible plugin suite (hooks, configs, binaries manifests)"
55
authors = [{name = "Nick Sweeting", email = "pyproject.toml+abx-plugins@archivebox.io"}]
66
requires-python = ">=3.11"
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
from __future__ import annotations
2+
3+
import os
4+
import shutil
5+
import subprocess
6+
from pathlib import Path
7+
8+
9+
REPO_ROOT = Path(__file__).resolve().parent.parent
10+
SINGLEFILE_HELPER = (
11+
REPO_ROOT
12+
/ "abx_plugins"
13+
/ "plugins"
14+
/ "singlefile"
15+
/ "singlefile_extension_save.js"
16+
)
17+
18+
19+
def test_singlefile_helper_honors_node_modules_dir(tmp_path: Path) -> None:
20+
"""singlefile helper should resolve puppeteer-core from NODE_MODULES_DIR."""
21+
node_binary = shutil.which("node")
22+
if not node_binary:
23+
raise AssertionError("Node.js is required for singlefile helper tests")
24+
25+
run_dir = tmp_path / "run"
26+
run_dir.mkdir()
27+
output_path = run_dir / "singlefile.html"
28+
29+
node_modules_dir = tmp_path / "node_modules"
30+
puppeteer_dir = node_modules_dir / "puppeteer-core"
31+
puppeteer_dir.mkdir(parents=True)
32+
(puppeteer_dir / "index.js").write_text(
33+
"module.exports = { connect: async () => ({}) };\n",
34+
encoding="utf-8",
35+
)
36+
37+
preload_path = tmp_path / "preload.js"
38+
preload_path.write_text(
39+
"""
40+
const fs = require('fs');
41+
const Module = require('module');
42+
const originalLoad = Module._load;
43+
44+
Module._load = function(request, parent, isMain) {
45+
if (request === '../chrome/chrome_utils.js') {
46+
return {
47+
installExtensionWithCache: async () => ({ name: 'singlefile', version: 'test' }),
48+
connectToPage: async () => ({
49+
browser: { disconnect: async () => {} },
50+
page: {
51+
url: async () => process.env.TEST_URL,
52+
goto: async () => {},
53+
createCDPSession: async () => ({ send: async () => {} }),
54+
target: () => ({ createCDPSession: async () => ({ send: async () => {} }) }),
55+
},
56+
}),
57+
waitForExtensionsMetadata: async () => [{ name: 'singlefile', id: 'test-extension-id' }],
58+
findExtensionMetadataByName: () => ({ id: 'test-extension-id' }),
59+
waitForExtensionTargetHandle: async () => ({}),
60+
loadExtensionFromTarget: async (extensions) => {
61+
extensions[0].dispatchAction = async () => {};
62+
},
63+
};
64+
}
65+
66+
if (request === './on_Crawl__82_singlefile_install.finite.bg.js') {
67+
return {
68+
EXTENSION: { name: 'singlefile' },
69+
saveSinglefileWithExtension: async (_page, _extension, options) => {
70+
fs.writeFileSync(options.outputPath, '<!DOCTYPE html><html><body>ok</body></html>');
71+
return options.outputPath;
72+
},
73+
};
74+
}
75+
76+
return originalLoad(request, parent, isMain);
77+
};
78+
""".lstrip(),
79+
encoding="utf-8",
80+
)
81+
82+
env = os.environ.copy()
83+
env["NODE_MODULES_DIR"] = str(node_modules_dir)
84+
env["TEST_URL"] = "https://example.com"
85+
86+
result = subprocess.run(
87+
[
88+
node_binary,
89+
"--require",
90+
str(preload_path),
91+
str(SINGLEFILE_HELPER),
92+
"--url=https://example.com",
93+
f"--output-path={output_path}",
94+
],
95+
cwd=run_dir,
96+
capture_output=True,
97+
text=True,
98+
env=env,
99+
timeout=30,
100+
)
101+
102+
assert result.returncode == 0, result.stderr
103+
assert output_path.exists(), "singlefile helper should emit the requested output file"
104+
assert "Cannot find module 'puppeteer-core'" not in result.stderr
105+
assert "[singlefile] dependencies loaded" in result.stderr

0 commit comments

Comments
 (0)