feat(client): add guarded product link capture
This commit is contained in:
@@ -16,11 +16,14 @@ from cmbuyer_client.device.adb import (
|
||||
AdbClient,
|
||||
CommandResult,
|
||||
DeviceIdentityUnconfirmedError,
|
||||
DeviceCommandError,
|
||||
DeviceCommandTimeoutError,
|
||||
DeviceNotFoundError,
|
||||
DeviceOfflineError,
|
||||
DeviceStateError,
|
||||
DeviceUnauthorizedError,
|
||||
DuplicatePhysicalDeviceError,
|
||||
IntentLaunchUnconfirmedError,
|
||||
SerialRequiredError,
|
||||
)
|
||||
|
||||
@@ -176,7 +179,95 @@ class AdbClientTests(unittest.TestCase):
|
||||
def run(self, arguments: Sequence[str], timeout_seconds: float) -> CommandResult:
|
||||
raise subprocess.TimeoutExpired(arguments, timeout_seconds)
|
||||
|
||||
from cmbuyer_client.device.adb import DeviceCommandTimeoutError
|
||||
|
||||
with self.assertRaises(DeviceCommandTimeoutError):
|
||||
AdbClient(TimeoutRunner()).inspect(USB_SERIAL)
|
||||
|
||||
def test_product_intent_is_fixed_to_action_view_and_pdd_package(self) -> None:
|
||||
class IntentRunner:
|
||||
def __init__(self) -> None:
|
||||
self.calls: list[tuple[str, ...]] = []
|
||||
|
||||
def run(self, arguments: Sequence[str], timeout_seconds: float) -> CommandResult:
|
||||
self.calls.append(tuple(arguments))
|
||||
return CommandResult(stdout="Status: ok\n")
|
||||
|
||||
runner = IntentRunner()
|
||||
summary = AdbClient(runner).start_pdd_view_intent(
|
||||
USB_SERIAL,
|
||||
"123",
|
||||
)
|
||||
|
||||
self.assertEqual(summary.status, "ok")
|
||||
self.assertEqual(
|
||||
runner.calls,
|
||||
[
|
||||
(
|
||||
"-s",
|
||||
USB_SERIAL,
|
||||
"shell",
|
||||
"am",
|
||||
"start",
|
||||
"-W",
|
||||
"-a",
|
||||
"android.intent.action.VIEW",
|
||||
"-d",
|
||||
"https://mobile.yangkeduo.com/goods.html?goods_id=123",
|
||||
"-p",
|
||||
"com.xunmeng.pinduoduo",
|
||||
)
|
||||
],
|
||||
)
|
||||
|
||||
def test_product_intent_without_explicit_success_is_rejected(self) -> None:
|
||||
class UnknownIntentRunner:
|
||||
def run(self, arguments: Sequence[str], timeout_seconds: float) -> CommandResult:
|
||||
return CommandResult(stdout="Starting: Intent { ... }\n")
|
||||
|
||||
with self.assertRaises(IntentLaunchUnconfirmedError):
|
||||
AdbClient(UnknownIntentRunner()).start_pdd_view_intent(
|
||||
USB_SERIAL,
|
||||
"123",
|
||||
)
|
||||
|
||||
def test_product_intent_rejects_invalid_goods_id_before_runner(self) -> None:
|
||||
class RecordingRunner:
|
||||
def __init__(self) -> None:
|
||||
self.calls: list[tuple[str, ...]] = []
|
||||
|
||||
def run(self, arguments: Sequence[str], timeout_seconds: float) -> CommandResult:
|
||||
self.calls.append(tuple(arguments))
|
||||
return CommandResult(stdout="Status: ok\n")
|
||||
|
||||
invalid_values: tuple[object, ...] = (
|
||||
"",
|
||||
"12a",
|
||||
"123",
|
||||
" 123",
|
||||
"123 ",
|
||||
"https://mobile.yangkeduo.com/goods.html?goods_id=123",
|
||||
"am start -W -d anything",
|
||||
123,
|
||||
None,
|
||||
)
|
||||
for value in invalid_values:
|
||||
with self.subTest(value=repr(value)):
|
||||
runner = RecordingRunner()
|
||||
with self.assertRaises(ValueError):
|
||||
AdbClient(runner).start_pdd_view_intent(USB_SERIAL, value) # type: ignore[arg-type]
|
||||
self.assertEqual(runner.calls, [])
|
||||
|
||||
def test_product_intent_nonzero_and_timeout_remain_distinct(self) -> None:
|
||||
class FailedIntentRunner:
|
||||
def run(self, arguments: Sequence[str], timeout_seconds: float) -> CommandResult:
|
||||
return CommandResult(stdout="sensitive command output", returncode=1)
|
||||
|
||||
class TimeoutIntentRunner:
|
||||
def run(self, arguments: Sequence[str], timeout_seconds: float) -> CommandResult:
|
||||
raise subprocess.TimeoutExpired(arguments, timeout_seconds)
|
||||
|
||||
with self.assertRaises(DeviceCommandError) as command_error:
|
||||
AdbClient(FailedIntentRunner()).start_pdd_view_intent(USB_SERIAL, "123")
|
||||
self.assertNotIn("sensitive command output", str(command_error.exception))
|
||||
|
||||
with self.assertRaises(DeviceCommandTimeoutError):
|
||||
AdbClient(TimeoutIntentRunner()).start_pdd_view_intent(USB_SERIAL, "123")
|
||||
|
||||
Reference in New Issue
Block a user