Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions docs/api_reference.rst
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,12 @@ Wake API
.. automodule:: textverified.wake_api
:members:

Mocking API
~~~~~~~~~~~

.. automodule:: textverified.mocking
:members:

PaginatedList
---------------

Expand Down
127 changes: 118 additions & 9 deletions docs/examples.rst
Original file line number Diff line number Diff line change
Expand Up @@ -206,17 +206,10 @@ Wakeable Rental Example
# 2. Start a wake request for the rental
print("Sending wake request and waiting for active window...")
wake_request = wake_requests.create(rental)
duration = wake_request.usage_window_end - wake_request.usage_window_start
print(
f"Number {rental.number} is active from {wake_request.usage_window_start}"
f" to {wake_request.usage_window_end} (duration: {duration})"
)

# 3. Wait for the wake request to complete
time_until_start = wake_request.usage_window_start - datetime.datetime.now(datetime.timezone.utc)
print(f"Waiting for the number to become active... ({time_until_start})")
wake_response = wake_requests.wait_for_wake_request(wake_request)

duration = wake_response.usage_window_end - wake_response.usage_window_start
print(f"Number {rental.number} is now active until {wake_response.usage_window_end} (duration: {duration})")

# 3. Poll for SMS messages on the awakened number
print(f"Polling SMS messages for number {rental.number}...")
Expand Down Expand Up @@ -260,3 +253,119 @@ Proper error handling for production use:

Note that all API requests use exponential backoff for retries, and retries on connection error or ratelimit errors.

Mocking Examples
----------------

The mocking feature allows you to create mock objects for testing and development without making actual API calls.

Basic Verification Workflow with Mock ID
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

.. code-block:: python

from textverified import TextVerified, mocking

# Create a mock verification
mock_verification = mocking.verification()
print(f"Mock verification ID: {mock_verification.id}")

client = TextVerified(api_key="your_key", api_username="your_username")

# Use mock ID with real API methods
verification = client.verifications.details(mock_verification.id)
print(f"Verification number: {verification.number}")

# Poll for SMS messages
messages = client.sms.incoming(verification, timeout=10)
for message in messages:
print(f"Received code: {message.parsed_code}")
break

Verification Mock Purchase
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

.. code-block:: python

from textverified import TextVerified, mocking, ReservationCapability, NewVerificationRequest

# Create a mock service name
mock_service = mocking.target()
print(f"Mock service: {mock_service}")

client = TextVerified(api_key="your_key", api_username="your_username")

# Create verification request with mock service
request = NewVerificationRequest(
service_name=mock_service,
capability=ReservationCapability.SMS
)

# Get pricing and create verification
price_snapshot = client.verifications.pricing(request)
assert price_snapshot.price == 0.0 # will be 0.0 for mock
verification = client.verifications.create(request)
print(f"Created verification: {verification.id}")

Testing Error Handling with Random Failures
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

.. code-block:: python

from textverified import TextVerified, mocking, MockBehavior

# Create mock that fails randomly (helps test error handling)
mock_verification = mocking.verification(behavior=MockBehavior.FailsRandomly)

client = TextVerified(api_key="your_key", api_username="your_username")

# API calls will fail ~ 33% of the time, use this to test your error handling
try:
verification = client.verifications.details(mock_verification.id)
print("Verification succeeded")
except Exception as e:
print(f"Verification failed: {e}")

Rental Workflow with Mock ID
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

.. code-block:: python

from textverified import TextVerified, mocking

# Create a mock rental
mock_rental = mocking.rental()
print(f"Mock rental ID: {mock_rental.id}")

client = TextVerified(api_key="your_key", api_username="your_username")

# Get rental details
rental = client.reservations.details(mock_rental.id)
print(f"Rental number: {rental.number}")

# List SMS messages
messages = client.sms.list()
print(f"Found {len(messages)} messages")

Wake Rental Workflow with Mock ID
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

.. code-block:: python

from textverified import TextVerified, mocking

# Create mock rental for wake testing
mock_rental = mocking.rental()

client = TextVerified(api_key="your_key", api_username="your_username")

# Get rental and create wake request
rental = client.reservations.details(mock_rental.id)
wake_request = client.wake_requests.create(rental)

# Poll for messages during wake window
wake_request.wait_for_wake_request() # This will block for mocks
messages = client.sms.incoming(rental, timeout=10)
for message in messages:
print(f"Received: {message.sms_content}")
break

5 changes: 5 additions & 0 deletions examples/credential_set.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@

textverified.configure(api_key="your_api_key", api_username="your_username")

# Now we can call any API method as usual.

# The order of imports is not important -
# this import could have been before .configure

from textverified import account as tv_account

# Get account details
Expand Down
185 changes: 185 additions & 0 deletions examples/mocking.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
"""
Mocking Examples for TextVerified Python Client

This example demonstrates how to use mock verification and rental IDs
in real API workflows for testing and development.
"""

from textverified import TextVerified, mocking, MockBehavior, MockReceivePolicy, ReservationCapability, NewVerificationRequest
import time

client = TextVerified(api_key="YOUR_KEY", api_username="YOUR_EMAIL")

def mock_verification_workflow():
"""Complete verification workflow using a mock verification ID."""
print("Mock Verification Workflow")
print("=" * 30)

# Create a mock verification
mock_verification = mocking.verification(receive_policy=MockReceivePolicy.IncomingText) # default behavior, but explicitly specified
print(f"Created mock verification: {mock_verification.id}")

try:
# Use the real client for verification details and state
verification = client.verifications.details(mock_verification.id)
print(f"Verification number: {verification.number}")
print(f"Verification state: {verification.state}")

# Poll for SMS messages with base
print("Polling for SMS messages...")
messages = client.sms.incoming(verification, timeout=10)
for message in messages:
print(f"Received SMS: {message.sms_content}")
print(f"Parsed code: {message.parsed_code}")

except Exception as e:
print(f"API call failed (expected with mock credentials): {type(e).__name__}")

print()


def mock_verification_purchase_workflow():
"""Verification purchase workflow using a mock service name."""
print("Mock Verification Purchase Workflow")
print("=" * 30)

# Create a mock service name (target)
# You can also use mocking.service(...) as an alias
mock_service = mocking.target(behavior=MockBehavior.Succeeds)
print(f"Created mock service: {mock_service}")

try:
# Create a verification request using the mock service name
request = NewVerificationRequest(
service_name=mock_service,
capability=ReservationCapability.SMS
)

# Get pricing for the mock service
price = client.verifications.pricing(request)
print(f"Pricing for mock service: ${price.price}")

# Create the verification
verification = client.verifications.create(request)
print(f"Verification created: {verification.id}")
print(f"Verification number: {verification.number}")

# Poll for SMS messages
print("Polling for verification code...")
for message in client.sms.incoming(verification, timeout=10):
print(f"Received SMS: {message.sms_content}")
print(f"Parsed verification code: {message.parsed_code}")
break

except Exception as e:
print(f"API call failed (expected with mock credentials): {type(e).__name__}")

print()


def mock_verification_with_random_failures():
"""Verification workflow that may fail randomly to test error handling."""
print("Mock Verification with Random Failures")
print("=" * 30)

# Create a mock verification that fails randomly (1/3 of the time)
# This helps test unexpected behavior and error handling
mock_verification = mocking.verification(
behavior=MockBehavior.FailsRandomly,
receive_policy=MockReceivePolicy.IncomingText
)
print(f"Created mock verification: {mock_verification.id}")

try:
verification = client.verifications.details(mock_verification.id)
print(f"Verification succeeded: {verification.number}")

# This might succeed or fail, testing your error handling
for message in client.sms.incoming(verification, timeout=10):
print(f"SMS received: {message.parsed_code}")

except Exception as e:
print(f"Verification failed (this may happen randomly): {type(e).__name__}")

print()


def mock_rental_workflow():
"""Rental workflow using a mock rental ID."""
print("Mock Rental Workflow")
print("=" * 30)

# Create a mock rental
mock_rental = mocking.rental(behavior=MockBehavior.Succeeds)
print(f"Created mock rental: {mock_rental.id}")

client = TextVerified(api_key="mock", api_username="mock")

try:
# Get rental details
rental = client.reservations.details(mock_rental.id)
print(f"Rental number: {rental.number}")
print(f"Rental state: {rental.state}")

# List SMS messages for the rental
messages = client.sms.list()
print(f"Found {len(messages)} SMS messages")

except Exception as e:
print(f"API call failed (expected with mock credentials): {type(e).__name__}")

print()


def mock_wake_rental_workflow():
"""Wake rental workflow using a mock rental ID."""
print("Mock Wake Rental Workflow")
print("=" * 30)

# Create a mock rental for wake testing
mock_rental = mocking.rental(
behavior=MockBehavior.Succeeds,
receive_policy=MockReceivePolicy.IncomingTextAndCall
)
print(f"Created mock rental: {mock_rental.id}")

try:
# Get rental details
rental = client.reservations.details(mock_rental.id)
print(f"Rental number: {rental.number}")

# Create a wake request for the rental
wake_request = client.wake_requests.create(rental)
print(f"Wake request created: {wake_request.id}")
print(f"Active from {wake_request.usage_window_start} to {wake_request.usage_window_end}")

# Poll for messages during the wake window
duration = wake_request.usage_window_end - wake_request.usage_window_start
print("Polling for messages during wake window...")
messages = client.sms.incoming(rental, timeout=duration.total_seconds())

for message in messages:
print(f"Received: {message.sms_content}")
break # Just show first message

except Exception as e:
print(f"API call failed (expected with mock credentials): {type(e).__name__}")

print()


if __name__ == "__main__":
print("TextVerified Mocking Examples")
print("=" * 30)
print()

# Run all examples
mock_verification_workflow()
mock_verification_purchase_workflow()
mock_verification_with_random_failures()
mock_rental_workflow()
mock_wake_rental_workflow()

print("Examples completed.")
print("Note: API calls use mock credentials and may fail - this demonstrates")
print("how mock IDs integrate with real API workflows for testing.")
7 changes: 5 additions & 2 deletions examples/wake_rental.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,18 @@
wake_request = wake_requests.create(rental)
duration = wake_request.usage_window_end - wake_request.usage_window_start
print(
f"Number {rental.number} is active from {wake_request.usage_window_start}"
f"Number {rental.number} is estimated to be active from {wake_request.usage_window_start}"
f" to {wake_request.usage_window_end} (duration: {duration})"
)

# 3. Wait for the wake request to complete
time_until_start = wake_request.usage_window_start - datetime.datetime.now(datetime.timezone.utc)
print(f"Waiting for the number to become active... ({time_until_start})")
print(f"Waiting for the number to become active... (estimate: {time_until_start})")
wake_response = wake_requests.wait_for_wake_request(wake_request)

# Refresh duration based on actual active window
duration = wake_response.usage_window_end - wake_response.usage_window_start
print(f"Number {rental.number} is now active until {wake_response.usage_window_end} (duration: {duration})")

# 3. Poll for SMS messages on the awakened number
print(f"Polling SMS messages for number {rental.number}...")
Expand Down
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ extend-exclude = '''
| \.venv
| build
| dist
| examples
| textverified/data
)/
'''
Expand Down
Loading