b824f6d405
- Support invite code discovery in main chat and redemption in settings menu - Add Settings RPA primitives with Radix UI mouse dispatch and retry polling for async DOM - Attribute 'has_redeemed' binary from the Additional tokens ticker / entrypoint visibility - Unblock agent @646 by repairing warp-def/dev tunnels and redeeming REDCJ7 via dev (+1B tokens) - Implement 'box onboard' pipeline to provision infra, authenticate, and auto-redeem queued codes - Add 'box onboard feed-matrix' ranking all agents by work done over time, job count, and role - Register 'InputType.SALVAGE' in loop modulation (CRITICAL priority, 600s timeout, 3 nudges to opm) - Ingest recurring balance audits into canonical HEARTBEAT.md and TOOLS.md
262 lines
10 KiB
Python
262 lines
10 KiB
Python
"""Tests for the invite code + usage handler (mocked CDP).
|
||
|
||
No live browser traffic: get_cdp_ws / cdp_evaluate are patched and the
|
||
DOM/API contracts asserted from fixtures captured live from muse.ai.
|
||
"""
|
||
import sys
|
||
import unittest
|
||
from pathlib import Path
|
||
from unittest import mock
|
||
|
||
REPO_ROOT = Path(__file__).resolve().parent.parent
|
||
sys.path.insert(0, str(REPO_ROOT / "bin"))
|
||
|
||
import invite
|
||
|
||
API_OK = {"status": 200, "data": {
|
||
"code": "F4BGHN", "has_redeemed_invite_code": True,
|
||
"uses_remaining": 30, "use_count": 0, "reward": None}}
|
||
|
||
POPOVER_TEXT = (
|
||
"Invite friends\n\nInvite a friend and you'll both get 1 billion Muse "
|
||
"tokens when they redeem your code in Settings within 48 hours of "
|
||
"joining. 30 uses left.\n\nF4BGHN\n"
|
||
"Invite code revealed: F4BGHN\nCopy referral link")
|
||
|
||
PIP_GENERAL = (
|
||
"General\nWallet\nWeekly limit resets on Oct 10\n100% used\n"
|
||
"Additional tokens\nNever expires\n10% used (901M tokens left)\n"
|
||
"Upgrade\nLanguage\nAppearance\nMode\nTheme color")
|
||
|
||
SIX_GENERAL = (
|
||
"100% used\nAdditional tokens\nNever expires\n"
|
||
"100% used (0 tokens left)\nUpgrade\nLanguage\nAppearance\n"
|
||
"Mode\nTheme color")
|
||
|
||
|
||
class NormalizeTests(unittest.TestCase):
|
||
def test_accepts_and_normalizes(self):
|
||
self.assertEqual(invite.normalize_code("F4BGHN"), "F4BGHN")
|
||
self.assertEqual(invite.normalize_code("f4bghn"), "F4BGHN")
|
||
self.assertEqual(invite.normalize_code(" redcj7\n"), "REDCJ7")
|
||
|
||
def test_rejects_malformed(self):
|
||
for bad in ("", "ABC12", "ABCDEFG", "ABC-12", "ABC 12",
|
||
"abcde!", None, 123, "F4BGH\nN"):
|
||
self.assertIsNone(invite.normalize_code(bad), bad)
|
||
|
||
|
||
class GetInviteTests(unittest.TestCase):
|
||
def setUp(self):
|
||
p = mock.patch("time.sleep")
|
||
p.start()
|
||
self.addCleanup(p.stop)
|
||
g = mock.patch.object(invite, "get_cdp_ws",
|
||
return_value=(mock.Mock(), {}))
|
||
self.get_ws = g.start()
|
||
self.addCleanup(g.stop)
|
||
c = mock.patch.object(invite, "cdp_evaluate")
|
||
self.cdp = c.start()
|
||
self.addCleanup(c.stop)
|
||
|
||
def test_bad_node_before_cdp(self):
|
||
with self.assertRaises(invite.InviteError):
|
||
invite.get_invite("nope")
|
||
self.get_ws.assert_not_called()
|
||
|
||
def test_api_success(self):
|
||
self.cdp.return_value = dict(API_OK)
|
||
res = invite.get_invite("pip")
|
||
self.assertEqual(res, {"ok": True, "node": "pip", "source": "api",
|
||
"code": "F4BGHN", "has_redeemed": True,
|
||
"uses_remaining": 30, "use_count": 0,
|
||
"reward": None})
|
||
|
||
def test_api_failure_falls_back_to_popover(self):
|
||
self.cdp.side_effect = [{"error": "boom"}, "CLICKED",
|
||
POPOVER_TEXT, "ESC"]
|
||
res = invite.get_invite("pip")
|
||
self.assertTrue(res["ok"])
|
||
self.assertEqual(res["source"], "dom")
|
||
self.assertEqual(res["code"], "F4BGHN")
|
||
self.assertIsNone(res["has_redeemed"])
|
||
|
||
def test_no_api_no_popover(self):
|
||
self.cdp.side_effect = [None, "NO_BUTTON", "ESC"]
|
||
res = invite.get_invite("pip")
|
||
self.assertFalse(res["ok"])
|
||
self.assertIn("popover", res["error"])
|
||
|
||
def test_connection_error(self):
|
||
self.get_ws.side_effect = ConnectionError("refused")
|
||
res = invite.get_invite("def")
|
||
self.assertFalse(res["ok"])
|
||
self.assertIn("CDP", res["error"])
|
||
|
||
|
||
class RedeemTests(unittest.TestCase):
|
||
def setUp(self):
|
||
g = mock.patch.object(invite, "get_cdp_ws",
|
||
return_value=(mock.Mock(), {}))
|
||
self.get_ws = g.start()
|
||
self.addCleanup(g.stop)
|
||
c = mock.patch.object(invite, "cdp_evaluate")
|
||
self.cdp = c.start()
|
||
self.addCleanup(c.stop)
|
||
|
||
def test_bad_code_before_cdp(self):
|
||
for bad in ("xyz", "", None, "ABC-12"):
|
||
with self.assertRaises(invite.InviteError, msg=bad):
|
||
invite.redeem_invite("646", bad)
|
||
self.get_ws.assert_not_called()
|
||
|
||
def test_bad_node_before_cdp(self):
|
||
with self.assertRaises(invite.InviteError):
|
||
invite.redeem_invite("nope", "F4BGHN")
|
||
self.get_ws.assert_not_called()
|
||
|
||
def test_success(self):
|
||
self.cdp.return_value = {"status": 200, "ok": True, "data": {
|
||
"success": True, "redemptionStatus": "redeemed",
|
||
"detail": "You both got 1 billion Muse tokens."}}
|
||
res = invite.redeem_invite("646", "f4bghn")
|
||
self.assertTrue(res["ok"])
|
||
self.assertEqual(res["code"], "F4BGHN")
|
||
self.assertEqual(res["redemption_status"], "redeemed")
|
||
sent_js = self.cdp.call_args[0][1]
|
||
self.assertIn("F4BGHN", sent_js)
|
||
|
||
def test_reason_passthrough(self):
|
||
self.cdp.return_value = {"status": 400, "ok": False, "data": {
|
||
"success": False, "reason": "already_redeemed",
|
||
"detail": "You’ve already redeemed an invite code."}}
|
||
res = invite.redeem_invite("muse", "REDCJ7")
|
||
self.assertFalse(res["ok"])
|
||
self.assertEqual(res["reason"], "already_redeemed")
|
||
self.assertIn("already redeemed", res["detail"])
|
||
|
||
def test_transport_error(self):
|
||
self.cdp.side_effect = RuntimeError("ws blew up")
|
||
res = invite.redeem_invite("646", "F4BGHN")
|
||
self.assertFalse(res["ok"])
|
||
self.assertIn("ws blew up", res["error"])
|
||
|
||
def test_connection_error(self):
|
||
self.get_ws.side_effect = ConnectionError("refused")
|
||
res = invite.redeem_invite("646", "F4BGHN")
|
||
self.assertFalse(res["ok"])
|
||
self.assertEqual(res["code"], "F4BGHN")
|
||
|
||
|
||
class UsageTests(unittest.TestCase):
|
||
def test_parse_pip_general(self):
|
||
self.assertEqual(invite.parse_usage_text(PIP_GENERAL), {
|
||
"weekly_reset": "Oct 10", "weekly_used_pct": 100,
|
||
"additional_expires": "Never expires",
|
||
"additional_used_pct": 10,
|
||
"additional_left": "901M tokens left",
|
||
"has_redeemed": True})
|
||
|
||
def test_parse_646_general_partial(self):
|
||
self.assertEqual(invite.parse_usage_text(SIX_GENERAL), {
|
||
"weekly_reset": None, "weekly_used_pct": 100,
|
||
"additional_expires": "Never expires",
|
||
"additional_used_pct": 100,
|
||
"additional_left": "0 tokens left",
|
||
"has_redeemed": True})
|
||
|
||
def test_parse_empty(self):
|
||
self.assertEqual(invite.parse_usage_text(""), {
|
||
"weekly_reset": None, "weekly_used_pct": None,
|
||
"additional_expires": None, "additional_used_pct": None,
|
||
"additional_left": None, "has_redeemed": False})
|
||
|
||
def test_bad_node_before_cdp(self):
|
||
with mock.patch.object(invite, "get_cdp_ws") as g:
|
||
with self.assertRaises(invite.InviteError):
|
||
invite.get_usage("nope")
|
||
g.assert_not_called()
|
||
|
||
def test_settings_open_failure(self):
|
||
with mock.patch.object(invite, "get_cdp_ws",
|
||
return_value=(mock.Mock(), {})), \
|
||
mock.patch.object(invite, "open_settings",
|
||
return_value=False):
|
||
res = invite.get_usage("pip")
|
||
self.assertFalse(res["ok"])
|
||
self.assertIn("did not open", res["error"])
|
||
|
||
def test_success(self):
|
||
with mock.patch.object(invite, "get_cdp_ws",
|
||
return_value=(mock.Mock(), {})), \
|
||
mock.patch.object(invite, "open_settings",
|
||
return_value=True), \
|
||
mock.patch("hatch_menu.dialog.goto_tab",
|
||
return_value=True), \
|
||
mock.patch("hatch_menu.dialog.dialog_text",
|
||
return_value=PIP_GENERAL):
|
||
res = invite.get_usage("pip")
|
||
self.assertTrue(res["ok"])
|
||
self.assertEqual(res["weekly_reset"], "Oct 10")
|
||
self.assertEqual(res["additional_left"], "901M tokens left")
|
||
self.assertTrue(res["has_redeemed"])
|
||
|
||
def test_general_tab_failure(self):
|
||
with mock.patch.object(invite, "get_cdp_ws",
|
||
return_value=(mock.Mock(), {})), \
|
||
mock.patch.object(invite, "open_settings",
|
||
return_value=True), \
|
||
mock.patch("hatch_menu.dialog.goto_tab",
|
||
return_value=False):
|
||
res = invite.get_usage("pip")
|
||
self.assertFalse(res["ok"])
|
||
self.assertIn("General tab", res["error"])
|
||
|
||
|
||
class FleetTests(unittest.TestCase):
|
||
def test_invite_status_aggregates_and_never_raises(self):
|
||
with mock.patch.object(
|
||
invite, "get_invite",
|
||
side_effect=[{"ok": True, "node": "646"},
|
||
invite.InviteError("bad")]):
|
||
res = invite.fleet_invite_status(["646", "bogus"])
|
||
self.assertTrue(res["646"]["ok"])
|
||
self.assertFalse(res["bogus"]["ok"])
|
||
|
||
def test_usage_aggregates(self):
|
||
with mock.patch.object(
|
||
invite, "get_usage",
|
||
return_value={"ok": True, "node": "pip"}):
|
||
res = invite.fleet_usage(["pip"])
|
||
self.assertTrue(res["pip"]["ok"])
|
||
|
||
|
||
class ShimTests(unittest.TestCase):
|
||
"""open_settings/click_settings_tab delegate to the tree (single copy).
|
||
|
||
Trusted-click behavior itself is covered by tests/test_hatch_menu.py.
|
||
"""
|
||
|
||
def test_open_settings_delegates(self):
|
||
ws = mock.Mock()
|
||
with mock.patch("hatch_menu.dialog.open_settings",
|
||
return_value=True) as m:
|
||
self.assertTrue(invite.open_settings(ws))
|
||
m.assert_called_once_with(ws)
|
||
|
||
def test_open_settings_failure_passthrough(self):
|
||
with mock.patch("hatch_menu.dialog.open_settings",
|
||
return_value=False):
|
||
self.assertFalse(invite.open_settings(mock.Mock()))
|
||
|
||
def test_click_settings_tab_delegates(self):
|
||
ws = mock.Mock()
|
||
with mock.patch("hatch_menu.dialog.goto_tab",
|
||
return_value=True) as m:
|
||
self.assertTrue(invite.click_settings_tab(ws, "General"))
|
||
m.assert_called_once_with(ws, "General")
|
||
|
||
|
||
if __name__ == "__main__":
|
||
unittest.main()
|