Skip to content

Commit b3ef1fd

Browse files
committed
tests: add tests for locations, more assertions for pagination, html output
1 parent 561d334 commit b3ef1fd

3 files changed

Lines changed: 82 additions & 13 deletions

File tree

.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ jobs:
1515
runs-on: ubuntu-latest
1616
strategy:
1717
matrix:
18-
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13"]
18+
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13", "3.14"]
1919

2020
steps:
2121
- name: Checkout repository

.github/workflows/release.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ jobs:
1414
runs-on: ubuntu-latest
1515
strategy:
1616
matrix:
17-
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13"]
17+
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13", "3.14"]
1818
steps:
1919
- uses: actions/checkout@v6
2020

tests/test_integration.py

Lines changed: 80 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,16 @@
1+
from urllib.parse import parse_qs, urlparse
2+
13
import pytest
24

35
import serpapi
46

57

8+
def _query_param(url, param):
9+
values = parse_qs(urlparse(url).query).get(param)
10+
if values:
11+
return values[0]
12+
13+
614
def test_basic_import():
715
"""Test that basic import works as intended."""
816
import serpapi
@@ -18,6 +26,43 @@ def test_entrypoints(client):
1826
assert api.locations
1927

2028

29+
def test_locations_query_limit_and_shape(client):
30+
locations = client.locations(q="Austin", limit=5)
31+
32+
assert isinstance(locations, list)
33+
assert 0 < len(locations) <= 5
34+
35+
expected_fields = {
36+
"id",
37+
"name",
38+
"canonical_name",
39+
"country_code",
40+
"target_type",
41+
"reach",
42+
}
43+
44+
for location in locations:
45+
assert expected_fields.issubset(location.keys())
46+
assert isinstance(location["canonical_name"], str)
47+
48+
assert any(
49+
"Austin" in location["name"] or "Austin" in location["canonical_name"]
50+
for location in locations
51+
)
52+
53+
54+
def test_search_accepts_location_from_locations_api(client):
55+
locations = client.locations(q="Austin", limit=1)
56+
location_name = locations[0]["canonical_name"]
57+
58+
search = client.search(q="coffee", location=location_name)
59+
60+
assert search.get("error") is None
61+
assert search["organic_results"]
62+
assert "Austin" in search["search_parameters"]["location_requested"]
63+
assert "United States" in search["search_parameters"]["location_used"]
64+
65+
2166
def test_account_without_credentials():
2267
"""Ensure that an HTTPError is raised when account is accessed without API Credentials."""
2368
with pytest.raises(serpapi.HTTPError):
@@ -58,29 +103,53 @@ def test_coffee_search_as_dict(coffee_search):
58103
assert isinstance(d, dict)
59104

60105

61-
def test_coffee_search_html(coffee_search_html):
106+
def test_search_output_html_contains_raw_html_document(coffee_search_html):
62107
assert isinstance(coffee_search_html, str)
108+
assert "<html" in coffee_search_html.lower()
109+
assert "</html>" in coffee_search_html.lower()
110+
assert "coffee" in coffee_search_html.lower()
63111
assert not hasattr(coffee_search_html, "next_page_url")
64112

65113

66-
def test_coffee_search_n_pages(coffee_search):
67-
page_count = 0
68-
max_pages = 3
114+
def test_next_page_url_uses_serpapi_pagination_next(coffee_search):
115+
next_page_url = coffee_search.next_page_url
69116

70-
for page in coffee_search.yield_pages(max_pages=max_pages):
71-
if page_count == 0:
72-
assert 'start' not in page['search_parameters'], "The 'start' parameter should not be in the first page"
73-
74-
page_count += 1
117+
assert next_page_url == coffee_search["serpapi_pagination"]["next"]
118+
assert _query_param(next_page_url, "start") == "10"
119+
assert _query_param(next_page_url, "api_key") is None
120+
121+
122+
def test_yield_pages_returns_unique_search_pages(coffee_search):
123+
max_pages = 3
124+
pages = list(coffee_search.yield_pages(max_pages=max_pages))
75125

76-
assert page_count == max_pages
126+
assert len(pages) == max_pages
127+
assert len({page["search_metadata"]["id"] for page in pages}) == max_pages
128+
assert "start" not in pages[0]["search_parameters"]
129+
assert int(pages[1]["search_parameters"]["start"]) == 10
130+
assert int(pages[2]["search_parameters"]["start"]) == 20
77131

78132

79-
def test_coffee_search_next_page(coffee_search):
133+
def test_next_page_advances_start_and_returns_new_results(coffee_search):
80134
next_page = coffee_search.next_page()
81135

82136
assert isinstance(next_page, serpapi.SerpResults)
83137
assert coffee_search["search_metadata"]["id"] != next_page["search_metadata"]["id"]
138+
assert int(next_page["search_parameters"]["start"]) == 10
139+
assert next_page["organic_results"]
140+
141+
page_number = next_page["search_information"].get("page_number")
142+
if page_number is not None:
143+
assert int(page_number) == 2
144+
145+
146+
def test_search_archive_round_trips_search_id(client, coffee_search):
147+
search_id = coffee_search["search_metadata"]["id"]
148+
149+
archived_search = client.search_archive(search_id=search_id)
150+
151+
assert isinstance(archived_search, serpapi.SerpResults)
152+
assert archived_search["search_metadata"]["id"] == search_id
84153

85154

86155
def test_search_function_signature(coffee_params, client):

0 commit comments

Comments
 (0)