-
Notifications
You must be signed in to change notification settings - Fork 10
Expand file tree
/
Copy pathtest_browser.py
More file actions
172 lines (138 loc) · 5.42 KB
/
test_browser.py
File metadata and controls
172 lines (138 loc) · 5.42 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
import asyncio
import logistro
import pytest
import choreographer as choreo
from choreographer import errors
from choreographer.protocol import devtools_async
# We no longer use live URLs to as not depend on the network
# allows to create a browser pool for tests
pytestmark = pytest.mark.asyncio(loop_scope="function")
_logger = logistro.getLogger(__name__)
@pytest.mark.asyncio
async def test_create_and_close_tab(browser):
_logger.info("testing...")
tab = await browser.create_tab("")
assert isinstance(tab, choreo.Tab)
assert tab.target_id in browser.tabs
await browser.close_tab(tab)
assert tab.target_id not in browser.tabs
@pytest.mark.asyncio
async def test_create_and_close_session(browser):
_logger.info("testing...")
with pytest.warns(errors.ExperimentalFeatureWarning):
session = await browser.create_session()
assert isinstance(session, devtools_async.Session)
assert session.session_id in browser.sessions
await browser.close_session(session)
assert session.session_id not in browser.sessions
# Along with testing, this could be repurposed as well to diagnose
# This deserves some thought re. difference between write_json and send_command
@pytest.mark.asyncio
async def test_broker_write_json(browser):
_logger.info("testing...")
# Test valid request with correct id and method
response = await browser._broker.write_json( # noqa: SLF001
{"id": 0, "method": "Target.getTargets"},
)
assert "result" in response and "targetInfos" in response["result"] # noqa: PT018 I like this assertion
# Test invalid method name should return error
response = await browser._broker.write_json( # noqa: SLF001
{"id": 2, "method": "dkadklqwmd"},
)
assert "error" in response
# Test missing 'id' key
with pytest.raises(
errors.MissingKeyError,
):
await browser._broker.write_json( # noqa: SLF001
{"method": "Target.getTargets"},
)
# Test missing 'method' key
with pytest.raises(
errors.MissingKeyError,
):
await browser._broker.write_json( # noqa: SLF001
{"id": 1},
)
# Test empty dictionary
with pytest.raises(
errors.MissingKeyError,
):
await browser._broker.write_json({}) # noqa: SLF001
# Test invalid parameter in the message
with pytest.raises(
RuntimeError,
):
await browser._broker.write_json( # noqa: SLF001
{"id": 0, "method": "Target.getTargets", "invalid_parameter": "kamksamdk"},
)
# Test int method should return error
with pytest.raises(
errors.MessageTypeError,
):
await browser._broker.write_json( # noqa: SLF001
{"id": 3, "method": 12345},
)
# Test non-integer id should return error
with pytest.raises(
errors.MessageTypeError,
):
await browser._broker.write_json( # noqa: SLF001
{"id": "string", "method": "Target.getTargets"},
)
@pytest.mark.asyncio
async def test_browser_send_command(browser):
_logger.info("testing...")
# Test valid request with correct command
response = await browser.send_command(command="Target.getTargets")
assert "result" in response and "targetInfos" in response["result"] # noqa: PT018 I like this assertion
# Test invalid method name should return error
response = await browser.send_command(command="dkadklqwmd")
assert "error" in response
# Test int method should return error
with pytest.raises(
errors.MessageTypeError,
):
await browser.send_command(command=12345)
@pytest.mark.asyncio
async def test_browser_send_command_with_perf(browser):
_logger.info("testing...")
perfs = []
# Run multiple commands and collect perf data
for _ in range(3):
response, perf = await browser.send_command(
command="Target.getTargets",
with_perf=True,
)
assert "result" in response and "targetInfos" in response["result"] # noqa: PT018 I like this assertion
# Validate perf is a tuple of 3 floats
assert isinstance(perf, tuple)
assert all(isinstance(t, float) for t in perf)
# Validate timing makes sense (write_start <= write_end <= read_end)
write_start, write_end, read_end = perf
assert write_start <= write_end
assert write_start <= read_end
# read_end is tough because it happens on a different processor
# and it might actually be somewhat skewed
perfs.append(perf)
await asyncio.sleep(0.1)
# Verify each perf tuple is distinct and sequential
for i in range(len(perfs) - 1):
_, _, prev_read_end = perfs[i]
next_write_start, _, _ = perfs[i + 1]
# Next command should start after previous command ended
assert prev_read_end <= next_write_start, "Commands should be sequential"
@pytest.mark.asyncio
async def test_populate_targets(browser):
_logger.info("testing...")
await browser.send_command(command="Target.createTarget", params={"url": ""})
await browser.populate_targets()
assert len(browser.tabs) >= 1
@pytest.mark.asyncio
async def test_get_tab(browser):
_logger.info("testing...")
await browser.create_tab("")
assert browser.get_tab() == next(iter(browser.tabs.values()))
await browser.create_tab()
await browser.create_tab("")
assert browser.get_tab() == next(iter(browser.tabs.values()))