From 195a656a7d4f77dc2d07dc2c23cecc02c117d884 Mon Sep 17 00:00:00 2001 From: OpenClaw Date: Fri, 27 Feb 2026 11:01:11 +0000 Subject: [PATCH] fix(sdk): BUG-015 validate URL in capture() when using ScreenshotOptions - Add URL validation after options.to_dict() in Python SDK - Add failing test first (TDD), then fix - All 17 Python SDK tests passing --- .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 366 bytes .../snapapi/__pycache__/client.cpython-312.pyc | Bin 0 -> 7736 bytes sdk/python/src/snapapi/client.py | 2 ++ .../__pycache__/test_snapapi.cpython-312.pyc | Bin 0 -> 17794 bytes sdk/python/tests/test_snapapi.py | 8 ++++++-- 5 files changed, 8 insertions(+), 2 deletions(-) create mode 100644 sdk/python/src/snapapi/__pycache__/__init__.cpython-312.pyc create mode 100644 sdk/python/src/snapapi/__pycache__/client.cpython-312.pyc create mode 100644 sdk/python/tests/__pycache__/test_snapapi.cpython-312.pyc diff --git a/sdk/python/src/snapapi/__pycache__/__init__.cpython-312.pyc b/sdk/python/src/snapapi/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..07474a58e09ceda699a4c8b621b4cb62cf06ba21 GIT binary patch literal 366 zcmX@j%ge>Uz`)>9xiIq_0|Ucj5C?{tpp4HN3=9m@8B!Rc7*ZHhm~t3%nWC6-nWLC< zS)y1N8PXY2m=-Zcv8FIbu~o8YvX+`NFfat?B^Edacq#-`mSp7TDFnNCD?DnLqTm{; zn~`5!lA5AWoLrQenpd2WU!nj~mzKI9w@`Ls3^bamS8Yk zmw!P?W`16A6|141fu4b%Ci^Y+`1q9kC!tidaAdD+2=qNIo$qCqDib zcYJ(VYEf}!eqMb1N`}uMU;fh9FUc*?hgzmzoRY0y0Cu^4aZ$2Ue0*kJ zW=VX!UP0wA4x8Nkl+v73yCPl&1_qF`izOHs7(OsFGBVy|uzk*8bCJR35tmg1`wc$P LM(!eR1_lNICWB}< literal 0 HcmV?d00001 diff --git a/sdk/python/src/snapapi/__pycache__/client.cpython-312.pyc b/sdk/python/src/snapapi/__pycache__/client.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..223ed01c1823a38d5702129a7ea11e0b48aac977 GIT binary patch literal 7736 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 literal 0 HcmV?d00001 diff --git a/sdk/python/src/snapapi/client.py b/sdk/python/src/snapapi/client.py index 63983f9..fb2fa0e 100644 --- a/sdk/python/src/snapapi/client.py +++ b/sdk/python/src/snapapi/client.py @@ -144,6 +144,8 @@ class SnapAPI: """ if options: body = options.to_dict() + if not body.get('url'): + raise ValueError("url is required") else: if not url: raise ValueError("url is required") diff --git a/sdk/python/tests/__pycache__/test_snapapi.cpython-312.pyc b/sdk/python/tests/__pycache__/test_snapapi.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..650078aa05c6ef29ee2bdc08eb2b56b3f6ec253f GIT binary patch literal 17794 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 P=-cZ5fti6t3LIbnu@o5v literal 0 HcmV?d00001 diff --git a/sdk/python/tests/test_snapapi.py b/sdk/python/tests/test_snapapi.py index 8a2cdf9..8ca56ab 100644 --- a/sdk/python/tests/test_snapapi.py +++ b/sdk/python/tests/test_snapapi.py @@ -165,8 +165,12 @@ class TestSnapAPI(unittest.TestCase): self.snap.capture(None) self.assertEqual(str(cm.exception), "url is required") - # Note: When using ScreenshotOptions object, URL validation doesn't happen early - # This could be considered a bug in the SDK but we're testing current behavior + def test_capture_raises_value_error_if_options_has_empty_url(self): + """capture(options=ScreenshotOptions(url='')) should raise ValueError.""" + options = ScreenshotOptions(url="") + with self.assertRaises(ValueError) as cm: + self.snap.capture(options=options) + self.assertEqual(str(cm.exception), "url is required") @patch('snapapi.client.urllib.request.urlopen') def test_capture_raises_snap_api_error_on_http_error(self, mock_urlopen):