diff options
Diffstat (limited to 'packages/meshbay-hub/tests')
43 files changed, 145 insertions, 131 deletions
diff --git a/packages/meshbay-hub/tests/conftest.py b/packages/meshbay-hub/tests/conftest.py index bf94464..bb0ed28 100644 --- a/packages/meshbay-hub/tests/conftest.py +++ b/packages/meshbay-hub/tests/conftest.py @@ -1,12 +1,12 @@ """Shared pytest fixtures for hub tests.""" import os +from pathlib import Path + import pytest import pytest_asyncio -from pathlib import Path -from unittest.mock import AsyncMock -from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey from cryptography.hazmat.primitives import serialization +from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey # Force SQLite in-memory for all hub tests os.environ.setdefault("MESHBAY_DATABASE_URL", "sqlite+aiosqlite:///:memory:") @@ -28,7 +28,13 @@ def hub_key_path(tmp_path_factory) -> Path: @pytest.fixture def hub_config(hub_key_path, tmp_path): - from meshbay_hub.config import HubConfig, DatabaseConfig, ServerConfig, HubIdentityConfig, JWTConfig + from meshbay_hub.config import ( + DatabaseConfig, + HubConfig, + HubIdentityConfig, + JWTConfig, + ServerConfig, + ) cfg = HubConfig( db=DatabaseConfig(url="sqlite+aiosqlite:///:memory:"), server=ServerConfig(host="127.0.0.1", port=8000), diff --git a/packages/meshbay-hub/tests/harness/boot_guard_probe.py b/packages/meshbay-hub/tests/harness/boot_guard_probe.py index 01751ba..b4a5e7c 100644 --- a/packages/meshbay-hub/tests/harness/boot_guard_probe.py +++ b/packages/meshbay-hub/tests/harness/boot_guard_probe.py @@ -83,7 +83,8 @@ const cases = []; const post = (o) => fetch('/log', { method: 'POST', body: JSON.stringify(o) }); addEventListener('error', (e) => post({ error: 'page error: ' + (e.message || e) })); addEventListener('unhandledrejection', - (e) => post({ error: 'rejection: ' + ((e.reason && (e.reason.stack || e.reason.message)) || e.reason) })); + (e) => post({ error: 'rejection: ' + + ((e.reason && (e.reason.stack || e.reason.message)) || e.reason) })); const sleep = (ms) => new Promise((r) => setTimeout(r, ms)); const add = (src) => { const f = document.createElement('iframe'); diff --git a/packages/meshbay-hub/tests/harness/chat_send_probe.py b/packages/meshbay-hub/tests/harness/chat_send_probe.py index b6dd957..d343c50 100644 --- a/packages/meshbay-hub/tests/harness/chat_send_probe.py +++ b/packages/meshbay-hub/tests/harness/chat_send_probe.py @@ -96,7 +96,6 @@ def _page() -> str: the page built itself would prove only that the page agrees with the page. """ import msgpack # noqa: F401 (imported for the failure it gives if absent) - from meshbay_common.groupbox import PURPOSE_CHAT_KEYS, seal sealed = seal(GEK, PURPOSE_CHAT_KEYS, "chat_keys_resp", GROUP_ID, diff --git a/packages/meshbay-hub/tests/harness/menu_scroll_probe.py b/packages/meshbay-hub/tests/harness/menu_scroll_probe.py index 5fb9579..c4d3b87 100755 --- a/packages/meshbay-hub/tests/harness/menu_scroll_probe.py +++ b/packages/meshbay-hub/tests/harness/menu_scroll_probe.py @@ -48,7 +48,8 @@ import { Menu } from '/menu.js'; const LOGS = []; addEventListener('error', (e) => LOGS.push('error: ' + (e.message || e))); addEventListener('unhandledrejection', - (e) => LOGS.push('rejection: ' + ((e.reason && (e.reason.stack || e.reason.message)) || e.reason))); + (e) => LOGS.push('rejection: ' + + ((e.reason && (e.reason.stack || e.reason.message)) || e.reason))); const sleep = (ms) => new Promise((r) => setTimeout(r, ms)); const frame = () => new Promise((r) => requestAnimationFrame(() => requestAnimationFrame(r))); diff --git a/packages/meshbay-hub/tests/harness/music_grid_probe.py b/packages/meshbay-hub/tests/harness/music_grid_probe.py index da73b1f..4f5b0ce 100644 --- a/packages/meshbay-hub/tests/harness/music_grid_probe.py +++ b/packages/meshbay-hub/tests/harness/music_grid_probe.py @@ -103,7 +103,8 @@ import { MusicPlayerBar } from '/music-player.js'; const LOGS = []; addEventListener('error', (e) => LOGS.push('error: ' + (e.message || e))); addEventListener('unhandledrejection', - (e) => LOGS.push('rejection: ' + ((e.reason && (e.reason.stack || e.reason.message)) || e.reason))); + (e) => LOGS.push('rejection: ' + + ((e.reason && (e.reason.stack || e.reason.message)) || e.reason))); const sleep = (ms) => new Promise((r) => setTimeout(r, ms)); const waitFor = async (sel, tries = 60) => { @@ -212,7 +213,8 @@ const clickMenu = async (i) => { const last = rows[rows.length - 1]; const entry = { artist: label, top, heading: heading ? heading.textContent : null, - headingH: heading ? Math.round(heading.getBoundingClientRect().height) : null }; + headingH: heading + ? Math.round(heading.getBoundingClientRect().height) : null }; if (last && Math.abs(last.top - top) < 8) last.cells.push(entry); else rows.push({ top, cells: [entry] }); } diff --git a/packages/meshbay-hub/tests/harness/music_queue_probe.py b/packages/meshbay-hub/tests/harness/music_queue_probe.py index 483c093..9be440b 100755 --- a/packages/meshbay-hub/tests/harness/music_queue_probe.py +++ b/packages/meshbay-hub/tests/harness/music_queue_probe.py @@ -102,7 +102,8 @@ import { MusicPlayerBar } from '/music-player.js'; const LOGS = []; addEventListener('error', (e) => LOGS.push('error: ' + (e.message || e))); addEventListener('unhandledrejection', - (e) => LOGS.push('rejection: ' + ((e.reason && (e.reason.stack || e.reason.message)) || e.reason))); + (e) => LOGS.push('rejection: ' + + ((e.reason && (e.reason.stack || e.reason.message)) || e.reason))); const sleep = (ms) => new Promise((r) => setTimeout(r, ms)); const waitFor = async (sel, tries = 60) => { diff --git a/packages/meshbay-hub/tests/harness/playlist_store_probe.py b/packages/meshbay-hub/tests/harness/playlist_store_probe.py index 6421426..9a54a0d 100755 --- a/packages/meshbay-hub/tests/harness/playlist_store_probe.py +++ b/packages/meshbay-hub/tests/harness/playlist_store_probe.py @@ -38,7 +38,8 @@ import { MANIFEST_KIND, bodyKind } from '/playlist-merge.js'; const LOGS = []; addEventListener('error', (e) => LOGS.push('error: ' + (e.message || e))); addEventListener('unhandledrejection', - (e) => LOGS.push('rejection: ' + ((e.reason && (e.reason.stack || e.reason.message)) || e.reason))); + (e) => LOGS.push('rejection: ' + + ((e.reason && (e.reason.stack || e.reason.message)) || e.reason))); const USER = 'user-1'; const steps = []; @@ -95,7 +96,8 @@ function fakeNode() { await P.addTracks(USER, P.FAVORITES_ID, [track(9)], 'g1', 'Favoris'); steps.push({ step: 'after editing', - list: (await P.listPlaylists(USER)).map((p) => ({ id: p.id, name: p.name, count: p.count })) }); + list: (await P.listPlaylists(USER)) + .map((p) => ({ id: p.id, name: p.name, count: p.count })) }); steps.push({ step: 'tracks read back', tracks: (await P.getPlaylistTracks(USER, eveningId)).map((t) => ({ diff --git a/packages/meshbay-hub/tests/harness/playlist_ui_probe.py b/packages/meshbay-hub/tests/harness/playlist_ui_probe.py index 2defed9..e6f99f7 100644 --- a/packages/meshbay-hub/tests/harness/playlist_ui_probe.py +++ b/packages/meshbay-hub/tests/harness/playlist_ui_probe.py @@ -101,7 +101,8 @@ import * as P from '/playlists.js'; const LOGS = []; addEventListener('error', (e) => LOGS.push('error: ' + (e.message || e))); addEventListener('unhandledrejection', - (e) => LOGS.push('rejection: ' + ((e.reason && (e.reason.stack || e.reason.message)) || e.reason))); + (e) => LOGS.push('rejection: ' + + ((e.reason && (e.reason.stack || e.reason.message)) || e.reason))); const sleep = (ms) => new Promise((r) => setTimeout(r, ms)); const waitFor = async (sel, tries = 60) => { @@ -256,7 +257,8 @@ const clickMenu = async (i) => { open.click(); await waitFor('.music-detail .music-tracklist'); steps.push({ step: 'loaded into the queue', - play: [...document.querySelectorAll('.music-detail .music-tracklist .music-track-title')] + play: [...document.querySelectorAll( + '.music-detail .music-tracklist .music-track-title')] .map((e) => e.textContent) }); document.querySelector('.music-detail .video-close').click(); await sleep(150); @@ -270,8 +272,10 @@ const clickMenu = async (i) => { await clickLabel('A2-t2'); await sleep(300); steps.push({ step: 'track removed', - lists: (await P.listPlaylists('u1')).map((p) => ({ name: p.name, count: p.count })), - tracks: (await P.getPlaylistTracks('u1', lists.find((p) => p.name === 'Soirée').id)) + lists: (await P.listPlaylists('u1')) + .map((p) => ({ name: p.name, count: p.count })), + tracks: (await P.getPlaylistTracks('u1', + lists.find((p) => p.name === 'Soirée').id)) .map((tr) => tr.display_title) }); // 6. Delete it. diff --git a/packages/meshbay-hub/tests/test_account_deletion.py b/packages/meshbay-hub/tests/test_account_deletion.py index 3d3fee4..2653f0d 100644 --- a/packages/meshbay-hub/tests/test_account_deletion.py +++ b/packages/meshbay-hub/tests/test_account_deletion.py @@ -12,9 +12,8 @@ command. import hashlib import pytest -from sqlalchemy import select - from meshbay_hub.db.models import GroupMember, Notification, RefreshToken, User +from sqlalchemy import select def _auth_key(password: str, username: str) -> str: diff --git a/packages/meshbay-hub/tests/test_account_pinning.py b/packages/meshbay-hub/tests/test_account_pinning.py index 192bd25..a1419c3 100644 --- a/packages/meshbay-hub/tests/test_account_pinning.py +++ b/packages/meshbay-hub/tests/test_account_pinning.py @@ -23,7 +23,6 @@ from pathlib import Path import pytest from cryptography.hazmat.primitives import serialization from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey - from meshbay_common.device import device_add_transcript STATIC = (Path(__file__).resolve().parents[1] diff --git a/packages/meshbay-hub/tests/test_admin_views.py b/packages/meshbay-hub/tests/test_admin_views.py index 5017b76..da2d3c9 100644 --- a/packages/meshbay-hub/tests/test_admin_views.py +++ b/packages/meshbay-hub/tests/test_admin_views.py @@ -11,9 +11,8 @@ import base64 import hashlib import pytest -from sqlalchemy import select - from meshbay_hub.db.models import User +from sqlalchemy import select def _auth_key(password: str, username: str) -> str: @@ -109,9 +108,8 @@ async def test_a_node_is_recorded_at_the_address_it_announced_from( import base64 import time - from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey from cryptography.hazmat.primitives import serialization - + from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey from meshbay_hub.db.models import Node admin = await _admin(client, db_session, "root4_test") diff --git a/packages/meshbay-hub/tests/test_asset_versioning.py b/packages/meshbay-hub/tests/test_asset_versioning.py index 0c93f5a..aa2dc6d 100644 --- a/packages/meshbay-hub/tests/test_asset_versioning.py +++ b/packages/meshbay-hub/tests/test_asset_versioning.py @@ -22,7 +22,6 @@ import re import pytest from fastapi.testclient import TestClient - from meshbay_hub.api.webapp import ASSET_V, STATIC_DIR, _asset_version from meshbay_hub.app import create_app diff --git a/packages/meshbay-hub/tests/test_availability_between_members.py b/packages/meshbay-hub/tests/test_availability_between_members.py index 2be7c03..4f5cbfb 100644 --- a/packages/meshbay-hub/tests/test_availability_between_members.py +++ b/packages/meshbay-hub/tests/test_availability_between_members.py @@ -24,7 +24,6 @@ import time import pytest from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey from cryptography.hazmat.primitives.asymmetric.x25519 import X25519PrivateKey - from meshbay_common.crypto import pk_to_b64 @@ -158,8 +157,7 @@ async def test_one_node_cannot_spend_the_hubs_database_on_notifications(): without backpressure. The budget is what stops one group's node from costing every other group on the instance. """ - from meshbay_hub.api.revocation import ( - NOTIFY_BURST, _notify_budget, _notify_window) + from meshbay_hub.api.revocation import NOTIFY_BURST, _notify_budget, _notify_window node = "budget-node" _notify_window.pop(node, None) @@ -265,8 +263,7 @@ def test_a_node_cannot_answer_an_offer_it_was_never_sent(): """ import asyncio - from meshbay_hub.api.signaling import ( - _answer_owner, _webrtc_answers, handle_webrtc_answer) + from meshbay_hub.api.signaling import _answer_owner, _webrtc_answers, handle_webrtc_answer loop = asyncio.new_event_loop() try: @@ -657,6 +654,7 @@ async def test_a_member_still_reaches_the_node_they_share_a_group_with(client): class _AnsweringWS: async def send_text(self, text): import json as _json + from meshbay_hub.api.signaling import handle_webrtc_answer msg = _json.loads(text) answered.append(msg) diff --git a/packages/meshbay-hub/tests/test_captcha_host_check.py b/packages/meshbay-hub/tests/test_captcha_host_check.py index 68cad34..778009f 100644 --- a/packages/meshbay-hub/tests/test_captcha_host_check.py +++ b/packages/meshbay-hub/tests/test_captcha_host_check.py @@ -31,12 +31,10 @@ TOML list is a typo far more often than an intention. import json import pytest - from meshbay_hub.captcha import verify_captcha from meshbay_hub.config import CaptchaConfig, load_config - class _Resp: def __init__(self, payload): self._payload = payload diff --git a/packages/meshbay-hub/tests/test_device_auth.py b/packages/meshbay-hub/tests/test_device_auth.py index e899f12..f9b172e 100644 --- a/packages/meshbay-hub/tests/test_device_auth.py +++ b/packages/meshbay-hub/tests/test_device_auth.py @@ -21,9 +21,7 @@ stopped being true. import base64 import time -import pytest from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey - from meshbay_common.crypto import pk_to_b64 diff --git a/packages/meshbay-hub/tests/test_files_drop_upload.py b/packages/meshbay-hub/tests/test_files_drop_upload.py index 5dfaf23..fc15c47 100644 --- a/packages/meshbay-hub/tests/test_files_drop_upload.py +++ b/packages/meshbay-hub/tests/test_files_drop_upload.py @@ -66,7 +66,8 @@ def test_names_in_a_folder_count_files_folders_and_empty_folders(tmp_path, sourc {"path": "music/Album", "name": "t.flac"}, {"path": "musicals", "name": "not-here.txt"}] got = _run(tmp_path, source, - f"namesIn({json.dumps(entries)}, ['music/Empty', 'music/Album/cd1'], 'music').sort()") + f"namesIn({json.dumps(entries)}, " + f"['music/Empty', 'music/Album/cd1'], 'music').sort()") assert got == ["Album", "Empty", "a.mp3"] diff --git a/packages/meshbay-hub/tests/test_group_hosting.py b/packages/meshbay-hub/tests/test_group_hosting.py index c571771..c6111f2 100644 --- a/packages/meshbay-hub/tests/test_group_hosting.py +++ b/packages/meshbay-hub/tests/test_group_hosting.py @@ -14,13 +14,12 @@ deleted every group during a hub restart. import base64 import hashlib -from datetime import datetime, timedelta, timezone +from datetime import UTC, datetime, timedelta import pytest -from sqlalchemy import select - from meshbay_hub.db.models import Group, GroupMember from meshbay_hub.tasks.cleanup import find_unhosted_groups, prune_unhosted_groups +from sqlalchemy import select def _auth_key(password: str, username: str) -> str: @@ -49,7 +48,7 @@ async def _group(client, owner, name, visibility="private", join_policy=None): async def _mark_hosted(db_session, group_id, when=None): g = await db_session.get(Group, group_id) - g.hosted_at = when or datetime.now(timezone.utc) + g.hosted_at = when or datetime.now(UTC) await db_session.commit() @@ -134,7 +133,7 @@ async def test_an_unhosted_group_past_the_grace_period_is_collected(client, db_s gid = (await _group(client, owner, "abandoned")).json()["group_id"] g = await db_session.get(Group, gid) - g.created_at = datetime.now(timezone.utc) - timedelta(days=8) + g.created_at = datetime.now(UTC) - timedelta(days=8) await db_session.commit() gone = await prune_unhosted_groups(db_session) @@ -149,8 +148,8 @@ async def test_an_old_group_that_was_hosted_is_never_collected(client, db_sessio gid = (await _group(client, owner, "long-lived")).json()["group_id"] g = await db_session.get(Group, gid) - g.created_at = datetime.now(timezone.utc) - timedelta(days=400) - g.hosted_at = datetime.now(timezone.utc) - timedelta(days=399) + g.created_at = datetime.now(UTC) - timedelta(days=400) + g.hosted_at = datetime.now(UTC) - timedelta(days=399) await db_session.commit() assert await find_unhosted_groups(db_session) == [] @@ -161,7 +160,7 @@ async def test_dry_run_reports_without_deleting(client, db_session): owner = await _user(client, "reaper4_test") gid = (await _group(client, owner, "still-here")).json()["group_id"] g = await db_session.get(Group, gid) - g.created_at = datetime.now(timezone.utc) - timedelta(days=30) + g.created_at = datetime.now(UTC) - timedelta(days=30) await db_session.commit() gone = await prune_unhosted_groups(db_session, dry_run=True) @@ -178,7 +177,7 @@ async def test_collecting_a_group_takes_its_memberships_with_it(client, db_sessi await client.post(f"/v1/groups/{gid}/members/tagalong", json={}, headers=owner) g = await db_session.get(Group, gid) - g.created_at = datetime.now(timezone.utc) - timedelta(days=9) + g.created_at = datetime.now(UTC) - timedelta(days=9) await db_session.commit() await prune_unhosted_groups(db_session) @@ -247,7 +246,7 @@ async def test_the_stamp_is_not_moved_by_a_later_reconnection(client, db_session owner = await _user(client, "stamped2") gid = (await _group(client, owner, "steady")).json()["group_id"] - first = datetime.now(timezone.utc) - timedelta(days=30) + first = datetime.now(UTC) - timedelta(days=30) await _mark_hosted([gid]) g = await db_session.get(Group, gid) g.hosted_at = first @@ -259,7 +258,7 @@ async def test_the_stamp_is_not_moved_by_a_later_reconnection(client, db_session await db_session.refresh(g) # SQLite hands back a naive datetime where PostgreSQL keeps the offset, so # the comparison is made on common ground rather than on the driver. - stored = g.hosted_at.replace(tzinfo=timezone.utc) if g.hosted_at.tzinfo is None \ + stored = g.hosted_at.replace(tzinfo=UTC) if g.hosted_at.tzinfo is None \ else g.hosted_at assert abs((stored - first).total_seconds()) < 1, "the stamp moved" diff --git a/packages/meshbay-hub/tests/test_group_leave_and_quota.py b/packages/meshbay-hub/tests/test_group_leave_and_quota.py index 4431f53..8af830d 100644 --- a/packages/meshbay-hub/tests/test_group_leave_and_quota.py +++ b/packages/meshbay-hub/tests/test_group_leave_and_quota.py @@ -14,13 +14,12 @@ removes them, and whoever left still holds the group key they were served. import base64 import hashlib -from datetime import datetime, timezone +from datetime import UTC, datetime import pytest -from sqlalchemy import select - from meshbay_hub.api.groups import MAX_PUBLIC_GROUPS from meshbay_hub.db.models import Group, GroupMember, User +from sqlalchemy import select def _auth_key(password: str, username: str) -> str: @@ -61,7 +60,7 @@ async def test_a_member_can_leave(client, db_session): # Marked hosted, or the member would not see the group in the first place # and the assertion below would hold whether or not leaving worked. g = await db_session.get(Group, gid) - g.hosted_at = datetime.now(timezone.utc) + g.hosted_at = datetime.now(UTC) await db_session.commit() before = await client.get("/v1/groups/mine", headers=member) diff --git a/packages/meshbay-hub/tests/test_group_membership.py b/packages/meshbay-hub/tests/test_group_membership.py index 2761595..ad1b3ab 100644 --- a/packages/meshbay-hub/tests/test_group_membership.py +++ b/packages/meshbay-hub/tests/test_group_membership.py @@ -11,10 +11,9 @@ import base64 import hashlib import pytest +from meshbay_hub.db.models import GroupMember, User from sqlalchemy import select -from meshbay_hub.db.models import Group, GroupMember, User - def _auth_key(password: str, username: str) -> str: salt = hashlib.sha256(f"meshbay:auth:v1:{username}".encode()).digest() diff --git a/packages/meshbay-hub/tests/test_group_purge.py b/packages/meshbay-hub/tests/test_group_purge.py index 0611dba..e729297 100644 --- a/packages/meshbay-hub/tests/test_group_purge.py +++ b/packages/meshbay-hub/tests/test_group_purge.py @@ -21,13 +21,18 @@ from datetime import UTC, datetime, timedelta import jwt import pytest -from sqlalchemy import delete, func, select, text -from sqlalchemy.exc import IntegrityError - from meshbay_hub.db.models import ( - ContentReport, EmailVerification, Group, GroupMember, IPLog, Notification, User, + ContentReport, + EmailVerification, + Group, + GroupMember, + IPLog, + Notification, + User, ) from meshbay_hub.db.purge import _referencing +from sqlalchemy import delete, func, select, text +from sqlalchemy.exc import IntegrityError SEEDED = {"group_members", "notifications", "email_verifications", "content_reports"} diff --git a/packages/meshbay-hub/tests/test_groups_self_service.py b/packages/meshbay-hub/tests/test_groups_self_service.py index f9346c1..a3a8f2d 100644 --- a/packages/meshbay-hub/tests/test_groups_self_service.py +++ b/packages/meshbay-hub/tests/test_groups_self_service.py @@ -1,9 +1,10 @@ """Integration tests for group self-service: create, join, members.""" +from datetime import UTC + import pytest from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey from cryptography.hazmat.primitives.asymmetric.x25519 import X25519PrivateKey - from meshbay_common.crypto import pk_to_b64 @@ -43,10 +44,11 @@ async def _create_group(client, token, name="test-group", visibility="public", async def _mark_hosted(db_session, *group_ids): """Pretend a node announced these groups, as /v1/nodes/ws would.""" - from datetime import datetime, timezone + from datetime import datetime + from meshbay_hub.db.models import Group for gid in group_ids: - (await db_session.get(Group, gid)).hosted_at = datetime.now(timezone.utc) + (await db_session.get(Group, gid)).hosted_at = datetime.now(UTC) await db_session.commit() diff --git a/packages/meshbay-hub/tests/test_hook_ordering.py b/packages/meshbay-hub/tests/test_hook_ordering.py index 3c82bb0..d03cdf5 100644 --- a/packages/meshbay-hub/tests/test_hook_ordering.py +++ b/packages/meshbay-hub/tests/test_hook_ordering.py @@ -123,7 +123,8 @@ def test_the_check_would_notice(): # Inject a dependency on `last` into the first declaration's dep array. end = broken.index("\n }, [", decls[0].start()) close = broken.index("]", end) - broken = broken[:close] + (", " if broken[end + 7:close].strip() else "") + last + broken[close:] + broken = (broken[:close] + (", " if broken[end + 7:close].strip() else "") + + last + broken[close:]) declared_at = {m.group(1): m.start() for m in DECL.finditer(broken)} caught = False diff --git a/packages/meshbay-hub/tests/test_hub_api.py b/packages/meshbay-hub/tests/test_hub_api.py index 37e8e4f..2afd27b 100644 --- a/packages/meshbay-hub/tests/test_hub_api.py +++ b/packages/meshbay-hub/tests/test_hub_api.py @@ -3,13 +3,11 @@ Integration tests for the Hub API. Uses SQLite in-memory + httpx.AsyncClient — no PostgreSQL, no network. """ -import base64 +from datetime import UTC + import pytest -import pytest_asyncio from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey from cryptography.hazmat.primitives.asymmetric.x25519 import X25519PrivateKey -from cryptography.hazmat.primitives import serialization - from meshbay_common.crypto import pk_to_b64 from meshbay_hub.api.deps import set_admin_usernames @@ -32,7 +30,8 @@ async def _announce_signed(client, token: str) -> tuple[str, str]: The node key is independent of the user's identity key, so this mints a fresh one and signs the domain-separated announce message with it. """ - import base64 as _b64, time as _t + import base64 as _b64 + import time as _t me = await client.get("/v1/users/me", headers={"Authorization": f"Bearer {token}"}) @@ -261,7 +260,9 @@ async def test_group_member_add(client): "pk_user_ed25519": pk_ed, "pk_user_x25519": pk_x}) alice_token = (await client.post("/v1/users/login", - json={"username": "alice2_test", "password": "alicepass99"})).json()["access_token"] + json={"username": "alice2_test", + "password": "alicepass99"}) + ).json()["access_token"] a_hdrs = {"Authorization": f"Bearer {alice_token}"} @@ -299,9 +300,13 @@ async def test_non_admin_cannot_add_member(client): "pk_user_ed25519": pk_ed, "pk_user_x25519": pk_x}) charlie_token = (await client.post("/v1/users/login", - json={"username": "charlie_test", "password": "charliepass"})).json()["access_token"] + json={"username": "charlie_test", + "password": "charliepass"}) + ).json()["access_token"] dan_token = (await client.post("/v1/users/login", - json={"username": "dan_test", "password": "danpass1234"})).json()["access_token"] + json={"username": "dan_test", + "password": "danpass1234"}) + ).json()["access_token"] r = await client.post("/v1/groups", json={"name": "charlies-group"}, headers={"Authorization": f"Bearer {charlie_token}"}) @@ -339,7 +344,9 @@ async def test_jwt_contains_groups_claim(client): # Alice creates a group and adds Bob alice_token = (await client.post("/v1/users/login", - json={"username": "grp_alice", "password": "alicepass99"})).json()["access_token"] + json={"username": "grp_alice", + "password": "alicepass99"}) + ).json()["access_token"] r = await client.post("/v1/groups", json={"name": "testgroup"}, headers={"Authorization": f"Bearer {alice_token}"}) group_id = r.json()["group_id"] @@ -399,9 +406,10 @@ async def test_my_groups(client, db_session): # A group no node has announced is shown to its owner only — a member would # otherwise see a name they cannot open. Stamped here so the rest of this # test is about membership, which is what it was written for. - from datetime import datetime, timezone + from datetime import datetime + from meshbay_hub.db.models import Group - (await db_session.get(Group, group_id)).hosted_at = datetime.now(timezone.utc) + (await db_session.get(Group, group_id)).hosted_at = datetime.now(UTC) await db_session.commit() # Re-login to get fresh token with group claims @@ -434,7 +442,6 @@ async def test_my_groups(client, db_session): @pytest.mark.asyncio async def test_group_online_nodes(client): """GET /v1/groups/{id}/nodes returns online nodes serving the group.""" - import json from meshbay_hub.api.revocation import _connected_nodes, _node_groups pk_ed, pk_x, _ = _gen_user_keys() @@ -541,7 +548,7 @@ async def test_admin_can_revoke(client): @pytest.mark.asyncio async def test_email_encrypted_at_rest(client): """Email stored in DB must not contain plaintext address.""" - from meshbay_hub.auth import encrypt_email, decrypt_email + from meshbay_hub.auth import decrypt_email, encrypt_email encrypted = encrypt_email("test@example.com") assert "@" not in encrypted assert decrypt_email(encrypted) == "test@example.com" @@ -589,9 +596,10 @@ async def test_password_rehash_on_login(client, app): user = result.scalar_one() user.pw_version = 1 # Re-hash with v1 params so verify_password(version=1) succeeds - from meshbay_hub.auth import _ARGON2_VERSIONS, _ARGON2_KEY_LEN, _ARGON2_LANES - from cryptography.hazmat.primitives.kdf.argon2 import Argon2id import os + + from cryptography.hazmat.primitives.kdf.argon2 import Argon2id + from meshbay_hub.auth import _ARGON2_KEY_LEN, _ARGON2_LANES, _ARGON2_VERSIONS salt = os.urandom(16) params = _ARGON2_VERSIONS[1] pw_hash = Argon2id( @@ -760,13 +768,14 @@ async def test_webrtc_signaling_roundtrip(client, app): @pytest.mark.asyncio async def test_ip_log_cleanup(app): """Old IP log entries are purged by cleanup task.""" - from datetime import datetime, timezone, timedelta + from datetime import datetime, timedelta + from meshbay_hub.db.engine import get_db from meshbay_hub.db.models import IPLog from meshbay_hub.tasks.cleanup import purge_old_ip_logs async for db in get_db(): - old_ts = datetime.now(timezone.utc) - timedelta(days=400) + old_ts = datetime.now(UTC) - timedelta(days=400) db.add(IPLog(event="test_old", ip_address="1.2.3.4", timestamp=old_ts)) db.add(IPLog(event="test_recent", ip_address="5.6.7.8")) await db.commit() @@ -774,7 +783,7 @@ async def test_ip_log_cleanup(app): deleted = await purge_old_ip_logs(db, retention_days=365) assert deleted == 1 - from sqlalchemy import select, func + from sqlalchemy import func, select count = (await db.execute( select(func.count()).where(IPLog.event.in_(["test_old", "test_recent"])) )).scalar_one() diff --git a/packages/meshbay-hub/tests/test_layout_measured.py b/packages/meshbay-hub/tests/test_layout_measured.py index a71b6b9..9bf1bde 100644 --- a/packages/meshbay-hub/tests/test_layout_measured.py +++ b/packages/meshbay-hub/tests/test_layout_measured.py @@ -178,7 +178,8 @@ GROUPED = textwrap.dedent(""" <button class="transfer-cancel">✕</button> </div> <div class="dl-progress"><div class="dl-fill" style="width:42%"></div></div> - <div class="transfer-meta"><span>210 MB / 493 MB</span><span>3.1 MB/s · 4 min left</span></div> + <div class="transfer-meta"><span>210 MB / 493 MB</span> + <span>3.1 MB/s · 4 min left</span></div> </div> </div> <div class="transfer-group"> @@ -190,7 +191,8 @@ GROUPED = textwrap.dedent(""" <button class="transfer-cancel">✕</button> </div> <div class="dl-progress dl-waiting"></div> - <div class="transfer-meta"><span>Waiting — your slots are busy</span><span>1.2 GB</span></div> + <div class="transfer-meta"><span>Waiting — your slots are busy</span> + <span>1.2 GB</span></div> </div> </div> </div> diff --git a/packages/meshbay-hub/tests/test_locales.py b/packages/meshbay-hub/tests/test_locales.py index 59ea2bf..602d161 100644 --- a/packages/meshbay-hub/tests/test_locales.py +++ b/packages/meshbay-hub/tests/test_locales.py @@ -158,7 +158,8 @@ def test_locale_resolution_is_region_aware(tmp_path): const out = {}; for (const tags of [['pt-BR'], ['pt'], ['zh-CN'], ['zh'], ['fr-CA'], ['de-AT'], ['ru', 'it'], ['ko']]) { - Object.defineProperty(globalThis, 'navigator', { value: { languages: tags, language: tags[0] }, configurable: true }); + Object.defineProperty(globalThis, 'navigator', + { value: { languages: tags, language: tags[0] }, configurable: true }); delete store.mb_lang; out[tags.join(',')] = await i18n.initLocale(); } @@ -186,7 +187,8 @@ def test_counted_string_picks_the_right_polish_form(tmp_path): setItem: (k, v) => { store[k] = v; }, }; globalThis.document = { documentElement: {} }; - Object.defineProperty(globalThis, 'navigator', { value: { languages: ['pl'], language: 'pl' }, configurable: true }); + Object.defineProperty(globalThis, 'navigator', + { value: { languages: ['pl'], language: 'pl' }, configurable: true }); const i18n = await import('./i18n.js'); await i18n.initLocale(); console.log(JSON.stringify( @@ -205,7 +207,8 @@ def test_interpolated_value_is_not_read_as_a_replacement_pattern(tmp_path): setItem: (k, v) => { store[k] = v; }, }; globalThis.document = { documentElement: {} }; - Object.defineProperty(globalThis, 'navigator', { value: { languages: ['en'], language: 'en' }, configurable: true }); + Object.defineProperty(globalThis, 'navigator', + { value: { languages: ['en'], language: 'en' }, configurable: true }); const i18n = await import('./i18n.js'); await i18n.initLocale(); console.log(JSON.stringify( diff --git a/packages/meshbay-hub/tests/test_login_lockout.py b/packages/meshbay-hub/tests/test_login_lockout.py index 6f17d98..601edbd 100644 --- a/packages/meshbay-hub/tests/test_login_lockout.py +++ b/packages/meshbay-hub/tests/test_login_lockout.py @@ -18,14 +18,13 @@ is `test_availability_between_members.py`, because it takes two accounts. """ import asyncio -from datetime import datetime, timedelta, timezone +from datetime import UTC, datetime, timedelta import pytest -from sqlalchemy import select, update - from meshbay_hub.api.deps import set_admin_usernames from meshbay_hub.db.models import LoginThrottle from meshbay_hub.login_throttle import _key +from sqlalchemy import select, update RIGHT = "r" * 44 WRONG = "w" * 44 @@ -94,7 +93,7 @@ async def test_a_lockout_ends_when_its_window_does(client, db_session): await db_session.execute( update(LoginThrottle).where(LoginThrottle.key == _key("dave_test")) - .values(last_failure_at=datetime.now(timezone.utc) - timedelta(minutes=61))) + .values(last_failure_at=datetime.now(UTC) - timedelta(minutes=61))) await db_session.commit() assert (await _login(client, "dave_test", RIGHT)).status_code == 200 @@ -106,7 +105,7 @@ async def test_old_failures_do_not_carry_into_a_new_window(client, db_session): await _fail(client, "erin_test", 3) await db_session.execute( update(LoginThrottle).where(LoginThrottle.key == _key("erin_test")) - .values(last_failure_at=datetime.now(timezone.utc) - timedelta(minutes=61))) + .values(last_failure_at=datetime.now(UTC) - timedelta(minutes=61))) await db_session.commit() # One stale window of three, then one fresh failure: a count of one, not four. diff --git a/packages/meshbay-hub/tests/test_mail_is_not_a_relay.py b/packages/meshbay-hub/tests/test_mail_is_not_a_relay.py index fe6a5ee..a3f9a21 100644 --- a/packages/meshbay-hub/tests/test_mail_is_not_a_relay.py +++ b/packages/meshbay-hub/tests/test_mail_is_not_a_relay.py @@ -28,7 +28,6 @@ import base64 import pytest from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey from cryptography.hazmat.primitives.asymmetric.x25519 import X25519PrivateKey - from meshbay_common.crypto import pk_to_b64 from meshbay_hub import mail as mail_mod from meshbay_hub.api import users as users_mod @@ -316,9 +315,8 @@ async def _signed_in(client, db_session, username: str, email: str) -> dict: genuinely `pending` here, exactly as it would be in production, and a pending account cannot log in. """ - from sqlalchemy import select, update - from meshbay_hub.db.models import User + from sqlalchemy import select, update r = await _register(client, username, email) assert r.status_code == 201, r.text @@ -406,9 +404,8 @@ async def test_the_delay_survives_the_verification_row_being_deleted( json={"email": "c-first@example.test"}) assert r.status_code == 200, r.text - from sqlalchemy import delete - from meshbay_hub.db.models import EmailVerification + from sqlalchemy import delete await db_session.execute(delete(EmailVerification)) await db_session.commit() @@ -421,9 +418,8 @@ async def test_the_delay_survives_the_verification_row_being_deleted( # ── The operator's controls ────────────────────────────────────────────────── async def _admin(client, db_session, username: str) -> dict: - from sqlalchemy import update - from meshbay_hub.db.models import User + from sqlalchemy import update headers = await _signed_in(client, db_session, username, f"{username}@example.test") @@ -491,9 +487,8 @@ async def test_an_unknown_mail_setting_is_refused(client, db_session): @pytest.mark.asyncio async def test_a_moderator_may_read_the_bounds_but_not_change_them( client, db_session): - from sqlalchemy import update - from meshbay_hub.db.models import User + from sqlalchemy import update headers = await _signed_in(client, db_session, "mailmod_test", "mailmod@example.test") diff --git a/packages/meshbay-hub/tests/test_memory_ceiling.py b/packages/meshbay-hub/tests/test_memory_ceiling.py index 1654825..5984292 100644 --- a/packages/meshbay-hub/tests/test_memory_ceiling.py +++ b/packages/meshbay-hub/tests/test_memory_ceiling.py @@ -246,11 +246,11 @@ def test_no_unguarded_memory_floor(target_fn): # definition out before looking. Comments go too — the branch that used to # be the bug is now described in one, and a test that reads prose is the # mistake already recorded in CLAUDE.md for the packaged systemd unit. - start = next(n for n, l in enumerate(lines) if "const _memoryFloor" in l) + start = next(n for n, ln in enumerate(lines) if "const _memoryFloor" in ln) end = next(n for n in range(start, len(lines)) if lines[n].strip() == "};") rest = lines[:start] + lines[end + 1:] - code = [re.sub(r"//.*$", "", l) for l in rest] - bare = [l.strip() for l in code if re.search(r"\breturn null\b", l)] + code = [re.sub(r"//.*$", "", ln) for ln in rest] + bare = [ln.strip() for ln in code if re.search(r"\breturn null\b", ln)] assert bare == [], ( "an unguarded in-memory fallback was added to _openDownloadTarget; " "return _memoryFloor() instead: " + "; ".join(bare)) diff --git a/packages/meshbay-hub/tests/test_migrations_reach_head.py b/packages/meshbay-hub/tests/test_migrations_reach_head.py index 13c5590..7f0d5df 100644 --- a/packages/meshbay-hub/tests/test_migrations_reach_head.py +++ b/packages/meshbay-hub/tests/test_migrations_reach_head.py @@ -30,9 +30,8 @@ from pathlib import Path import pytest from alembic import command from alembic.config import Config -from sqlalchemy import create_engine, inspect - from meshbay_hub.db.models import Base +from sqlalchemy import create_engine, inspect HUB = Path(__file__).resolve().parents[1] diff --git a/packages/meshbay-hub/tests/test_node_auth.py b/packages/meshbay-hub/tests/test_node_auth.py index 4137932..09816de 100644 --- a/packages/meshbay-hub/tests/test_node_auth.py +++ b/packages/meshbay-hub/tests/test_node_auth.py @@ -8,9 +8,9 @@ import base64 import time import pytest +from cryptography.hazmat.primitives import serialization from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey from cryptography.hazmat.primitives.asymmetric.x25519 import X25519PrivateKey -from cryptography.hazmat.primitives import serialization def _gen_ed25519(): diff --git a/packages/meshbay-hub/tests/test_node_ws_auth.py b/packages/meshbay-hub/tests/test_node_ws_auth.py index f3ac3a2..7d96851 100644 --- a/packages/meshbay-hub/tests/test_node_ws_auth.py +++ b/packages/meshbay-hub/tests/test_node_ws_auth.py @@ -16,7 +16,6 @@ import base64 import pytest from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey from cryptography.hazmat.primitives.asymmetric.x25519 import X25519PrivateKey - from meshbay_common.crypto import pk_to_b64 @@ -405,7 +404,10 @@ async def test_empty_node_cannot_shadow_another_members_group(client): source for that group, because it is the one clients would reach first. """ from meshbay_hub.api.revocation import ( - _authorize_node_ws, _node_groups, get_online_nodes_for_group) + _authorize_node_ws, + _node_groups, + get_online_nodes_for_group, + ) host = await _make_user(client, "hoster_test") guest = await _make_user(client, "guest_test") diff --git a/packages/meshbay-hub/tests/test_notification_dismissal.py b/packages/meshbay-hub/tests/test_notification_dismissal.py index 1c9c7b3..d498b4d 100644 --- a/packages/meshbay-hub/tests/test_notification_dismissal.py +++ b/packages/meshbay-hub/tests/test_notification_dismissal.py @@ -32,7 +32,6 @@ from pathlib import Path import pytest from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey from cryptography.hazmat.primitives.asymmetric.x25519 import X25519PrivateKey - from meshbay_common.crypto import pk_to_b64 from meshbay_hub.api.deps import set_admin_usernames diff --git a/packages/meshbay-hub/tests/test_notifications.py b/packages/meshbay-hub/tests/test_notifications.py index 02aca1c..b87e1d5 100644 --- a/packages/meshbay-hub/tests/test_notifications.py +++ b/packages/meshbay-hub/tests/test_notifications.py @@ -3,7 +3,6 @@ import pytest from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey from cryptography.hazmat.primitives.asymmetric.x25519 import X25519PrivateKey - from meshbay_common.crypto import pk_to_b64 from meshbay_hub.api.deps import set_admin_usernames diff --git a/packages/meshbay-hub/tests/test_notifications_behaviour.py b/packages/meshbay-hub/tests/test_notifications_behaviour.py index a247508..4684d3f 100644 --- a/packages/meshbay-hub/tests/test_notifications_behaviour.py +++ b/packages/meshbay-hub/tests/test_notifications_behaviour.py @@ -7,13 +7,12 @@ browser's localStorage and nothing read it), and there was no way to clear the list. """ -import hashlib import base64 +import hashlib import pytest -from sqlalchemy import select - from meshbay_hub.db.models import GroupMember, Notification, User +from sqlalchemy import select def _auth_key(password: str, username: str) -> str: @@ -36,7 +35,7 @@ async def test_chat_keeps_one_notification_per_group(client, db_session): """Forty messages are one line saying when the conversation last spoke.""" from meshbay_hub.api.notifications import create_notification - token = await _user(client, "listener") + await _user(client, "listener") owner = await _user(client, "talker_test") g = await client.post("/v1/groups", json={"name": "busy"}, headers={"Authorization": f"Bearer {owner}"}) diff --git a/packages/meshbay-hub/tests/test_packaging_hub_unit.py b/packages/meshbay-hub/tests/test_packaging_hub_unit.py index 7d8f5d2..e29164e 100644 --- a/packages/meshbay-hub/tests/test_packaging_hub_unit.py +++ b/packages/meshbay-hub/tests/test_packaging_hub_unit.py @@ -85,7 +85,6 @@ def test_the_command_resolves_from_the_installed_package_not_the_checkout(): """Derived from `meshbay_hub.__file__`, so it is correct in a venv, an RPM and a checkout alike — which is the whole point of not writing it down.""" import meshbay_hub - from meshbay_hub.daemon import migrations_dir assert migrations_dir() == ( diff --git a/packages/meshbay-hub/tests/test_password_change.py b/packages/meshbay-hub/tests/test_password_change.py index b2fe586..bfe0c97 100644 --- a/packages/meshbay-hub/tests/test_password_change.py +++ b/packages/meshbay-hub/tests/test_password_change.py @@ -11,9 +11,8 @@ import base64 import hashlib import pytest -from sqlalchemy import select - from meshbay_hub.db.models import IPLog, RefreshToken, User +from sqlalchemy import select def _auth_key(password: str, username: str) -> str: diff --git a/packages/meshbay-hub/tests/test_password_reset.py b/packages/meshbay-hub/tests/test_password_reset.py index 823807c..b07f77c 100644 --- a/packages/meshbay-hub/tests/test_password_reset.py +++ b/packages/meshbay-hub/tests/test_password_reset.py @@ -9,7 +9,7 @@ the recovery key and is not exercised here. import base64 import time -from datetime import datetime, timedelta, timezone +from datetime import UTC, datetime, timedelta import pytest from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey @@ -126,7 +126,7 @@ async def test_an_expired_code_is_refused(client, db_session): select(User.id).where(User.username == "carol_test"))).scalar_one() row = (await db_session.execute(select(EmailVerification).where( EmailVerification.user_id == uid))).scalars().one() - row.expires_at = datetime.now(timezone.utc) - timedelta(minutes=1) + row.expires_at = datetime.now(UTC) - timedelta(minutes=1) await db_session.commit() r = await client.post("/v1/users/password/reset", json={ diff --git a/packages/meshbay-hub/tests/test_public_groups_toggle.py b/packages/meshbay-hub/tests/test_public_groups_toggle.py index 96e3383..dbc6a38 100644 --- a/packages/meshbay-hub/tests/test_public_groups_toggle.py +++ b/packages/meshbay-hub/tests/test_public_groups_toggle.py @@ -17,7 +17,7 @@ and their access — plan A, not a purge. import base64 import hashlib -from datetime import datetime, timezone +from datetime import UTC, datetime import pytest from meshbay_hub.api.deps import set_admin_usernames @@ -61,7 +61,7 @@ async def _create_public(client, owner, name): async def _mark_hosted(db_session, *group_ids): """Pretend a node announced these groups, as /v1/nodes/ws would.""" for gid in group_ids: - (await db_session.get(Group, gid)).hosted_at = datetime.now(timezone.utc) + (await db_session.get(Group, gid)).hosted_at = datetime.now(UTC) await db_session.commit() diff --git a/packages/meshbay-hub/tests/test_revocation.py b/packages/meshbay-hub/tests/test_revocation.py index ad9caf4..e2ca5e7 100644 --- a/packages/meshbay-hub/tests/test_revocation.py +++ b/packages/meshbay-hub/tests/test_revocation.py @@ -1,11 +1,9 @@ """Tests for revocation — admin endpoint + token signing.""" -import time -import pytest import jwt +import pytest from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey from cryptography.hazmat.primitives.asymmetric.x25519 import X25519PrivateKey - from meshbay_common.crypto import pk_to_b64 from meshbay_hub.api.deps import set_admin_usernames diff --git a/packages/meshbay-hub/tests/test_session_lifetime.py b/packages/meshbay-hub/tests/test_session_lifetime.py index af73767..3a1f47a 100644 --- a/packages/meshbay-hub/tests/test_session_lifetime.py +++ b/packages/meshbay-hub/tests/test_session_lifetime.py @@ -6,13 +6,12 @@ maximum — plus a sign-out the hub honours and "sign out everywhere". The browser half is `test_browser_idle_signout.py`; this is the hub's. """ -from datetime import datetime, timedelta, timezone +from datetime import UTC, datetime, timedelta import pytest -from sqlalchemy import select, update - from meshbay_hub.api.deps import set_admin_usernames from meshbay_hub.db.models import RefreshToken, User +from sqlalchemy import select, update AUTH_KEY = "s" * 44 @@ -40,7 +39,7 @@ async def _refresh(client, token): def _aware(dt): - return dt if dt.tzinfo else dt.replace(tzinfo=timezone.utc) + return dt if dt.tzinfo else dt.replace(tzinfo=UTC) async def _expiry(db_session, username): @@ -66,7 +65,7 @@ async def test_the_defaults_are_in_the_panel_and_the_browser_delay_is_public(cli async def test_a_refresh_token_lasts_the_idle_window(client, db_session): await _register(client, "idle_window") await _login(client, "idle_window") - left = await _expiry(db_session, "idle_window") - datetime.now(timezone.utc) + left = await _expiry(db_session, "idle_window") - datetime.now(UTC) assert timedelta(hours=23, minutes=58) < left <= timedelta(hours=24) @@ -78,7 +77,7 @@ async def test_the_idle_window_never_undercuts_the_access_token(client, db_sessi json={"session": {"refresh_idle_hours": 1}}) await _register(client, "short_idle") await _login(client, "short_idle") - left = await _expiry(db_session, "short_idle") - datetime.now(timezone.utc) + left = await _expiry(db_session, "short_idle") - datetime.now(UTC) # The test hub's access token lives 3600 s; the floor is that plus an hour. assert left > timedelta(hours=1, minutes=58) @@ -98,7 +97,7 @@ async def test_no_session_renews_past_its_maximum(client, db_session): select(User.id).where(User.username == "long_session"))).scalar_one() await db_session.execute( update(RefreshToken).where(RefreshToken.user_id == uid) - .values(created_at=datetime.now(timezone.utc) - timedelta(hours=721))) + .values(created_at=datetime.now(UTC) - timedelta(hours=721))) await db_session.commit() r = await _refresh(client, current) diff --git a/packages/meshbay-hub/tests/test_session_renewal.py b/packages/meshbay-hub/tests/test_session_renewal.py index 5d4bcfd..7b8c108 100644 --- a/packages/meshbay-hub/tests/test_session_renewal.py +++ b/packages/meshbay-hub/tests/test_session_renewal.py @@ -26,9 +26,9 @@ broken client. """ import json +import re import shutil import subprocess -import re from pathlib import Path import pytest diff --git a/packages/meshbay-hub/tests/test_table_rows_measured.py b/packages/meshbay-hub/tests/test_table_rows_measured.py index 60ec878..f203624 100644 --- a/packages/meshbay-hub/tests/test_table_rows_measured.py +++ b/packages/meshbay-hub/tests/test_table_rows_measured.py @@ -16,11 +16,10 @@ rectangles show it does not — which is what this file is for. """ import json +import shutil import subprocess from pathlib import Path -import shutil - import pytest HARNESS = Path(__file__).parent / "harness" / "layout_probe.py" diff --git a/packages/meshbay-hub/tests/test_transfers.py b/packages/meshbay-hub/tests/test_transfers.py index a776b50..9b65ca5 100644 --- a/packages/meshbay-hub/tests/test_transfers.py +++ b/packages/meshbay-hub/tests/test_transfers.py @@ -243,7 +243,10 @@ class L { acquire() { return this._wait; } release(reason) { if (!this.closed) { this.closed = true; this.released.push(reason); } } grant() { this.state = 'granted'; if (this._onState) this._onState(this); this._go(); } - push(state, ahead) { this.state = state; this.ahead = ahead; if (this._onState) this._onState(this); } + push(state, ahead) { + this.state = state; this.ahead = ahead; + if (this._onState) this._onState(this); + } } """ |