Skip to content

Commit 291afe9

Browse files
update core integration test
1 parent a0cebee commit 291afe9

File tree

2 files changed

+254
-122
lines changed

2 files changed

+254
-122
lines changed

tests/integration/api/test_core_api.py

Lines changed: 144 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -8,83 +8,159 @@
88
from stagehand.schemas import ExtractOptions
99

1010

11-
skip_if_no_creds = pytest.mark.skipif(
12-
not (os.getenv("BROWSERBASE_API_KEY") and os.getenv("BROWSERBASE_PROJECT_ID")),
13-
reason="Browserbase credentials are not available for API integration tests",
14-
)
15-
16-
1711
class Article(BaseModel):
1812
"""Schema for article extraction tests"""
1913
title: str = Field(..., description="The title of the article")
2014
summary: str = Field(None, description="A brief summary or description of the article")
2115

2216

23-
@pytest_asyncio.fixture(scope="module")
24-
@skip_if_no_creds
25-
async def stagehand_api():
26-
"""Provide a lightweight Stagehand instance pointing to the Browserbase API."""
27-
config = StagehandConfig(
28-
env="BROWSERBASE",
29-
api_key=os.getenv("BROWSERBASE_API_KEY"),
30-
project_id=os.getenv("BROWSERBASE_PROJECT_ID"),
31-
headless=True,
32-
verbose=0,
33-
)
34-
sh = Stagehand(config=config)
35-
await sh.init()
36-
yield sh
37-
await sh.close()
17+
class TestStagehandAPIIntegration:
18+
"""Integration tests for Stagehand Python SDK in BROWSERBASE API mode."""
3819

20+
@pytest.fixture(scope="class")
21+
def browserbase_config(self):
22+
"""Configuration for BROWSERBASE mode testing"""
23+
return StagehandConfig(
24+
env="BROWSERBASE",
25+
api_key=os.getenv("BROWSERBASE_API_KEY"),
26+
project_id=os.getenv("BROWSERBASE_PROJECT_ID"),
27+
model_name="gpt-4o",
28+
headless=False,
29+
verbose=2,
30+
model_client_options={"apiKey": os.getenv("MODEL_API_KEY") or os.getenv("OPENAI_API_KEY")},
31+
)
3932

40-
@skip_if_no_creds
41-
@pytest.mark.integration
42-
@pytest.mark.api
43-
@pytest.mark.asyncio
44-
async def test_stagehand_api_initialization(stagehand_api):
45-
"""Ensure that Stagehand initializes correctly against the Browserbase API."""
46-
assert stagehand_api.session_id is not None
33+
@pytest_asyncio.fixture
34+
async def stagehand_api(self, browserbase_config):
35+
"""Create a Stagehand instance for BROWSERBASE API testing"""
36+
if not (os.getenv("BROWSERBASE_API_KEY") and os.getenv("BROWSERBASE_PROJECT_ID")):
37+
pytest.skip("Browserbase credentials not available")
38+
39+
stagehand = Stagehand(config=browserbase_config)
40+
await stagehand.init()
41+
yield stagehand
42+
await stagehand.close()
4743

44+
@pytest.mark.asyncio
45+
@pytest.mark.integration
46+
@pytest.mark.api
47+
@pytest.mark.skipif(
48+
not (os.getenv("BROWSERBASE_API_KEY") and os.getenv("BROWSERBASE_PROJECT_ID")),
49+
reason="Browserbase credentials are not available for API integration tests",
50+
)
51+
async def test_stagehand_api_initialization(self, stagehand_api):
52+
"""Ensure that Stagehand initializes correctly against the Browserbase API."""
53+
assert stagehand_api.session_id is not None
4854

49-
@skip_if_no_creds
50-
@pytest.mark.integration
51-
@pytest.mark.api
52-
@pytest.mark.asyncio
53-
async def test_api_extract_functionality(stagehand_api):
54-
"""Test core extract functionality in API mode - extracted from e2e tests."""
55-
stagehand = stagehand_api
56-
57-
# Navigate to a content-rich page
58-
await stagehand.page.goto("https://news.ycombinator.com")
59-
60-
# Test simple text-based extraction
61-
titles_text = await stagehand.page.extract(
62-
"Extract the titles of the first 3 articles on the page as a JSON array"
55+
@pytest.mark.asyncio
56+
@pytest.mark.integration
57+
@pytest.mark.api
58+
@pytest.mark.skipif(
59+
not (os.getenv("BROWSERBASE_API_KEY") and os.getenv("BROWSERBASE_PROJECT_ID")),
60+
reason="Browserbase credentials are not available for API integration tests",
6361
)
64-
65-
# Verify extraction worked
66-
assert titles_text is not None
67-
68-
# Test schema-based extraction
69-
extract_options = ExtractOptions(
70-
instruction="Extract the first article's title and any available summary",
71-
schema_definition=Article
62+
async def test_api_observe_and_act_workflow(self, stagehand_api):
63+
"""Test core observe and act workflow in API mode - replicated from local tests."""
64+
stagehand = stagehand_api
65+
66+
# Navigate to a form page for testing
67+
await stagehand.page.goto("https://httpbin.org/forms/post")
68+
69+
# Test OBSERVE primitive: Find form elements
70+
form_elements = await stagehand.page.observe("Find all form input elements")
71+
72+
# Verify observations
73+
assert form_elements is not None
74+
assert len(form_elements) > 0
75+
76+
# Verify observation structure
77+
for obs in form_elements:
78+
assert hasattr(obs, "selector")
79+
assert obs.selector # Not empty
80+
81+
# Test ACT primitive: Fill form fields
82+
await stagehand.page.act("Fill the customer name field with 'API Integration Test'")
83+
await stagehand.page.act("Fill the telephone field with '555-API'")
84+
await stagehand.page.act("Fill the email field with '[email protected]'")
85+
86+
# Verify actions worked by observing filled fields
87+
filled_fields = await stagehand.page.observe("Find all filled form input fields")
88+
assert filled_fields is not None
89+
assert len(filled_fields) > 0
90+
91+
# Test interaction with specific elements
92+
customer_field = await stagehand.page.observe("Find the customer name input field")
93+
assert customer_field is not None
94+
assert len(customer_field) > 0
95+
96+
@pytest.mark.asyncio
97+
@pytest.mark.integration
98+
@pytest.mark.api
99+
@pytest.mark.skipif(
100+
not (os.getenv("BROWSERBASE_API_KEY") and os.getenv("BROWSERBASE_PROJECT_ID")),
101+
reason="Browserbase credentials are not available for API integration tests",
102+
)
103+
async def test_api_basic_navigation_and_observe(self, stagehand_api):
104+
"""Test basic navigation and observe functionality in API mode - replicated from local tests."""
105+
stagehand = stagehand_api
106+
107+
# Navigate to a simple page
108+
await stagehand.page.goto("https://example.com")
109+
110+
# Observe elements on the page
111+
observations = await stagehand.page.observe("Find all the links on the page")
112+
113+
# Verify we got some observations
114+
assert observations is not None
115+
assert len(observations) > 0
116+
117+
# Verify observation structure
118+
for obs in observations:
119+
assert hasattr(obs, "selector")
120+
assert obs.selector # Not empty
121+
122+
@pytest.mark.asyncio
123+
@pytest.mark.integration
124+
@pytest.mark.api
125+
@pytest.mark.skipif(
126+
not (os.getenv("BROWSERBASE_API_KEY") and os.getenv("BROWSERBASE_PROJECT_ID")),
127+
reason="Browserbase credentials are not available for API integration tests",
72128
)
73-
74-
article_data = await stagehand.page.extract(extract_options)
75-
assert article_data is not None
76-
77-
# Validate the extracted data structure (Browserbase format)
78-
if hasattr(article_data, 'data') and article_data.data:
79-
# BROWSERBASE mode format
80-
article = Article.model_validate(article_data.data)
81-
assert article.title
82-
assert len(article.title) > 0
83-
elif hasattr(article_data, 'title'):
84-
# Fallback format
85-
article = Article.model_validate(article_data.model_dump())
86-
assert article.title
87-
assert len(article.title) > 0
88-
89-
# Verify API session is active
90-
assert stagehand.session_id is not None
129+
async def test_api_extraction_functionality(self, stagehand_api):
130+
"""Test extraction functionality in API mode - replicated from local tests."""
131+
stagehand = stagehand_api
132+
133+
# Navigate to a content-rich page
134+
await stagehand.page.goto("https://news.ycombinator.com")
135+
136+
# Test simple text-based extraction
137+
titles_text = await stagehand.page.extract(
138+
"Extract the titles of the first 3 articles on the page as a JSON array"
139+
)
140+
141+
# Verify extraction worked
142+
assert titles_text is not None
143+
144+
# Test schema-based extraction
145+
extract_options = ExtractOptions(
146+
instruction="Extract the first article's title and any available summary",
147+
schema_definition=Article
148+
)
149+
150+
article_data = await stagehand.page.extract(extract_options)
151+
assert article_data is not None
152+
153+
# Validate the extracted data structure (Browserbase format)
154+
if hasattr(article_data, 'data') and article_data.data:
155+
# BROWSERBASE mode format
156+
article = Article.model_validate(article_data.data)
157+
assert article.title
158+
assert len(article.title) > 0
159+
elif hasattr(article_data, 'title'):
160+
# Fallback format
161+
article = Article.model_validate(article_data.model_dump())
162+
assert article.title
163+
assert len(article.title) > 0
164+
165+
# Verify API session is active
166+
assert stagehand.session_id is not None

0 commit comments

Comments
 (0)