Skip to content

Commit 87f7664

Browse files
committed
test web module
1 parent 2358dda commit 87f7664

File tree

5 files changed

+160
-13
lines changed

5 files changed

+160
-13
lines changed

docs/source/examples/super_simple_chart.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
import { h, Component, render } from "https://unpkg.com/preact?module";
1+
import { h, render } from "https://unpkg.com/preact?module";
22
import htm from "https://unpkg.com/htm?module";
33

44
const html = htm.bind(h);
55

66
export { h as createElement, render as renderElement };
77

88
export function unmountElement(container) {
9-
preactRender(null, container);
9+
render(null, container);
1010
}
1111

1212
export function SuperSimpleChart(props) {

src/idom/web/module.py

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -57,12 +57,11 @@ def module_from_template(
5757
resolve_exports_depth: int = 5,
5858
) -> WebModule:
5959
cdn = cdn.rstrip("/")
60-
template_file = (
61-
Path(__file__).parent / "templates" / f"{template}{module_name_suffix(name)}"
62-
)
6360

61+
template_file_name = f"{template}{module_name_suffix(name)}"
62+
template_file = Path(__file__).parent / "templates" / template_file_name
6463
if not template_file.exists():
65-
raise ValueError(f"No template for {template!r} exists")
64+
raise ValueError(f"No template for {template_file_name!r} exists")
6665

6766
target_file = _web_module_path(name)
6867
if not target_file.exists():
@@ -93,9 +92,10 @@ def module_from_file(
9392
) -> WebModule:
9493
source_file = Path(file)
9594
target_file = _web_module_path(name)
96-
if target_file.exists():
97-
if target_file.resolve() != source_file.resolve():
98-
raise ValueError(f"{name!r} already exists as {target_file.resolve()}")
95+
if not source_file.exists():
96+
raise FileNotFoundError(f"Source file does not exist: {source_file}")
97+
elif target_file.exists() or target_file.is_symlink():
98+
raise FileExistsError(f"{name!r} already exists as {target_file.resolve()}")
9999
else:
100100
target_file.parent.mkdir(parents=True, exist_ok=True)
101101
target_file.symlink_to(source_file)
@@ -156,7 +156,9 @@ def export(
156156
return _make_export(web_module, export_names, fallback, allow_children)
157157
else:
158158
if web_module.export_names is not None:
159-
missing = list(set(export_names).difference(web_module.export_names))
159+
missing = list(
160+
sorted(set(export_names).difference(web_module.export_names))
161+
)
160162
if missing:
161163
raise ValueError(f"{web_module.source!r} does not export {missing!r}")
162164
return [
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { h, render } from "https://unpkg.com/preact?module";
2+
import htm from "https://unpkg.com/htm?module";
3+
4+
const html = htm.bind(h);
5+
6+
export { h as createElement, render as renderElement };
7+
8+
export function unmountElement(container) {
9+
render(null, container);
10+
}
11+
12+
export function Header1(props) {
13+
return h("h1", {id: props.id}, props.text);
14+
}
15+
16+
export function Header2(props) {
17+
return h("h2", {id: props.id}, props.text);
18+
}

tests/test_web/js_fixtures/simple-button.js

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,16 @@
1-
import react from "./react.js";
1+
import { h, render } from "https://unpkg.com/preact?module";
2+
import htm from "https://unpkg.com/htm?module";
3+
4+
const html = htm.bind(h);
5+
6+
export { h as createElement, render as renderElement };
7+
8+
export function unmountElement(container) {
9+
render(null, container);
10+
}
211

312
export function SimpleButton(props) {
4-
return react.createElement(
13+
return h(
514
"button",
615
{
716
id: props.id,

tests/test_web/test_module.py

Lines changed: 119 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,21 @@
11
from pathlib import Path
22

3+
import pytest
4+
from sanic import Sanic
5+
from selenium.webdriver.common.by import By
6+
from selenium.webdriver.support import expected_conditions
7+
from selenium.webdriver.support.ui import WebDriverWait
8+
39
import idom
10+
from idom.server.sanic import PerClientStateServer
11+
from idom.testing import ServerMountPoint
12+
from idom.web.module import NAME_SOURCE, WebModule
413

514

615
JS_FIXTURES_DIR = Path(__file__).parent / "js_fixtures"
716

817

9-
def test_that_js_module_unmount_is_called(driver, driver_wait, display):
18+
def test_that_js_module_unmount_is_called(driver, display):
1019
SomeComponent = idom.web.export(
1120
idom.web.module_from_file(
1221
"set-flag-when-unmount-is-called",
@@ -37,3 +46,112 @@ def ShowCurrentComponent():
3746

3847
# the unmount callback for the old component was called
3948
driver.find_element_by_id("unmount-flag")
49+
50+
51+
def test_module_from_url(driver):
52+
app = Sanic()
53+
54+
# instead of directing the URL to a CDN, we just point it to this static file
55+
app.static(
56+
"/simple-button.js",
57+
str(JS_FIXTURES_DIR / "simple-button.js"),
58+
content_type="text/javascript",
59+
)
60+
61+
SimpleButton = idom.web.export(
62+
idom.web.module_from_url("/simple-button.js", resolve_exports=False),
63+
"SimpleButton",
64+
)
65+
66+
@idom.component
67+
def ShowSimpleButton():
68+
return SimpleButton({"id": "my-button"})
69+
70+
with ServerMountPoint(PerClientStateServer, app=app) as mount_point:
71+
mount_point.mount(ShowSimpleButton)
72+
driver.get(mount_point.url())
73+
driver.find_element_by_id("my-button")
74+
75+
76+
def test_module_from_template_where_template_does_not_exist():
77+
with pytest.raises(ValueError, match="No template for 'does-not-exist.js'"):
78+
idom.web.module_from_template("does-not-exist", "something.js")
79+
80+
81+
def test_module_from_template(driver, display):
82+
victory = idom.web.module_from_template("react", "victory@35.4.0")
83+
VictoryBar = idom.web.export(victory, "VictoryBar")
84+
display(VictoryBar)
85+
wait = WebDriverWait(driver, 10)
86+
wait.until(
87+
expected_conditions.visibility_of_element_located(
88+
(By.CLASS_NAME, "VictoryContainer")
89+
)
90+
)
91+
92+
93+
def test_module_from_file(driver, driver_wait, display):
94+
SimpleButton = idom.web.export(
95+
idom.web.module_from_file(
96+
"simple-button", JS_FIXTURES_DIR / "simple-button.js"
97+
),
98+
"SimpleButton",
99+
)
100+
101+
is_clicked = idom.Ref(False)
102+
103+
@idom.component
104+
def ShowSimpleButton():
105+
return SimpleButton(
106+
{"id": "my-button", "onClick": lambda event: is_clicked.set_current(True)}
107+
)
108+
109+
display(ShowSimpleButton)
110+
111+
button = driver.find_element_by_id("my-button")
112+
button.click()
113+
driver_wait.until(lambda d: is_clicked.current)
114+
115+
116+
def test_module_from_file_source_conflict(tmp_path):
117+
first_file = tmp_path / "first.js"
118+
119+
with pytest.raises(FileNotFoundError, match="does not exist"):
120+
idom.web.module_from_file("temp", first_file)
121+
122+
first_file.touch()
123+
124+
idom.web.module_from_file("temp", first_file)
125+
126+
second_file = tmp_path / "second.js"
127+
second_file.touch()
128+
129+
with pytest.raises(FileExistsError, match="already exists"):
130+
idom.web.module_from_file("temp", second_file)
131+
132+
133+
def test_module_missing_exports():
134+
module = WebModule("test", NAME_SOURCE, None, {"a", "b", "c"}, None)
135+
136+
with pytest.raises(ValueError, match="does not export 'x'"):
137+
idom.web.export(module, "x")
138+
139+
with pytest.raises(ValueError, match=r"does not export \['x', 'y'\]"):
140+
idom.web.export(module, ["x", "y"])
141+
142+
143+
def test_module_exports_multiple_components(driver, display):
144+
Header1, Header2 = idom.web.export(
145+
idom.web.module_from_file(
146+
"exports-two-components", JS_FIXTURES_DIR / "exports-two-components.js"
147+
),
148+
["Header1", "Header2"],
149+
)
150+
151+
display(lambda: Header1({"id": "my-h1"}, "My Header 1"))
152+
153+
driver.find_element_by_id("my-h1")
154+
155+
display(lambda: Header2({"id": "my-h2"}, "My Header 2"))
156+
157+
driver.find_element_by_id("my-h2")

0 commit comments

Comments
 (0)