@pyscript/core 0.1.22 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/core.js +2 -2
- package/dist/core.js.map +1 -1
- package/dist/error-e4fe78fd.js +2 -0
- package/dist/error-e4fe78fd.js.map +1 -0
- package/package.json +2 -2
- package/src/core.js +19 -33
- package/src/plugins/error.js +2 -2
- package/src/stdlib/pyscript/display.py +7 -0
- package/src/stdlib/pyscript.js +1 -1
- package/dist/error-87e0706c.js +0 -2
- package/dist/error-87e0706c.js.map +0 -1
- package/tests/integration/__init__.py +0 -0
- package/tests/integration/conftest.py +0 -184
- package/tests/integration/support.py +0 -1038
- package/tests/integration/test_00_support.py +0 -495
- package/tests/integration/test_01_basic.py +0 -353
- package/tests/integration/test_02_display.py +0 -452
- package/tests/integration/test_03_element.py +0 -303
- package/tests/integration/test_assets/line_plot.png +0 -0
- package/tests/integration/test_assets/tripcolor.png +0 -0
- package/tests/integration/test_async.py +0 -197
- package/tests/integration/test_event_handling.py +0 -193
- package/tests/integration/test_importmap.py +0 -66
- package/tests/integration/test_interpreter.py +0 -98
- package/tests/integration/test_plugins.py +0 -419
- package/tests/integration/test_py_config.py +0 -294
- package/tests/integration/test_py_repl.py +0 -663
- package/tests/integration/test_py_terminal.py +0 -270
- package/tests/integration/test_runtime_attributes.py +0 -64
- package/tests/integration/test_script_type.py +0 -121
- package/tests/integration/test_shadow_root.py +0 -33
- package/tests/integration/test_splashscreen.py +0 -124
- package/tests/integration/test_stdio_handling.py +0 -370
- package/tests/integration/test_style.py +0 -47
- package/tests/integration/test_warnings_and_banners.py +0 -32
- package/tests/integration/test_zz_examples.py +0 -419
- package/tests/integration/test_zzz_docs_snippets.py +0 -305
@@ -1,303 +0,0 @@
|
|
1
|
-
import pytest
|
2
|
-
|
3
|
-
from .support import PyScriptTest
|
4
|
-
|
5
|
-
|
6
|
-
class TestElement(PyScriptTest):
|
7
|
-
"""Test the Element api"""
|
8
|
-
|
9
|
-
@pytest.mark.skip("FIXME: Element interface is gone. Replace with PyDom")
|
10
|
-
def test_element_id(self):
|
11
|
-
"""Test the element id"""
|
12
|
-
self.pyscript_run(
|
13
|
-
"""
|
14
|
-
<div id="foo"></div>
|
15
|
-
<py-script>
|
16
|
-
from pyscript import Element
|
17
|
-
el = Element("foo")
|
18
|
-
print(el.id)
|
19
|
-
</py-script>
|
20
|
-
"""
|
21
|
-
)
|
22
|
-
assert self.console.log.lines[-1] == "foo"
|
23
|
-
|
24
|
-
py_terminal = self.page.wait_for_selector("py-terminal")
|
25
|
-
assert "foo" in py_terminal.inner_text()
|
26
|
-
|
27
|
-
@pytest.mark.skip("FIXME: Element interface is gone. Replace with PyDom")
|
28
|
-
def test_element_value(self):
|
29
|
-
"""Test the element value"""
|
30
|
-
self.pyscript_run(
|
31
|
-
"""
|
32
|
-
<input id="foo" value="bar">
|
33
|
-
<py-script>
|
34
|
-
from pyscript import Element
|
35
|
-
el = Element("foo")
|
36
|
-
print(el.value)
|
37
|
-
</py-script>
|
38
|
-
"""
|
39
|
-
)
|
40
|
-
assert self.console.log.lines[-1] == "bar"
|
41
|
-
|
42
|
-
py_terminal = self.page.wait_for_selector("py-terminal")
|
43
|
-
assert "bar" in py_terminal.inner_text()
|
44
|
-
|
45
|
-
@pytest.mark.skip("FIXME: Element interface is gone. Replace with PyDom")
|
46
|
-
def test_element_innerHtml(self):
|
47
|
-
"""Test the element innerHtml"""
|
48
|
-
self.pyscript_run(
|
49
|
-
"""
|
50
|
-
<div id="foo"><b>bar</b></div>
|
51
|
-
<py-script>
|
52
|
-
from pyscript import Element
|
53
|
-
el = Element("foo")
|
54
|
-
print(el.innerHtml)
|
55
|
-
</py-script>
|
56
|
-
"""
|
57
|
-
)
|
58
|
-
assert self.console.log.lines[-1] == "<b>bar</b>"
|
59
|
-
|
60
|
-
py_terminal = self.page.wait_for_selector("py-terminal")
|
61
|
-
assert "bar" in py_terminal.inner_text()
|
62
|
-
|
63
|
-
@pytest.mark.skip("FIXME: Element interface is gone. Replace with PyDom")
|
64
|
-
def test_element_write_no_append(self):
|
65
|
-
"""Test the element write"""
|
66
|
-
self.pyscript_run(
|
67
|
-
"""
|
68
|
-
<div id="foo"></div>
|
69
|
-
<py-script>
|
70
|
-
from pyscript import Element
|
71
|
-
el = Element("foo")
|
72
|
-
el.write("Hello!")
|
73
|
-
el.write("World!")
|
74
|
-
</py-script>
|
75
|
-
"""
|
76
|
-
)
|
77
|
-
div = self.page.wait_for_selector("#foo")
|
78
|
-
assert "World!" in div.inner_text()
|
79
|
-
|
80
|
-
@pytest.mark.skip("FIXME: Element interface is gone. Replace with PyDom")
|
81
|
-
def test_element_write_append(self):
|
82
|
-
"""Test the element write"""
|
83
|
-
self.pyscript_run(
|
84
|
-
"""
|
85
|
-
<div id="foo"></div>
|
86
|
-
<py-script>
|
87
|
-
from pyscript import Element
|
88
|
-
el = Element("foo")
|
89
|
-
el.write("Hello!")
|
90
|
-
el.write("World!", append=True)
|
91
|
-
</py-script>
|
92
|
-
"""
|
93
|
-
)
|
94
|
-
parent_div = self.page.wait_for_selector("#foo")
|
95
|
-
|
96
|
-
assert "Hello!" in parent_div.inner_text()
|
97
|
-
# confirm that the second write was appended
|
98
|
-
assert "Hello!<div>World!</div>" in parent_div.inner_html()
|
99
|
-
|
100
|
-
@pytest.mark.skip("FIXME: Element interface is gone. Replace with PyDom")
|
101
|
-
def test_element_clear_div(self):
|
102
|
-
"""Test the element clear"""
|
103
|
-
self.pyscript_run(
|
104
|
-
"""
|
105
|
-
<div id="foo">Hello!</div>
|
106
|
-
<py-script>
|
107
|
-
from pyscript import Element
|
108
|
-
el = Element("foo")
|
109
|
-
el.clear()
|
110
|
-
</py-script>
|
111
|
-
"""
|
112
|
-
)
|
113
|
-
div = self.page.locator("#foo")
|
114
|
-
assert div.inner_text() == ""
|
115
|
-
|
116
|
-
@pytest.mark.skip("FIXME: Element interface is gone. Replace with PyDom")
|
117
|
-
def test_element_clear_input(self):
|
118
|
-
"""Test the element clear"""
|
119
|
-
self.pyscript_run(
|
120
|
-
"""
|
121
|
-
<input id="foo" value="bar">
|
122
|
-
<py-script>
|
123
|
-
from pyscript import Element
|
124
|
-
el = Element("foo")
|
125
|
-
el.clear()
|
126
|
-
</py-script>
|
127
|
-
"""
|
128
|
-
)
|
129
|
-
input = self.page.wait_for_selector("#foo")
|
130
|
-
assert input.input_value() == ""
|
131
|
-
|
132
|
-
@pytest.mark.skip("FIXME: Element interface is gone. Replace with PyDom")
|
133
|
-
def test_element_select(self):
|
134
|
-
"""Test the element select"""
|
135
|
-
self.pyscript_run(
|
136
|
-
"""
|
137
|
-
<select id="foo">
|
138
|
-
<option value="bar">Bar</option>
|
139
|
-
</select>
|
140
|
-
<py-script>
|
141
|
-
from pyscript import Element
|
142
|
-
el = Element("foo")
|
143
|
-
js.console.log(el.select("option").value)
|
144
|
-
</py-script>
|
145
|
-
"""
|
146
|
-
)
|
147
|
-
assert self.console.log.lines[-1] == "bar"
|
148
|
-
|
149
|
-
@pytest.mark.skip("FIXME: Element interface is gone. Replace with PyDom")
|
150
|
-
def test_element_select_content(self):
|
151
|
-
"""Test the element select"""
|
152
|
-
self.pyscript_run(
|
153
|
-
"""
|
154
|
-
<template id="foo">
|
155
|
-
<div>Bar</div>
|
156
|
-
</template>
|
157
|
-
<py-script>
|
158
|
-
from pyscript import Element
|
159
|
-
el = Element("foo")
|
160
|
-
js.console.log(el.select("div", from_content=True).innerHtml)
|
161
|
-
</py-script>
|
162
|
-
"""
|
163
|
-
)
|
164
|
-
assert self.console.log.lines[-1] == "Bar"
|
165
|
-
|
166
|
-
@pytest.mark.skip("FIXME: Element interface is gone. Replace with PyDom")
|
167
|
-
def test_element_clone_no_id(self):
|
168
|
-
"""Test the element clone"""
|
169
|
-
self.pyscript_run(
|
170
|
-
"""
|
171
|
-
<div id="foo">Hello!</div>
|
172
|
-
<py-script>
|
173
|
-
from pyscript import Element
|
174
|
-
el = Element("foo")
|
175
|
-
el.clone()
|
176
|
-
</py-script>
|
177
|
-
"""
|
178
|
-
)
|
179
|
-
divs = self.page.locator("#foo")
|
180
|
-
assert divs.count() == 2
|
181
|
-
assert divs.first.inner_text() == "Hello!"
|
182
|
-
assert divs.last.inner_text() == "Hello!"
|
183
|
-
|
184
|
-
@pytest.mark.skip("FIXME: Element interface is gone. Replace with PyDom")
|
185
|
-
def test_element_clone_with_id(self):
|
186
|
-
"""Test the element clone"""
|
187
|
-
self.pyscript_run(
|
188
|
-
"""
|
189
|
-
<div id="foo">Hello!</div>
|
190
|
-
<py-script>
|
191
|
-
from pyscript import Element
|
192
|
-
el = Element("foo")
|
193
|
-
el.clone(new_id="bar")
|
194
|
-
</py-script>
|
195
|
-
"""
|
196
|
-
)
|
197
|
-
divs = self.page.locator("#foo")
|
198
|
-
assert divs.count() == 1
|
199
|
-
assert divs.inner_text() == "Hello!"
|
200
|
-
|
201
|
-
clone = self.page.locator("#bar")
|
202
|
-
assert clone.inner_text() == "Hello!"
|
203
|
-
|
204
|
-
@pytest.mark.skip("FIXME: Element interface is gone. Replace with PyDom")
|
205
|
-
def test_element_clone_to_other_element(self):
|
206
|
-
"""Test the element clone"""
|
207
|
-
self.pyscript_run(
|
208
|
-
"""
|
209
|
-
<div id="container">
|
210
|
-
<div id="bond">
|
211
|
-
Bond
|
212
|
-
</div>
|
213
|
-
<div id="james">
|
214
|
-
James
|
215
|
-
</div>
|
216
|
-
</div>
|
217
|
-
<py-script>
|
218
|
-
from pyscript import Element
|
219
|
-
|
220
|
-
bond_div = Element("bond")
|
221
|
-
james_div = Element("james")
|
222
|
-
|
223
|
-
bond_div.clone(new_id="bond-2", to=james_div)
|
224
|
-
</py-script>
|
225
|
-
"""
|
226
|
-
)
|
227
|
-
bond_divs = self.page.locator("#bond")
|
228
|
-
james_divs = self.page.locator("#james")
|
229
|
-
bond_2_divs = self.page.locator("#bond-2")
|
230
|
-
|
231
|
-
assert bond_divs.count() == 1
|
232
|
-
assert james_divs.count() == 1
|
233
|
-
assert bond_2_divs.count() == 1
|
234
|
-
|
235
|
-
container_div = self.page.locator("#container")
|
236
|
-
# Make sure that the clones are rendered in the right order
|
237
|
-
assert container_div.inner_text() == "Bond\nJames\nBond"
|
238
|
-
|
239
|
-
@pytest.mark.skip("FIXME: Element interface is gone. Replace with PyDom")
|
240
|
-
def test_element_remove_single_class(self):
|
241
|
-
"""Test the element remove_class"""
|
242
|
-
self.pyscript_run(
|
243
|
-
"""
|
244
|
-
<div id="foo" class="bar baz"></div>
|
245
|
-
<py-script>
|
246
|
-
from pyscript import Element
|
247
|
-
el = Element("foo")
|
248
|
-
el.remove_class("bar")
|
249
|
-
</py-script>
|
250
|
-
"""
|
251
|
-
)
|
252
|
-
div = self.page.locator("#foo")
|
253
|
-
assert div.get_attribute("class") == "baz"
|
254
|
-
|
255
|
-
@pytest.mark.skip("FIXME: Element interface is gone. Replace with PyDom")
|
256
|
-
def test_element_remove_multiple_classes(self):
|
257
|
-
"""Test the element remove_class"""
|
258
|
-
self.pyscript_run(
|
259
|
-
"""
|
260
|
-
<div id="foo" class="foo bar baz"></div>
|
261
|
-
<py-script>
|
262
|
-
from pyscript import Element
|
263
|
-
el = Element("foo")
|
264
|
-
el.remove_class(["foo", "baz", "bar"])
|
265
|
-
</py-script>
|
266
|
-
"""
|
267
|
-
)
|
268
|
-
div = self.page.locator("#foo")
|
269
|
-
assert div.get_attribute("class") == ""
|
270
|
-
|
271
|
-
@pytest.mark.skip("FIXME: Element interface is gone. Replace with PyDom")
|
272
|
-
def test_element_add_single_class(self):
|
273
|
-
"""Test the element add_class"""
|
274
|
-
self.pyscript_run(
|
275
|
-
"""
|
276
|
-
<style> .red { color: red; } </style>
|
277
|
-
<div id="foo">Hi!</div>
|
278
|
-
<py-script>
|
279
|
-
from pyscript import Element
|
280
|
-
el = Element("foo")
|
281
|
-
el.add_class("red")
|
282
|
-
</py-script>
|
283
|
-
"""
|
284
|
-
)
|
285
|
-
div = self.page.locator("#foo")
|
286
|
-
assert div.get_attribute("class") == "red"
|
287
|
-
|
288
|
-
@pytest.mark.skip("FIXME: Element interface is gone. Replace with PyDom")
|
289
|
-
def test_element_add_multiple_class(self):
|
290
|
-
"""Test the element add_class"""
|
291
|
-
self.pyscript_run(
|
292
|
-
"""
|
293
|
-
<style> .red { color: red; } .bold { font-weight: bold; } </style>
|
294
|
-
<div id="foo">Hi!</div>
|
295
|
-
<py-script>
|
296
|
-
from pyscript import Element
|
297
|
-
el = Element("foo")
|
298
|
-
el.add_class(["red", "bold"])
|
299
|
-
</py-script>
|
300
|
-
"""
|
301
|
-
)
|
302
|
-
div = self.page.locator("#foo")
|
303
|
-
assert div.get_attribute("class") == "red bold"
|
Binary file
|
Binary file
|
@@ -1,197 +0,0 @@
|
|
1
|
-
from .support import PyScriptTest, filter_inner_text
|
2
|
-
|
3
|
-
|
4
|
-
class TestAsync(PyScriptTest):
|
5
|
-
# ensure_future() and create_task() should behave similarly;
|
6
|
-
# we'll use the same source code to test both
|
7
|
-
coroutine_script = """
|
8
|
-
<py-script>
|
9
|
-
import js
|
10
|
-
import asyncio
|
11
|
-
js.console.log("first")
|
12
|
-
async def main():
|
13
|
-
await asyncio.sleep(1)
|
14
|
-
js.console.log("third")
|
15
|
-
asyncio.{func}(main())
|
16
|
-
js.console.log("second")
|
17
|
-
</py-script>
|
18
|
-
"""
|
19
|
-
|
20
|
-
def test_asyncio_ensure_future(self):
|
21
|
-
self.pyscript_run(self.coroutine_script.format(func="ensure_future"))
|
22
|
-
self.wait_for_console("third")
|
23
|
-
assert self.console.log.lines[-3:] == ["first", "second", "third"]
|
24
|
-
|
25
|
-
def test_asyncio_create_task(self):
|
26
|
-
self.pyscript_run(self.coroutine_script.format(func="create_task"))
|
27
|
-
self.wait_for_console("third")
|
28
|
-
assert self.console.log.lines[-3:] == ["first", "second", "third"]
|
29
|
-
|
30
|
-
def test_asyncio_gather(self):
|
31
|
-
self.pyscript_run(
|
32
|
-
"""
|
33
|
-
<py-script id="pys">
|
34
|
-
import asyncio
|
35
|
-
import js
|
36
|
-
from pyodide.ffi import to_js
|
37
|
-
|
38
|
-
async def coro(delay):
|
39
|
-
await asyncio.sleep(delay)
|
40
|
-
return(delay)
|
41
|
-
|
42
|
-
async def get_results():
|
43
|
-
results = await asyncio.gather(*[coro(d) for d in range(3,0,-1)])
|
44
|
-
js.console.log(str(results)) #Compare to string representation, not Proxy
|
45
|
-
js.console.log("DONE")
|
46
|
-
|
47
|
-
asyncio.ensure_future(get_results())
|
48
|
-
</py-script>
|
49
|
-
"""
|
50
|
-
)
|
51
|
-
self.wait_for_console("DONE")
|
52
|
-
assert self.console.log.lines[-2:] == ["[3, 2, 1]", "DONE"]
|
53
|
-
|
54
|
-
def test_multiple_async(self):
|
55
|
-
self.pyscript_run(
|
56
|
-
"""
|
57
|
-
<py-script>
|
58
|
-
import js
|
59
|
-
import asyncio
|
60
|
-
async def a_func():
|
61
|
-
for i in range(3):
|
62
|
-
js.console.log('A', i)
|
63
|
-
await asyncio.sleep(0.1)
|
64
|
-
asyncio.ensure_future(a_func())
|
65
|
-
</py-script>
|
66
|
-
|
67
|
-
<py-script>
|
68
|
-
import js
|
69
|
-
import asyncio
|
70
|
-
async def b_func():
|
71
|
-
for i in range(3):
|
72
|
-
js.console.log('B', i)
|
73
|
-
await asyncio.sleep(0.1)
|
74
|
-
js.console.log('b func done')
|
75
|
-
asyncio.ensure_future(b_func())
|
76
|
-
</py-script>
|
77
|
-
"""
|
78
|
-
)
|
79
|
-
self.wait_for_console("b func done")
|
80
|
-
assert self.console.log.lines == [
|
81
|
-
"A 0",
|
82
|
-
"B 0",
|
83
|
-
"A 1",
|
84
|
-
"B 1",
|
85
|
-
"A 2",
|
86
|
-
"B 2",
|
87
|
-
"b func done",
|
88
|
-
]
|
89
|
-
|
90
|
-
def test_multiple_async_multiple_display_targeted(self):
|
91
|
-
self.pyscript_run(
|
92
|
-
"""
|
93
|
-
<py-script id='pyA'>
|
94
|
-
from pyscript import display
|
95
|
-
import js
|
96
|
-
import asyncio
|
97
|
-
|
98
|
-
async def a_func():
|
99
|
-
for i in range(2):
|
100
|
-
display(f'A{i}', target='pyA', append=True)
|
101
|
-
await asyncio.sleep(0.1)
|
102
|
-
asyncio.ensure_future(a_func())
|
103
|
-
|
104
|
-
</py-script>
|
105
|
-
<py-script id='pyB'>
|
106
|
-
from pyscript import display
|
107
|
-
import js
|
108
|
-
import asyncio
|
109
|
-
|
110
|
-
async def a_func():
|
111
|
-
for i in range(2):
|
112
|
-
display(f'B{i}', target='pyB', append=True)
|
113
|
-
await asyncio.sleep(0.1)
|
114
|
-
js.console.log("B DONE")
|
115
|
-
|
116
|
-
asyncio.ensure_future(a_func())
|
117
|
-
</py-script>
|
118
|
-
"""
|
119
|
-
)
|
120
|
-
self.wait_for_console("B DONE")
|
121
|
-
inner_text = self.page.inner_text("html")
|
122
|
-
assert "A0\nA1\nB0\nB1" in filter_inner_text(inner_text)
|
123
|
-
|
124
|
-
def test_async_display_untargeted(self):
|
125
|
-
self.pyscript_run(
|
126
|
-
"""
|
127
|
-
<py-script>
|
128
|
-
from pyscript import display
|
129
|
-
import asyncio
|
130
|
-
import js
|
131
|
-
|
132
|
-
async def a_func():
|
133
|
-
display('A')
|
134
|
-
await asyncio.sleep(1)
|
135
|
-
js.console.log("DONE")
|
136
|
-
|
137
|
-
asyncio.ensure_future(a_func())
|
138
|
-
</py-script>
|
139
|
-
"""
|
140
|
-
)
|
141
|
-
self.wait_for_console("DONE")
|
142
|
-
assert self.page.locator("py-script").inner_text() == "A"
|
143
|
-
|
144
|
-
def test_sync_and_async_order(self):
|
145
|
-
"""
|
146
|
-
The order of execution is defined as follows:
|
147
|
-
1. first, we execute all the py-script tag in order
|
148
|
-
2. then, we start all the tasks which were scheduled with create_task
|
149
|
-
|
150
|
-
Note that tasks are started *AFTER* all py-script tags have been
|
151
|
-
executed. That's why the console.log() inside mytask1 and mytask2 are
|
152
|
-
executed after e.g. js.console.log("6").
|
153
|
-
"""
|
154
|
-
src = """
|
155
|
-
<py-script>
|
156
|
-
import js
|
157
|
-
js.console.log("1")
|
158
|
-
</py-script>
|
159
|
-
|
160
|
-
<py-script>
|
161
|
-
import asyncio
|
162
|
-
import js
|
163
|
-
|
164
|
-
async def mytask1():
|
165
|
-
js.console.log("7")
|
166
|
-
await asyncio.sleep(0)
|
167
|
-
js.console.log("9")
|
168
|
-
|
169
|
-
js.console.log("2")
|
170
|
-
asyncio.create_task(mytask1())
|
171
|
-
js.console.log("3")
|
172
|
-
</py-script>
|
173
|
-
|
174
|
-
<py-script>
|
175
|
-
import js
|
176
|
-
js.console.log("4")
|
177
|
-
</py-script>
|
178
|
-
|
179
|
-
<py-script>
|
180
|
-
import asyncio
|
181
|
-
import js
|
182
|
-
|
183
|
-
async def mytask2():
|
184
|
-
js.console.log("8")
|
185
|
-
await asyncio.sleep(0)
|
186
|
-
js.console.log("10")
|
187
|
-
js.console.log("DONE")
|
188
|
-
|
189
|
-
js.console.log("5")
|
190
|
-
asyncio.create_task(mytask2())
|
191
|
-
js.console.log("6")
|
192
|
-
</py-script>
|
193
|
-
"""
|
194
|
-
self.pyscript_run(src, wait_for_pyscript=False)
|
195
|
-
self.wait_for_console("DONE")
|
196
|
-
lines = self.console.log.lines[-11:]
|
197
|
-
assert lines == ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "DONE"]
|
@@ -1,193 +0,0 @@
|
|
1
|
-
import pytest
|
2
|
-
|
3
|
-
from .support import PyScriptTest
|
4
|
-
|
5
|
-
pytest.skip(
|
6
|
-
reason="FIXME: @when decorator missing from pyscript", allow_module_level=True
|
7
|
-
)
|
8
|
-
|
9
|
-
|
10
|
-
class TestEventHandler(PyScriptTest):
|
11
|
-
def test_when_decorator_with_event(self):
|
12
|
-
"""When the decorated function takes a single parameter,
|
13
|
-
it should be passed the event object
|
14
|
-
"""
|
15
|
-
self.pyscript_run(
|
16
|
-
"""
|
17
|
-
<button id="foo_id">foo_button</button>
|
18
|
-
<py-script>
|
19
|
-
from pyscript import when
|
20
|
-
@when("click", selector="#foo_id")
|
21
|
-
def foo(evt):
|
22
|
-
print(f"I've clicked {evt.target} with id {evt.target.id}")
|
23
|
-
</py-script>
|
24
|
-
"""
|
25
|
-
)
|
26
|
-
self.page.locator("text=foo_button").click()
|
27
|
-
console_text = self.console.all.lines
|
28
|
-
self.wait_for_console("I've clicked [object HTMLButtonElement] with id foo_id")
|
29
|
-
assert "I've clicked [object HTMLButtonElement] with id foo_id" in console_text
|
30
|
-
self.assert_no_banners()
|
31
|
-
|
32
|
-
def test_when_decorator_without_event(self):
|
33
|
-
"""When the decorated function takes no parameters (not including 'self'),
|
34
|
-
it should be called without the event object
|
35
|
-
"""
|
36
|
-
self.pyscript_run(
|
37
|
-
"""
|
38
|
-
<button id="foo_id">foo_button</button>
|
39
|
-
<py-script>
|
40
|
-
from pyscript import when
|
41
|
-
@when("click", selector="#foo_id")
|
42
|
-
def foo():
|
43
|
-
print("The button was clicked")
|
44
|
-
</py-script>
|
45
|
-
"""
|
46
|
-
)
|
47
|
-
self.page.locator("text=foo_button").click()
|
48
|
-
self.wait_for_console("The button was clicked")
|
49
|
-
assert "The button was clicked" in self.console.log.lines
|
50
|
-
self.assert_no_banners()
|
51
|
-
|
52
|
-
def test_multiple_when_decorators_with_event(self):
|
53
|
-
self.pyscript_run(
|
54
|
-
"""
|
55
|
-
<button id="foo_id">foo_button</button>
|
56
|
-
<button id="bar_id">bar_button</button>
|
57
|
-
<py-script>
|
58
|
-
from pyscript import when
|
59
|
-
@when("click", selector="#foo_id")
|
60
|
-
def foo(evt):
|
61
|
-
print(f"I've clicked {evt.target} with id {evt.target.id}")
|
62
|
-
@when("click", selector="#bar_id")
|
63
|
-
def foo(evt):
|
64
|
-
print(f"I've clicked {evt.target} with id {evt.target.id}")
|
65
|
-
</py-script>
|
66
|
-
"""
|
67
|
-
)
|
68
|
-
self.page.locator("text=foo_button").click()
|
69
|
-
console_text = self.console.all.lines
|
70
|
-
self.wait_for_console("I've clicked [object HTMLButtonElement] with id foo_id")
|
71
|
-
assert "I've clicked [object HTMLButtonElement] with id foo_id" in console_text
|
72
|
-
|
73
|
-
self.page.locator("text=bar_button").click()
|
74
|
-
console_text = self.console.all.lines
|
75
|
-
self.wait_for_console("I've clicked [object HTMLButtonElement] with id bar_id")
|
76
|
-
assert "I've clicked [object HTMLButtonElement] with id bar_id" in console_text
|
77
|
-
self.assert_no_banners()
|
78
|
-
|
79
|
-
def test_two_when_decorators(self):
|
80
|
-
"""When decorating a function twice, both should function"""
|
81
|
-
self.pyscript_run(
|
82
|
-
"""
|
83
|
-
<button id="foo_id">foo_button</button>
|
84
|
-
<button class="bar_class">bar_button</button>
|
85
|
-
<py-script>
|
86
|
-
from pyscript import when
|
87
|
-
@when("click", selector="#foo_id")
|
88
|
-
@when("mouseover", selector=".bar_class")
|
89
|
-
def foo(evt):
|
90
|
-
print(f"An event of type {evt.type} happened")
|
91
|
-
</py-script>
|
92
|
-
"""
|
93
|
-
)
|
94
|
-
self.page.locator("text=bar_button").hover()
|
95
|
-
self.page.locator("text=foo_button").click()
|
96
|
-
self.wait_for_console("An event of type click happened")
|
97
|
-
assert "An event of type mouseover happened" in self.console.log.lines
|
98
|
-
assert "An event of type click happened" in self.console.log.lines
|
99
|
-
self.assert_no_banners()
|
100
|
-
|
101
|
-
def test_two_when_decorators_same_element(self):
|
102
|
-
"""When decorating a function twice *on the same DOM element*, both should function"""
|
103
|
-
self.pyscript_run(
|
104
|
-
"""
|
105
|
-
<button id="foo_id">foo_button</button>
|
106
|
-
<py-script>
|
107
|
-
from pyscript import when
|
108
|
-
@when("click", selector="#foo_id")
|
109
|
-
@when("mouseover", selector="#foo_id")
|
110
|
-
def foo(evt):
|
111
|
-
print(f"An event of type {evt.type} happened")
|
112
|
-
</py-script>
|
113
|
-
"""
|
114
|
-
)
|
115
|
-
self.page.locator("text=foo_button").hover()
|
116
|
-
self.page.locator("text=foo_button").click()
|
117
|
-
self.wait_for_console("An event of type click happened")
|
118
|
-
assert "An event of type mouseover happened" in self.console.log.lines
|
119
|
-
assert "An event of type click happened" in self.console.log.lines
|
120
|
-
self.assert_no_banners()
|
121
|
-
|
122
|
-
def test_when_decorator_multiple_elements(self):
|
123
|
-
"""The @when decorator's selector should successfully select multiple
|
124
|
-
DOM elements
|
125
|
-
"""
|
126
|
-
self.pyscript_run(
|
127
|
-
"""
|
128
|
-
<button class="bar_class">button1</button>
|
129
|
-
<button class="bar_class">button2</button>
|
130
|
-
<py-script>
|
131
|
-
from pyscript import when
|
132
|
-
@when("click", selector=".bar_class")
|
133
|
-
def foo(evt):
|
134
|
-
print(f"{evt.target.innerText} was clicked")
|
135
|
-
</py-script>
|
136
|
-
"""
|
137
|
-
)
|
138
|
-
self.page.locator("text=button1").click()
|
139
|
-
self.page.locator("text=button2").click()
|
140
|
-
self.wait_for_console("button2 was clicked")
|
141
|
-
assert "button1 was clicked" in self.console.log.lines
|
142
|
-
assert "button2 was clicked" in self.console.log.lines
|
143
|
-
self.assert_no_banners()
|
144
|
-
|
145
|
-
def test_when_decorator_duplicate_selectors(self):
|
146
|
-
""" """
|
147
|
-
self.pyscript_run(
|
148
|
-
"""
|
149
|
-
<button id="foo_id">foo_button</button>
|
150
|
-
<py-script>
|
151
|
-
from pyscript import when
|
152
|
-
@when("click", selector="#foo_id")
|
153
|
-
@when("click", selector="#foo_id")
|
154
|
-
def foo(evt):
|
155
|
-
print(f"I've clicked {evt.target} with id {evt.target.id}")
|
156
|
-
</py-script>
|
157
|
-
"""
|
158
|
-
)
|
159
|
-
self.page.locator("text=foo_button").click()
|
160
|
-
console_text = self.console.all.lines
|
161
|
-
self.wait_for_console("I've clicked [object HTMLButtonElement] with id foo_id")
|
162
|
-
assert (
|
163
|
-
console_text.count("I've clicked [object HTMLButtonElement] with id foo_id")
|
164
|
-
== 2
|
165
|
-
)
|
166
|
-
self.assert_no_banners()
|
167
|
-
|
168
|
-
def test_when_decorator_invalid_selector(self):
|
169
|
-
"""When the selector parameter of @when is invalid, it should show an error"""
|
170
|
-
self.pyscript_run(
|
171
|
-
"""
|
172
|
-
<button id="foo_id">foo_button</button>
|
173
|
-
<py-script>
|
174
|
-
from pyscript import when
|
175
|
-
@when("click", selector="#.bad")
|
176
|
-
def foo(evt):
|
177
|
-
...
|
178
|
-
</py-script>
|
179
|
-
"""
|
180
|
-
)
|
181
|
-
self.page.locator("text=foo_button").click()
|
182
|
-
msg = "Failed to execute 'querySelectorAll' on 'Document': '#.bad' is not a valid selector."
|
183
|
-
error = self.page.wait_for_selector(".py-error")
|
184
|
-
banner_text = error.inner_text()
|
185
|
-
|
186
|
-
if msg not in banner_text:
|
187
|
-
raise AssertionError(
|
188
|
-
f"Expected message '{msg}' does not "
|
189
|
-
f"match banner text '{banner_text}'"
|
190
|
-
)
|
191
|
-
|
192
|
-
assert msg in self.console.error.lines[-1]
|
193
|
-
self.check_py_errors(msg)
|