Skip to content

Commit 3dd8c70

Browse files
committed
test: add request validation tests for verify engine auth
Add unit tests that verify the SDK sends the Authorization header correctly for the Verify Engine API. These tests would have caught the authentication bug fixed in v0.2.1 where the token was being sent in form data instead of the Authorization header. Python SDK: - Add TestAssetSearchRequestConstruction class with 4 new tests - Verify Authorization header format is "token {token_value}" - Verify token is NOT sent in form data - Verify NID and optional params are sent correctly TypeScript SDK: - Add Vitest testing framework - Create client.test.ts with 15 tests covering: - Request construction (auth header, form data) - Response parsing (precise match, similar matches, etc.) - Input validation (threshold, sampleCount) - Rename integration.test.ts to integration-runner.ts to avoid Vitest picking it up (it's a standalone script, not unit tests)
1 parent 469c292 commit 3dd8c70

File tree

5 files changed

+879
-5
lines changed

5 files changed

+879
-5
lines changed

python/tests/test_asset_search.py

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,3 +237,114 @@ def test_search_asset_validates_sample_count(self, capture_client):
237237
match="sample_count must be a positive integer",
238238
):
239239
capture_client.search_asset(nid=TEST_NID, sample_count=0)
240+
241+
242+
class TestAssetSearchRequestConstruction:
243+
"""Tests for verifying correct request construction.
244+
245+
These tests ensure the SDK sends properly formatted requests to the API,
246+
including correct authentication headers. This catches bugs like sending
247+
the token in form data instead of the Authorization header.
248+
"""
249+
250+
@respx.mock
251+
def test_search_asset_sends_authorization_header(self):
252+
"""Verify Authorization header is sent with correct format."""
253+
test_token = "my-secret-token"
254+
capture = Capture(token=test_token)
255+
256+
mock_response = {
257+
"precise_match": "",
258+
"input_file_mime_type": "",
259+
"similar_matches": [],
260+
"order_id": "test-order",
261+
}
262+
263+
route = respx.post(ASSET_SEARCH_API_URL).mock(
264+
return_value=Response(200, json=mock_response)
265+
)
266+
267+
capture.search_asset(nid=TEST_NID)
268+
269+
# Verify the request was made
270+
assert route.called
271+
assert route.call_count == 1
272+
273+
# Verify Authorization header format: "token {token_value}"
274+
request = route.calls[0].request
275+
assert "Authorization" in request.headers
276+
assert request.headers["Authorization"] == f"token {test_token}"
277+
278+
@respx.mock
279+
def test_search_asset_does_not_send_token_in_form_data(self):
280+
"""Verify token is NOT sent in form data (only in header)."""
281+
test_token = "my-secret-token"
282+
capture = Capture(token=test_token)
283+
284+
mock_response = {
285+
"precise_match": "",
286+
"input_file_mime_type": "",
287+
"similar_matches": [],
288+
"order_id": "test-order",
289+
}
290+
291+
route = respx.post(ASSET_SEARCH_API_URL).mock(
292+
return_value=Response(200, json=mock_response)
293+
)
294+
295+
capture.search_asset(nid=TEST_NID)
296+
297+
# Get the request body
298+
request = route.calls[0].request
299+
body_content = request.content.decode("utf-8")
300+
301+
# Token should NOT appear in form data
302+
# (it should only be in the Authorization header)
303+
assert "my-secret-token" not in body_content
304+
305+
@respx.mock
306+
def test_search_asset_sends_nid_in_form_data(self):
307+
"""Verify NID is sent in form data when searching by NID."""
308+
capture = Capture(token="test-token")
309+
310+
mock_response = {
311+
"precise_match": "",
312+
"input_file_mime_type": "",
313+
"similar_matches": [],
314+
"order_id": "test-order",
315+
}
316+
317+
route = respx.post(ASSET_SEARCH_API_URL).mock(
318+
return_value=Response(200, json=mock_response)
319+
)
320+
321+
capture.search_asset(nid=TEST_NID)
322+
323+
# Verify NID is in the request body
324+
request = route.calls[0].request
325+
body_content = request.content.decode("utf-8")
326+
assert TEST_NID in body_content
327+
328+
@respx.mock
329+
def test_search_asset_sends_optional_params_in_form_data(self):
330+
"""Verify optional parameters are sent in form data."""
331+
capture = Capture(token="test-token")
332+
333+
mock_response = {
334+
"precise_match": "",
335+
"input_file_mime_type": "",
336+
"similar_matches": [],
337+
"order_id": "test-order",
338+
}
339+
340+
route = respx.post(ASSET_SEARCH_API_URL).mock(
341+
return_value=Response(200, json=mock_response)
342+
)
343+
344+
capture.search_asset(nid=TEST_NID, threshold=0.5, sample_count=10)
345+
346+
# Verify optional params are in the request body
347+
request = route.calls[0].request
348+
body_content = request.content.decode("utf-8")
349+
assert "0.5" in body_content # threshold
350+
assert "10" in body_content # sample_count

0 commit comments

Comments
 (0)