Skip to content

Commit f8d8033

Browse files
committed
Document methods and properties.
1 parent 1fd1903 commit f8d8033

7 files changed

Lines changed: 675 additions & 0 deletions

File tree

src/scrapi_sdk/browser_commands.py

Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,113 +5,298 @@
55

66

77
class BrowserCommand:
8+
"""Base class for browser commands executed after a page has loaded.
9+
10+
Browser commands allow automated interaction with a web page when
11+
:attr:`~scrapi_sdk.models.ScrapeRequest.use_browser` is set to ``True``.
12+
Commands are executed in the order they are added to the request.
13+
"""
14+
815
command_name: str
16+
"""The command name that identifies the type of browser command."""
917

1018
def to_wire(self) -> dict[str, Any]:
19+
"""Serialize this command to its API wire representation.
20+
21+
Returns:
22+
A dictionary containing the command payload for the ScrAPI API.
23+
24+
Raises:
25+
NotImplementedError: Must be implemented by subclasses.
26+
"""
1127
raise NotImplementedError
1228

1329

1430
@dataclass(slots=True)
1531
class ClickCommand(BrowserCommand):
32+
"""Browser command that clicks an element on the page.
33+
34+
Attributes:
35+
target_selector: The CSS or XPath selector used to find the element to click.
36+
command_name: The wire command name. Always ``"click"``.
37+
"""
38+
1639
target_selector: str = ""
1740
command_name: str = "click"
1841

1942
def to_wire(self) -> dict[str, Any]:
43+
"""Serialize the click command to its API wire representation.
44+
45+
Returns:
46+
A dictionary mapping ``"click"`` to the target selector.
47+
"""
2048
return {self.command_name: self.target_selector}
2149

2250

2351
@dataclass(slots=True)
2452
class ScrollCommand(BrowserCommand):
53+
"""Browser command that scrolls the page by a number of pixels.
54+
55+
Attributes:
56+
pixels: The number of pixels to scroll. Use negative values to scroll up.
57+
Defaults to 1000.
58+
command_name: The wire command name. Always ``"scroll"``.
59+
"""
60+
2561
pixels: int = 1000
2662
command_name: str = "scroll"
2763

2864
def to_wire(self) -> dict[str, Any]:
65+
"""Serialize the scroll command to its API wire representation.
66+
67+
Returns:
68+
A dictionary mapping ``"scroll"`` to the pixel count.
69+
"""
2970
return {self.command_name: self.pixels}
3071

3172

3273
@dataclass(slots=True)
3374
class WaitCommand(BrowserCommand):
75+
"""Browser command that pauses execution for a fixed duration.
76+
77+
Attributes:
78+
milliseconds: The number of milliseconds to wait. Maximum is 15000.
79+
command_name: The wire command name. Always ``"wait"``.
80+
"""
81+
3482
milliseconds: int = 0
3583
command_name: str = "wait"
3684

3785
def to_wire(self) -> dict[str, Any]:
86+
"""Serialize the wait command to its API wire representation.
87+
88+
Returns:
89+
A dictionary mapping ``"wait"`` to the millisecond duration.
90+
"""
3891
return {self.command_name: self.milliseconds}
3992

4093

4194
@dataclass(slots=True)
4295
class WaitForCommand(BrowserCommand):
96+
"""Browser command that waits until a specific element is present on the page.
97+
98+
Attributes:
99+
target_selector: The CSS or XPath selector used to find the target element.
100+
command_name: The wire command name. Always ``"wait_for"``.
101+
"""
102+
43103
target_selector: str = ""
44104
command_name: str = "wait_for"
45105

46106
def to_wire(self) -> dict[str, Any]:
107+
"""Serialize the wait-for command to its API wire representation.
108+
109+
Returns:
110+
A dictionary mapping ``"wait_for"`` to the target selector.
111+
"""
47112
return {self.command_name: self.target_selector}
48113

49114

50115
@dataclass(slots=True)
51116
class InputCommand(BrowserCommand):
117+
"""Browser command that types text into an input element.
118+
119+
Attributes:
120+
target_selector: The CSS or XPath selector used to find the input element.
121+
input_value: The text value to enter into the target element.
122+
command_name: The wire command name. Always ``"input"``.
123+
"""
124+
52125
target_selector: str = ""
53126
input_value: str = ""
54127
command_name: str = "input"
55128

56129
def to_wire(self) -> dict[str, Any]:
130+
"""Serialize the input command to its API wire representation.
131+
132+
Returns:
133+
A dictionary mapping ``"input"`` to a selector/value pair.
134+
"""
57135
return {self.command_name: {self.target_selector: self.input_value}}
58136

59137

60138
@dataclass(slots=True)
61139
class SelectCommand(BrowserCommand):
140+
"""Browser command that selects an option from a ``<select>`` element.
141+
142+
Attributes:
143+
target_selector: The CSS or XPath selector used to find the ``<select>`` element.
144+
select_value: The option value to select on the target element.
145+
command_name: The wire command name. Always ``"select"``.
146+
"""
147+
62148
target_selector: str = ""
63149
select_value: str = ""
64150
command_name: str = "select"
65151

66152
def to_wire(self) -> dict[str, Any]:
153+
"""Serialize the select command to its API wire representation.
154+
155+
Returns:
156+
A dictionary mapping ``"select"`` to a selector/value pair.
157+
"""
67158
return {self.command_name: {self.target_selector: self.select_value}}
68159

69160

70161
@dataclass(slots=True)
71162
class JavaScriptCommand(BrowserCommand):
163+
"""Browser command that evaluates a JavaScript snippet on the page.
164+
165+
Attributes:
166+
script: The JavaScript snippet to execute. Subject to a 5-second execution limit.
167+
command_name: The wire command name. Always ``"javascript"``.
168+
"""
169+
72170
script: str = ""
73171
command_name: str = "javascript"
74172

75173
def to_wire(self) -> dict[str, Any]:
174+
"""Serialize the JavaScript command to its API wire representation.
175+
176+
Returns:
177+
A dictionary mapping ``"javascript"`` to the script string.
178+
"""
76179
return {self.command_name: self.script}
77180

78181

79182
BrowserCommandType = Union[ClickCommand, ScrollCommand, WaitCommand, WaitForCommand, InputCommand, SelectCommand, JavaScriptCommand]
80183

81184

82185
class BrowserCommandList(list[BrowserCommandType]):
186+
"""An ordered list of browser commands to execute after a page has loaded.
187+
188+
Provides a fluent interface for building sequences of browser interactions.
189+
All methods return ``self`` to allow chaining.
190+
191+
Example::
192+
193+
request.browser_commands \\
194+
.click("#accept-cookies") \\
195+
.wait(500) \\
196+
.input("#search", "example query") \\
197+
.click("#submit")
198+
"""
199+
83200
def click(self, target_selector: str) -> BrowserCommandList:
201+
"""Append a click command targeting the specified element.
202+
203+
Args:
204+
target_selector: The CSS or XPath selector of the element to click.
205+
206+
Returns:
207+
This :class:`BrowserCommandList` instance for chaining.
208+
"""
84209
self.append(ClickCommand(target_selector=target_selector))
85210
return self
86211

87212
def scroll(self, pixels: int = 1000) -> BrowserCommandList:
213+
"""Append a scroll command to scroll the page by the given number of pixels.
214+
215+
Args:
216+
pixels: The number of pixels to scroll. Use a negative value to scroll
217+
up. Defaults to 1000.
218+
219+
Returns:
220+
This :class:`BrowserCommandList` instance for chaining.
221+
"""
88222
self.append(ScrollCommand(pixels=pixels))
89223
return self
90224

91225
def wait(self, milliseconds: int) -> BrowserCommandList:
226+
"""Append a wait command to pause execution for the given duration.
227+
228+
Args:
229+
milliseconds: The number of milliseconds to wait. Maximum is 15000.
230+
231+
Returns:
232+
This :class:`BrowserCommandList` instance for chaining.
233+
234+
Raises:
235+
ValueError: If ``milliseconds`` exceeds 15000.
236+
"""
92237
if milliseconds > 15000:
93238
raise ValueError("The maximum wait time is 15 seconds.")
94239

95240
self.append(WaitCommand(milliseconds=milliseconds))
96241
return self
97242

98243
def wait_for(self, target_selector: str) -> BrowserCommandList:
244+
"""Append a command that waits until the specified element is present.
245+
246+
Args:
247+
target_selector: The CSS or XPath selector of the element to wait for.
248+
249+
Returns:
250+
This :class:`BrowserCommandList` instance for chaining.
251+
"""
99252
self.append(WaitForCommand(target_selector=target_selector))
100253
return self
101254

102255
def input(self, target_selector: str, input_value: str) -> BrowserCommandList:
256+
"""Append a command that types text into the specified input element.
257+
258+
Args:
259+
target_selector: The CSS or XPath selector of the input element.
260+
input_value: The text value to enter into the element.
261+
262+
Returns:
263+
This :class:`BrowserCommandList` instance for chaining.
264+
"""
103265
self.append(InputCommand(target_selector=target_selector, input_value=input_value))
104266
return self
105267

106268
def select(self, target_selector: str, select_value: str) -> BrowserCommandList:
269+
"""Append a command that selects an option from a ``<select>`` element.
270+
271+
Args:
272+
target_selector: The CSS or XPath selector of the ``<select>`` element.
273+
select_value: The option value to select.
274+
275+
Returns:
276+
This :class:`BrowserCommandList` instance for chaining.
277+
"""
107278
self.append(SelectCommand(target_selector=target_selector, select_value=select_value))
108279
return self
109280

110281
def evaluate(self, javascript: str) -> BrowserCommandList:
282+
"""Append a command that evaluates a JavaScript snippet on the page.
283+
284+
Args:
285+
javascript: The JavaScript snippet to execute. Subject to a 5-second
286+
execution limit.
287+
288+
Returns:
289+
This :class:`BrowserCommandList` instance for chaining.
290+
"""
111291
self.append(JavaScriptCommand(script=javascript))
112292
return self
113293

114294
def to_wire(self) -> list[dict[str, Any]]:
295+
"""Serialize all commands in the list to their API wire representation.
296+
297+
Returns:
298+
A list of command dictionaries suitable for inclusion in the API request.
299+
"""
115300
return [command.to_wire() for command in self]
116301

117302

0 commit comments

Comments
 (0)