simplex 1.0.0__tar.gz → 1.2.0__tar.gz
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.
Potentially problematic release.
This version of simplex might be problematic. Click here for more details.
- {simplex-1.0.0 → simplex-1.2.0}/PKG-INFO +11 -2
- {simplex-1.0.0 → simplex-1.2.0}/setup.py +1 -1
- {simplex-1.0.0 → simplex-1.2.0}/simplex/simplex.py +44 -21
- {simplex-1.0.0 → simplex-1.2.0}/simplex.egg-info/PKG-INFO +11 -2
- simplex-1.2.0/tests/test_local.py +206 -0
- simplex-1.0.0/tests/test_local.py +0 -111
- {simplex-1.0.0 → simplex-1.2.0}/LICENSE +0 -0
- {simplex-1.0.0 → simplex-1.2.0}/README.md +0 -0
- {simplex-1.0.0 → simplex-1.2.0}/pyproject.toml +0 -0
- {simplex-1.0.0 → simplex-1.2.0}/setup.cfg +0 -0
- {simplex-1.0.0 → simplex-1.2.0}/simplex/__init__.py +0 -0
- {simplex-1.0.0 → simplex-1.2.0}/simplex/constants.py +0 -0
- {simplex-1.0.0 → simplex-1.2.0}/simplex/utils.py +0 -0
- {simplex-1.0.0 → simplex-1.2.0}/simplex.egg-info/SOURCES.txt +0 -0
- {simplex-1.0.0 → simplex-1.2.0}/simplex.egg-info/dependency_links.txt +0 -0
- {simplex-1.0.0 → simplex-1.2.0}/simplex.egg-info/entry_points.txt +0 -0
- {simplex-1.0.0 → simplex-1.2.0}/simplex.egg-info/requires.txt +0 -0
- {simplex-1.0.0 → simplex-1.2.0}/simplex.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.2
|
|
2
2
|
Name: simplex
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.2.0
|
|
4
4
|
Summary: Official Python SDK for Simplex API
|
|
5
5
|
Home-page: https://github.com/shreyka/simplex-python
|
|
6
6
|
Author: Simplex Labs, Inc.
|
|
@@ -21,6 +21,15 @@ Requires-Dist: rich>=13.0.0
|
|
|
21
21
|
Requires-Dist: prompt_toolkit>=3.0.0
|
|
22
22
|
Requires-Dist: playwright>=1.0.0
|
|
23
23
|
Requires-Dist: Pillow>=9.0.0
|
|
24
|
+
Dynamic: author
|
|
25
|
+
Dynamic: author-email
|
|
26
|
+
Dynamic: classifier
|
|
27
|
+
Dynamic: description
|
|
28
|
+
Dynamic: description-content-type
|
|
29
|
+
Dynamic: home-page
|
|
30
|
+
Dynamic: requires-dist
|
|
31
|
+
Dynamic: requires-python
|
|
32
|
+
Dynamic: summary
|
|
24
33
|
|
|
25
34
|
# Simplex AI Python SDK
|
|
26
35
|
|
|
@@ -1,42 +1,35 @@
|
|
|
1
|
-
from playwright.sync_api import Page, sync_playwright
|
|
1
|
+
from playwright.sync_api import Page, sync_playwright, Browser
|
|
2
2
|
from PIL import Image
|
|
3
3
|
import requests
|
|
4
4
|
from typing import List
|
|
5
5
|
import io
|
|
6
|
+
import time
|
|
6
7
|
|
|
7
8
|
from .utils import center_bbox, screenshot_to_image
|
|
8
9
|
|
|
9
10
|
BASE_URL = "https://u3mvtbirxf.us-east-1.awsapprunner.com"
|
|
10
11
|
|
|
11
12
|
class Simplex:
|
|
12
|
-
def __init__(self, api_key: str,
|
|
13
|
+
def __init__(self, api_key: str, browser: Browser = None):
|
|
13
14
|
"""
|
|
14
15
|
Initialize Simplex instance
|
|
15
16
|
|
|
16
17
|
Args:
|
|
17
18
|
api_key (str): API key for authentication
|
|
18
|
-
|
|
19
|
-
a new headless browser instance will be created.
|
|
19
|
+
browser (optional): Browser instance (for Hyperbrowser integration)
|
|
20
20
|
"""
|
|
21
21
|
self.api_key = api_key
|
|
22
|
+
self.browser = browser
|
|
22
23
|
|
|
23
|
-
if
|
|
24
|
+
if browser is None:
|
|
24
25
|
self.playwright = sync_playwright().start()
|
|
25
26
|
self.browser = self.playwright.chromium.launch(headless=True)
|
|
26
|
-
self.driver = self.browser.new_page()
|
|
27
27
|
else:
|
|
28
|
-
self.driver = driver
|
|
29
|
-
self.browser = None
|
|
30
28
|
self.playwright = None
|
|
29
|
+
|
|
30
|
+
self.driver = self.browser.new_page(viewport={"width": 1280, "height": 720})
|
|
31
31
|
|
|
32
|
-
def
|
|
33
|
-
"""Cleanup Playwright resources"""
|
|
34
|
-
if self.browser:
|
|
35
|
-
self.browser.close()
|
|
36
|
-
if self.playwright:
|
|
37
|
-
self.playwright.stop()
|
|
38
|
-
|
|
39
|
-
def find_element(self, element_description: str, state: Image.Image | None = None) -> List[int]:
|
|
32
|
+
def find_element(self, element_description: str, state: Image.Image | None = None, annotate: bool = True) -> List[int]:
|
|
40
33
|
"""
|
|
41
34
|
Find an element in the screenshot using the element description
|
|
42
35
|
|
|
@@ -69,11 +62,41 @@ class Simplex:
|
|
|
69
62
|
files=files
|
|
70
63
|
)
|
|
71
64
|
|
|
65
|
+
|
|
72
66
|
# Print the results
|
|
73
67
|
print(f"Status Code: {response.status_code}")
|
|
74
68
|
if response.status_code == 200:
|
|
75
69
|
res = response.json()
|
|
76
70
|
bbox = [int(res['x1']), int(res['y1']), int(res['x2']), int(res['y2'])]
|
|
71
|
+
|
|
72
|
+
# Add overlay directly to the page if driver exists
|
|
73
|
+
if hasattr(self, 'driver') and annotate:
|
|
74
|
+
# Create and inject overlay element
|
|
75
|
+
self.driver.evaluate("""
|
|
76
|
+
(bbox) => {
|
|
77
|
+
// Remove any existing overlay
|
|
78
|
+
const existingOverlay = document.getElementById('simplex-bbox-overlay');
|
|
79
|
+
if (existingOverlay) {
|
|
80
|
+
existingOverlay.remove();
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// Create new overlay
|
|
84
|
+
const overlay = document.createElement('div');
|
|
85
|
+
overlay.id = 'simplex-bbox-overlay';
|
|
86
|
+
overlay.style.position = 'absolute';
|
|
87
|
+
overlay.style.border = '2px solid red';
|
|
88
|
+
overlay.style.left = bbox[0] + 'px';
|
|
89
|
+
overlay.style.top = bbox[1] + 'px';
|
|
90
|
+
overlay.style.width = (bbox[2] - bbox[0]) + 'px';
|
|
91
|
+
overlay.style.height = (bbox[3] - bbox[1]) + 'px';
|
|
92
|
+
overlay.style.pointerEvents = 'none';
|
|
93
|
+
overlay.style.zIndex = '10000';
|
|
94
|
+
|
|
95
|
+
document.body.appendChild(overlay);
|
|
96
|
+
}
|
|
97
|
+
""", bbox)
|
|
98
|
+
self.driver.wait_for_selector('#simplex-bbox-overlay')
|
|
99
|
+
time.sleep(5)
|
|
77
100
|
return bbox
|
|
78
101
|
else:
|
|
79
102
|
print("Error:", response.text)
|
|
@@ -130,7 +153,7 @@ class Simplex:
|
|
|
130
153
|
"""
|
|
131
154
|
self.driver.goto(url)
|
|
132
155
|
|
|
133
|
-
def execute_action(self, action: List[List[str]], state: Image.Image | None = None) -> None:
|
|
156
|
+
def execute_action(self, action: List[List[str]], state: Image.Image | None = None, annotate: bool = True) -> None:
|
|
134
157
|
"""
|
|
135
158
|
Execute an action with playwright driver
|
|
136
159
|
|
|
@@ -143,12 +166,12 @@ class Simplex:
|
|
|
143
166
|
|
|
144
167
|
try:
|
|
145
168
|
if action_type == "CLICK":
|
|
146
|
-
bbox = self.find_element(description, state)
|
|
169
|
+
bbox = self.find_element(description, state, annotate=annotate)
|
|
147
170
|
center_x, center_y = center_bbox(bbox)
|
|
148
171
|
self.driver.mouse.click(center_x, center_y)
|
|
149
172
|
|
|
150
173
|
elif action_type == "HOVER":
|
|
151
|
-
bbox = self.find_element(description, state)
|
|
174
|
+
bbox = self.find_element(description, state, annotate=annotate)
|
|
152
175
|
center_x, center_y = center_bbox(bbox)
|
|
153
176
|
self.driver.mouse.move(center_x, center_y)
|
|
154
177
|
|
|
@@ -165,14 +188,14 @@ class Simplex:
|
|
|
165
188
|
print(f"Error executing action: {e}")
|
|
166
189
|
return None
|
|
167
190
|
|
|
168
|
-
def do(self, step_description: str) -> None:
|
|
191
|
+
def do(self, step_description: str, annotate: bool = True) -> None:
|
|
169
192
|
"""
|
|
170
193
|
Execute a step description
|
|
171
194
|
"""
|
|
172
195
|
state = self.take_stable_screenshot()
|
|
173
196
|
actions = self.step_to_action(step_description, state)
|
|
174
197
|
for action in actions:
|
|
175
|
-
self.execute_action(action)
|
|
198
|
+
self.execute_action(action, annotate=annotate)
|
|
176
199
|
|
|
177
200
|
def take_stable_screenshot(self) -> Image.Image:
|
|
178
201
|
"""
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.2
|
|
2
2
|
Name: simplex
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.2.0
|
|
4
4
|
Summary: Official Python SDK for Simplex API
|
|
5
5
|
Home-page: https://github.com/shreyka/simplex-python
|
|
6
6
|
Author: Simplex Labs, Inc.
|
|
@@ -21,6 +21,15 @@ Requires-Dist: rich>=13.0.0
|
|
|
21
21
|
Requires-Dist: prompt_toolkit>=3.0.0
|
|
22
22
|
Requires-Dist: playwright>=1.0.0
|
|
23
23
|
Requires-Dist: Pillow>=9.0.0
|
|
24
|
+
Dynamic: author
|
|
25
|
+
Dynamic: author-email
|
|
26
|
+
Dynamic: classifier
|
|
27
|
+
Dynamic: description
|
|
28
|
+
Dynamic: description-content-type
|
|
29
|
+
Dynamic: home-page
|
|
30
|
+
Dynamic: requires-dist
|
|
31
|
+
Dynamic: requires-python
|
|
32
|
+
Dynamic: summary
|
|
24
33
|
|
|
25
34
|
# Simplex AI Python SDK
|
|
26
35
|
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
import os
|
|
3
|
+
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
|
4
|
+
from simplex import Simplex
|
|
5
|
+
|
|
6
|
+
from PIL import ImageDraw
|
|
7
|
+
|
|
8
|
+
from playwright.sync_api import sync_playwright
|
|
9
|
+
from PIL import Image
|
|
10
|
+
import time
|
|
11
|
+
import os
|
|
12
|
+
from hyperbrowser import Hyperbrowser
|
|
13
|
+
|
|
14
|
+
from dotenv import load_dotenv
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
load_dotenv()
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def screenshot_tests():
|
|
21
|
+
simplex = Simplex(api_key=os.getenv("SIMPLEX_API_KEY"))
|
|
22
|
+
image = "/home/ubuntu/supreme-waffle/images/netflix.png"
|
|
23
|
+
screenshot = Image.open(image)
|
|
24
|
+
|
|
25
|
+
start_time = time.time()
|
|
26
|
+
bbox = simplex.find_element("dark mode icon", screenshot)
|
|
27
|
+
end_time = time.time()
|
|
28
|
+
print(f"Time taken: {end_time - start_time} seconds")
|
|
29
|
+
print(bbox)
|
|
30
|
+
|
|
31
|
+
start_time = time.time()
|
|
32
|
+
action = simplex.step_to_action("click and enter email address", screenshot)
|
|
33
|
+
end_time = time.time()
|
|
34
|
+
print(f"Time taken: {end_time - start_time} seconds")
|
|
35
|
+
print(action)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def execute_action_test():
|
|
39
|
+
playwright = sync_playwright().start()
|
|
40
|
+
browser = playwright.chromium.launch(headless=False)
|
|
41
|
+
driver = browser.new_page()
|
|
42
|
+
|
|
43
|
+
simplex = Simplex(api_key=os.getenv("SIMPLEX_API_KEY"), driver=driver)
|
|
44
|
+
simplex.goto("https://www.netflix.com/")
|
|
45
|
+
actions = [['CLICK', 'email field'], ['TYPE', 'email address']]
|
|
46
|
+
simplex.execute_action(actions[0])
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def cgtrader_test():
|
|
50
|
+
assets = ["apple watch"]
|
|
51
|
+
urls = []
|
|
52
|
+
|
|
53
|
+
with sync_playwright() as p:
|
|
54
|
+
driver = p.chromium.launch(headless=False).new_page()
|
|
55
|
+
simplex = Simplex(api_key=os.getenv("SIMPLEX_API_KEY"), driver=driver)
|
|
56
|
+
simplex.goto("https://www.cgtrader.com/")
|
|
57
|
+
|
|
58
|
+
for asset in assets:
|
|
59
|
+
simplex.goto("https://www.cgtrader.com")
|
|
60
|
+
simplex.do(f"search for {asset}")
|
|
61
|
+
simplex.do("click on search button")
|
|
62
|
+
simplex.do(f"click on the first product")
|
|
63
|
+
driver.wait_for_timeout(3000)
|
|
64
|
+
|
|
65
|
+
urls.append(simplex.driver.url)
|
|
66
|
+
|
|
67
|
+
print(urls)
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def test_find_element():
|
|
71
|
+
simplex = Simplex(api_key=os.getenv("SIMPLEX_API_KEY"))
|
|
72
|
+
simplex.goto("https://www.cgtrader.com/")
|
|
73
|
+
|
|
74
|
+
state = simplex.take_stable_screenshot()
|
|
75
|
+
bbox = simplex.find_element("search bar")
|
|
76
|
+
|
|
77
|
+
copy_image = state.copy()
|
|
78
|
+
draw = ImageDraw.Draw(copy_image)
|
|
79
|
+
draw.rectangle(bbox, outline='red', width=2)
|
|
80
|
+
copy_image.save("annotated_state.png")
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
# Get the page HTML and device scale factor
|
|
84
|
+
html = simplex.driver.content()
|
|
85
|
+
scale_factor = simplex.driver.evaluate("window.devicePixelRatio")
|
|
86
|
+
|
|
87
|
+
# Get viewport dimensions and other relevant settings
|
|
88
|
+
viewport_size = simplex.driver.viewport_size
|
|
89
|
+
zoom_level = simplex.driver.evaluate("document.documentElement.style.zoom || 1")
|
|
90
|
+
|
|
91
|
+
# Debug print
|
|
92
|
+
print(f"Original bbox: {bbox}")
|
|
93
|
+
print(f"Scale factor: {scale_factor}")
|
|
94
|
+
print(f"Viewport size: {viewport_size}")
|
|
95
|
+
print(f"Zoom level: {zoom_level}")
|
|
96
|
+
|
|
97
|
+
# Transform coordinates from screenshot to HTML
|
|
98
|
+
html_bbox = [
|
|
99
|
+
bbox[0] / scale_factor,
|
|
100
|
+
bbox[1] / scale_factor,
|
|
101
|
+
bbox[2] / scale_factor,
|
|
102
|
+
bbox[3] / scale_factor
|
|
103
|
+
]
|
|
104
|
+
print(f"Transformed bbox: {html_bbox}")
|
|
105
|
+
|
|
106
|
+
# Create HTML wrapper with matching viewport settings and scaled overlay
|
|
107
|
+
html_with_settings = f"""
|
|
108
|
+
<!DOCTYPE html>
|
|
109
|
+
<html>
|
|
110
|
+
<head>
|
|
111
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
112
|
+
<style>
|
|
113
|
+
body {{
|
|
114
|
+
margin: 0;
|
|
115
|
+
width: {viewport_size['width']}px;
|
|
116
|
+
height: {viewport_size['height']}px;
|
|
117
|
+
zoom: {zoom_level};
|
|
118
|
+
}}
|
|
119
|
+
.viewport-container {{
|
|
120
|
+
width: 100%;
|
|
121
|
+
height: 100%;
|
|
122
|
+
overflow: hidden;
|
|
123
|
+
position: relative;
|
|
124
|
+
transform-origin: top left;
|
|
125
|
+
transform: scale({1/scale_factor});
|
|
126
|
+
}}
|
|
127
|
+
#page-content {{
|
|
128
|
+
width: {viewport_size['width'] * scale_factor}px;
|
|
129
|
+
height: {viewport_size['height'] * scale_factor}px;
|
|
130
|
+
transform-origin: top left;
|
|
131
|
+
}}
|
|
132
|
+
#bbox-overlay {{
|
|
133
|
+
position: absolute;
|
|
134
|
+
border: 2px solid red;
|
|
135
|
+
left: {bbox[0]}px;
|
|
136
|
+
top: {bbox[1]}px;
|
|
137
|
+
width: {bbox[2] - bbox[0]}px;
|
|
138
|
+
height: {bbox[3] - bbox[1]}px;
|
|
139
|
+
pointer-events: none;
|
|
140
|
+
z-index: 10000;
|
|
141
|
+
}}
|
|
142
|
+
</style>
|
|
143
|
+
</head>
|
|
144
|
+
<body>
|
|
145
|
+
<div class="viewport-container">
|
|
146
|
+
<div id="page-content">
|
|
147
|
+
{html}
|
|
148
|
+
</div>
|
|
149
|
+
<div id="bbox-overlay"></div>
|
|
150
|
+
</div>
|
|
151
|
+
</body>
|
|
152
|
+
</html>
|
|
153
|
+
"""
|
|
154
|
+
|
|
155
|
+
# Save the HTML with viewport settings
|
|
156
|
+
with open('screenshot_with_viewport.html', 'w') as f:
|
|
157
|
+
f.write(html_with_settings)
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
def test_find_element_2():
|
|
161
|
+
with sync_playwright() as p:
|
|
162
|
+
driver = p.chromium.launch(headless=False).new_page(viewport={"width": 1920, "height": 1080})
|
|
163
|
+
simplex = Simplex(api_key=os.getenv("SIMPLEX_API_KEY"), driver=driver)
|
|
164
|
+
simplex.goto("https://www.cgtrader.com/")
|
|
165
|
+
|
|
166
|
+
state = simplex.take_stable_screenshot()
|
|
167
|
+
bbox = simplex.find_element("search bar")
|
|
168
|
+
|
|
169
|
+
print(bbox)
|
|
170
|
+
|
|
171
|
+
def test_hyperbrowser_integration():
|
|
172
|
+
"""Test Simplex integration with Hyperbrowser"""
|
|
173
|
+
|
|
174
|
+
# Initialize Hyperbrowser client
|
|
175
|
+
client = Hyperbrowser(api_key=os.getenv("HYPERBROWSER_API_KEY"))
|
|
176
|
+
|
|
177
|
+
# Create a new session
|
|
178
|
+
session = client.sessions.create()
|
|
179
|
+
ws_endpoint = session.ws_endpoint
|
|
180
|
+
|
|
181
|
+
try:
|
|
182
|
+
with sync_playwright() as p:
|
|
183
|
+
# Connect browser to Hyperbrowser session
|
|
184
|
+
browser = p.chromium.connect_over_cdp(ws_endpoint)
|
|
185
|
+
context = browser.new_context()
|
|
186
|
+
page = context.new_page()
|
|
187
|
+
|
|
188
|
+
# Initialize Simplex with the Hyperbrowser-connected page
|
|
189
|
+
simplex = Simplex(api_key=os.getenv("SIMPLEX_API_KEY"), browser=browser)
|
|
190
|
+
|
|
191
|
+
# Test basic functionality
|
|
192
|
+
simplex.goto("https://www.cgtrader.com/")
|
|
193
|
+
simplex.do("search for iphone")
|
|
194
|
+
|
|
195
|
+
# Verify the search worked by finding the search results
|
|
196
|
+
bbox = simplex.find_element("search results")
|
|
197
|
+
assert bbox is not None, "Search results not found"
|
|
198
|
+
|
|
199
|
+
finally:
|
|
200
|
+
# Always stop the Hyperbrowser session
|
|
201
|
+
client.sessions.stop(session.id)
|
|
202
|
+
|
|
203
|
+
if __name__ == "__main__":
|
|
204
|
+
test_hyperbrowser_integration()
|
|
205
|
+
|
|
206
|
+
|
|
@@ -1,111 +0,0 @@
|
|
|
1
|
-
import sys
|
|
2
|
-
import os
|
|
3
|
-
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
|
4
|
-
from simplex import Simplex
|
|
5
|
-
|
|
6
|
-
from PIL import ImageDraw
|
|
7
|
-
|
|
8
|
-
from playwright.sync_api import sync_playwright
|
|
9
|
-
from PIL import Image
|
|
10
|
-
import time
|
|
11
|
-
import tempfile
|
|
12
|
-
import webbrowser
|
|
13
|
-
|
|
14
|
-
from dotenv import load_dotenv
|
|
15
|
-
|
|
16
|
-
import io
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
load_dotenv()
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
def screenshot_tests():
|
|
23
|
-
simplex = Simplex(api_key=os.getenv("SIMPLEX_API_KEY"))
|
|
24
|
-
image = "/home/ubuntu/supreme-waffle/images/netflix.png"
|
|
25
|
-
screenshot = Image.open(image)
|
|
26
|
-
|
|
27
|
-
start_time = time.time()
|
|
28
|
-
bbox = simplex.find_element("dark mode icon", screenshot)
|
|
29
|
-
end_time = time.time()
|
|
30
|
-
print(f"Time taken: {end_time - start_time} seconds")
|
|
31
|
-
print(bbox)
|
|
32
|
-
|
|
33
|
-
start_time = time.time()
|
|
34
|
-
action = simplex.step_to_action("click and enter email address", screenshot)
|
|
35
|
-
end_time = time.time()
|
|
36
|
-
print(f"Time taken: {end_time - start_time} seconds")
|
|
37
|
-
print(action)
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
def execute_action_test():
|
|
41
|
-
playwright = sync_playwright().start()
|
|
42
|
-
browser = playwright.chromium.launch(headless=False)
|
|
43
|
-
driver = browser.new_page()
|
|
44
|
-
|
|
45
|
-
simplex = Simplex(api_key=os.getenv("SIMPLEX_API_KEY"), driver=driver)
|
|
46
|
-
simplex.goto("https://www.netflix.com/")
|
|
47
|
-
actions = [['CLICK', 'email field'], ['TYPE', 'email address']]
|
|
48
|
-
simplex.execute_action(actions[0])
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
def cgtrader_test():
|
|
52
|
-
assets = ["apple watch"]
|
|
53
|
-
urls = []
|
|
54
|
-
|
|
55
|
-
with sync_playwright() as p:
|
|
56
|
-
driver = p.chromium.launch(headless=False).new_page()
|
|
57
|
-
simplex = Simplex(api_key=os.getenv("SIMPLEX_API_KEY"), driver=driver)
|
|
58
|
-
simplex.goto("https://www.cgtrader.com/")
|
|
59
|
-
|
|
60
|
-
for asset in assets:
|
|
61
|
-
simplex.goto("https://www.cgtrader.com")
|
|
62
|
-
simplex.do(f"search for {asset}")
|
|
63
|
-
simplex.do("click on search button")
|
|
64
|
-
simplex.do(f"click on the first product")
|
|
65
|
-
driver.wait_for_timeout(3000)
|
|
66
|
-
|
|
67
|
-
urls.append(simplex.driver.url)
|
|
68
|
-
|
|
69
|
-
print(urls)
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
def test_find_element():
|
|
73
|
-
simplex = Simplex(api_key=os.getenv("SIMPLEX_API_KEY"))
|
|
74
|
-
simplex.goto("https://www.cgtrader.com/")
|
|
75
|
-
|
|
76
|
-
state = simplex.take_stable_screenshot()
|
|
77
|
-
bbox = simplex.find_element("cart")
|
|
78
|
-
|
|
79
|
-
# Save the screenshot without annotation
|
|
80
|
-
state.save('screenshot_with_bbox.png')
|
|
81
|
-
|
|
82
|
-
# Create a minimal HTML file with just the visualization and bbox
|
|
83
|
-
with open('screenshot_with_bbox.html', 'w') as f:
|
|
84
|
-
f.write(f"""
|
|
85
|
-
<div style="position: relative; display: inline-block;">
|
|
86
|
-
<img src="screenshot_with_bbox.png">
|
|
87
|
-
<div style="
|
|
88
|
-
position: absolute;
|
|
89
|
-
border: 2px solid red;
|
|
90
|
-
left: {bbox[0]}px;
|
|
91
|
-
top: {bbox[1]}px;
|
|
92
|
-
width: {bbox[2] - bbox[0]}px;
|
|
93
|
-
height: {bbox[3] - bbox[1]}px;
|
|
94
|
-
pointer-events: none;
|
|
95
|
-
"></div>
|
|
96
|
-
</div>
|
|
97
|
-
""")
|
|
98
|
-
|
|
99
|
-
# Create a second HTML file with just the screenshot
|
|
100
|
-
with open('screenshot.html', 'w') as f:
|
|
101
|
-
f.write("""
|
|
102
|
-
<div style="position: relative; display: inline-block;">
|
|
103
|
-
<img src="screenshot_with_bbox.png">
|
|
104
|
-
</div>
|
|
105
|
-
""")
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
if __name__ == "__main__":
|
|
109
|
-
cgtrader_test()
|
|
110
|
-
|
|
111
|
-
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|