from pathlib import Path
ROOT=Path(__file__).resolve().parents[1]
def test_v010_router_pwa_and_version():
    api=(ROOT/'app/api/v010.py').read_text(); main=(ROOT/'app/main.py').read_text()
    assert "prefix='/api/v010'" in api and 'app.include_router(v010_router)' in main
    for f in ['mobile.html','manifest.webmanifest','service-worker.js','mobile-icon.svg']: assert (ROOT/'app/static'/f).exists()
def test_v010_models_and_migration():
    text=(ROOT/'app/models/entities.py').read_text()
    for n in ['MobileDevice','PushSubscription','MobileNotificationPreference','OfflineSyncOperation','MobileSyncCursor','PushDelivery']: assert f'class {n}' in text
    assert (ROOT/'migrations/010_mobile_pwa.sql').exists()
def test_offline_sync_is_idempotent_and_bounded():
    api=(ROOT/'app/api/v010.py').read_text()
    assert 'client_operation_id' in api and 'batch.operations[:200]' in api and "operation_type=='notification.read'" in api
    assert 'UniqueConstraint(\'user_id\',\'client_operation_id\'' in (ROOT/'app/models/entities.py').read_text()
def test_push_security_and_worker():
    api=(ROOT/'app/api/v010.py').read_text(); service=(ROOT/'app/services/mobile_push.py').read_text(); workers=(ROOT/'app/workers/tasks.py').read_text()
    assert 'endpoint_hash=hashlib.sha256' in api and 'encrypt_secret' in api
    assert 'decrypt_secret' in service and 'vapid_private_key' in service and 'dispatch_mobile_push_task' in workers
def test_mobile_bootstrap_is_scoped():
    api=(ROOT/'app/api/v010.py').read_text()
    for term in ['Notification.user_id==u.id','ChannelMember.user_id==u.id','t.assignee_id==u.id','owned_device']: assert term in api
