Skip to content

Commit c67c5dc

Browse files
Merge pull request pyppeteer#79 from pyppeteer/test_jshandle
add tests for jshandle
2 parents 55d1c9a + 78faeda commit c67c5dc

File tree

2 files changed

+211
-0
lines changed

2 files changed

+211
-0
lines changed

tests/conftest.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424
if _firefox:
2525
_launch_options['product'] = 'firefox'
2626

27+
CHROME = not _firefox
28+
2729

2830
def pytest_configure(config):
2931
# shim for running in pycharm - see https://youtrack.jetbrains.com/issue/PY-41295

tests/test_jshandle.py

Lines changed: 209 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,209 @@
1+
import pytest
2+
from syncer import sync
3+
4+
from pyppeteer.errors import NetworkError
5+
from tests.conftest import CHROME
6+
7+
8+
@sync
9+
async def test_handle(isolated_page, server):
10+
"""test getting handle"""
11+
p = isolated_page
12+
assert await p.evaluateHandle('window')
13+
14+
15+
@sync
16+
async def test_handle_with_arg(isolated_page, server):
17+
"""test getting handle"""
18+
p = isolated_page
19+
navigatorHandle = await p.evaluateHandle("navigator")
20+
text = await p.evaluate('e => e.userAgent', navigatorHandle)
21+
assert 'Mozilla' in text
22+
23+
24+
@sync
25+
async def test_handle_primitive_types(isolated_page, server):
26+
"""test getting handle"""
27+
p = isolated_page
28+
handle = await p.evaluateHandle('5')
29+
assert p.evaluate('e => Object.is(e, 5)', handle)
30+
31+
32+
@sync
33+
async def test_warn_nested_handles(isolated_page, server):
34+
p = isolated_page
35+
handle = await p.evaluateHandle('document.body')
36+
await p.evaluateHandle(
37+
"opts => opts.elem.querySelector('p')",
38+
handle, # todo translate {elem: handle} right now this hangs
39+
)
40+
41+
42+
@sync
43+
async def test_handle_unserializable(isolated_page, server):
44+
p = isolated_page
45+
handle = await p.evaluateHandle('Infinity')
46+
assert await p.evaluate('e => Object.is(e, Infinity)', handle) is True
47+
48+
49+
@sync
50+
async def test_js_wrappers(isolated_page, server):
51+
p = isolated_page
52+
handle = await p.evaluateHandle("""
53+
() => {
54+
window.Foo = 123;
55+
return window;
56+
}
57+
""".strip())
58+
assert await p.evaluate('e => e.Foo', handle) == 123
59+
60+
61+
@sync
62+
async def test_with_primitives(isolated_page, server):
63+
p = isolated_page
64+
handle = await p.evaluateHandle("""
65+
() => {
66+
window.Foo = 123;
67+
return window;
68+
}
69+
""".strip())
70+
assert await p.evaluate('e => e.Foo', handle) == 123
71+
72+
73+
@sync
74+
async def test_getProperty(isolated_page, server):
75+
p = isolated_page
76+
handle = await p.evaluateHandle("""
77+
() => ({
78+
one: 1,
79+
two: 2,
80+
three: 3
81+
})
82+
""".strip())
83+
handle2 = await handle.getProperty('two')
84+
assert await handle2.jsonValue() == 2
85+
86+
87+
@sync
88+
async def test_jsonValue(isolated_page, server):
89+
# should work with json values
90+
p = isolated_page
91+
handle = await p.evaluateHandle('() => ({foo: "bar"})')
92+
assert await handle.jsonValue() == {'foo': 'bar'}
93+
94+
# should not work with dates
95+
handle_date = await p.evaluateHandle(
96+
"new Date('2017-09-26T00:00:00.000Z')"
97+
)
98+
assert await handle_date.jsonValue() == {}
99+
100+
# should throw for circular objects like windows
101+
handle_window = await p.evaluateHandle('window')
102+
with pytest.raises(NetworkError) as e:
103+
await handle_window.jsonValue()
104+
if CHROME:
105+
assert e.match('Object reference chain is too long')
106+
else:
107+
assert e.match('Object is not serial')
108+
109+
110+
@sync
111+
async def test_getProperties(isolated_page, server):
112+
p = isolated_page
113+
handle = await p.evaluateHandle('({foo: "bar"})')
114+
properties = await handle.getProperties()
115+
foo = properties.get('foo')
116+
assert foo
117+
assert await foo.jsonValue() == 'bar'
118+
119+
# should return even non-own properties
120+
handle = await p.evaluateHandle(
121+
"""
122+
() => {
123+
class A {
124+
constructor() {
125+
this.a = '1';
126+
}
127+
}
128+
129+
class B extends A {
130+
constructor() {
131+
super();
132+
this.b = '2';
133+
}
134+
}
135+
136+
return new B()
137+
}
138+
""")
139+
properties = await handle.getProperties()
140+
assert await properties.get('a').jsonValue() == '1'
141+
assert await properties.get('b').jsonValue() == '2'
142+
143+
144+
@sync
145+
async def test_asElement(isolated_page, server):
146+
p = isolated_page
147+
# should work
148+
handle = await p.evaluateHandle("document.body")
149+
assert handle.asElement()
150+
151+
# should return None for non-elements
152+
handle = await p.evaluateHandle("2")
153+
element = handle.asElement()
154+
assert element is None
155+
156+
# should return ElementHandle for TextNodes
157+
await p.setContent('<div>ee!</div>')
158+
handle = await p.evaluateHandle(
159+
"document.querySelector('div').firstChild"
160+
)
161+
element = handle.asElement()
162+
assert element
163+
assert await p.evaluate(
164+
'e => e.nodeType === HTMLElement.TEXT_NODE',
165+
element
166+
)
167+
168+
169+
# should work with nulified None
170+
await p.setContent('<section>test</section>')
171+
await p.evaluate('delete Node')
172+
handle = await p.evaluateHandle(
173+
'document.querySelector("section")'
174+
)
175+
assert handle.asElement()
176+
177+
178+
@sync
179+
async def test_toString(isolated_page, server):
180+
p = isolated_page
181+
input_to_expected = {
182+
# should work for primitives
183+
'2': 'JSHandle:2',
184+
'"a"': 'JSHandle:a',
185+
# should work for complicated objects
186+
'window': 'JSHandle@object',
187+
# should work with different subtypes
188+
'(function(){})': 'JSHandle@function',
189+
'12': 'JSHandle:12',
190+
'true': 'JSHandle:True',
191+
'undefined': 'JSHandle:None',
192+
'"foo"': 'JSHandle:foo',
193+
'Symbol()': 'JSHandle@symbol',
194+
'new Set()': 'JSHandle@set',
195+
'new Map()': 'JSHandle@map',
196+
'[]': 'JSHandle@array',
197+
'null': 'JSHandle:None',
198+
'/foo/': 'JSHandle@regexp',
199+
'document.body': 'JSHandle@node',
200+
'new Date()': 'JSHandle@date',
201+
'new WeakMap()': 'JSHandle@weakmap',
202+
'new Error()': 'JSHandle@error',
203+
'new Int32Array()': 'JSHandle@typedarray',
204+
'new Proxy({}, {})': 'JSHandle@proxy',
205+
206+
}
207+
for value, expected in input_to_expected.items():
208+
handle = await p.evaluateHandle(value)
209+
assert handle.toString() == expected

0 commit comments

Comments
 (0)