feat(box): add invite code handler, Settings RPA, and agent onboarding pipeline
- 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
This commit is contained in:
@@ -0,0 +1,182 @@
|
||||
#!/usr/bin/env python3
|
||||
"""test_invite_handler.py: Unit tests for invite code handler, usage parser, and settings RPA."""
|
||||
|
||||
import importlib.util
|
||||
import json
|
||||
import sys
|
||||
import unittest
|
||||
from pathlib import Path
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
REPO_ROOT = Path(__file__).resolve().parent.parent
|
||||
sys.path.insert(0, str(REPO_ROOT / "bin"))
|
||||
|
||||
import invite
|
||||
from invite_handler import InviteCodeInfo, InviteHandler, RedemptionResult, salvage_blocked_node
|
||||
from settings_rpa import NodeUsage, SettingsRPA
|
||||
|
||||
|
||||
class TestInviteCodeValidation(unittest.TestCase):
|
||||
def test_normalize_valid_codes(self):
|
||||
self.assertEqual(invite.normalize_code("REDCJ7"), "REDCJ7")
|
||||
self.assertEqual(invite.normalize_code(" redcj7 "), "REDCJ7")
|
||||
self.assertEqual(invite.normalize_code("81mdir"), "81MDIR")
|
||||
self.assertEqual(invite.normalize_code("F4BGHN"), "F4BGHN")
|
||||
self.assertEqual(invite.normalize_code("14ogf2"), "14OGF2")
|
||||
|
||||
def test_normalize_invalid_codes(self):
|
||||
self.assertIsNone(invite.normalize_code("SHORT"))
|
||||
self.assertIsNone(invite.normalize_code("TOOLONG123"))
|
||||
self.assertIsNone(invite.normalize_code("INV@L!"))
|
||||
self.assertIsNone(invite.normalize_code(""))
|
||||
self.assertIsNone(invite.normalize_code(None))
|
||||
self.assertIsNone(invite.normalize_code(123456))
|
||||
|
||||
|
||||
class TestUsageParser(unittest.TestCase):
|
||||
def test_parse_usage_blocked_node(self):
|
||||
sample_646 = """
|
||||
Settings
|
||||
General
|
||||
Meta Account
|
||||
Password, security, personal details
|
||||
Usage
|
||||
Free plan
|
||||
Weekly limit resets on Oct 9
|
||||
100% used
|
||||
Additional tokens
|
||||
Never expires
|
||||
100% used (0 tokens left)
|
||||
Upgrade
|
||||
Language
|
||||
Appearance
|
||||
"""
|
||||
parsed = invite.parse_usage_text(sample_646)
|
||||
self.assertEqual(parsed["weekly_reset"], "Oct 9")
|
||||
self.assertEqual(parsed["weekly_used_pct"], 100)
|
||||
self.assertEqual(parsed["additional_expires"], "Never expires")
|
||||
self.assertEqual(parsed["additional_used_pct"], 100)
|
||||
self.assertEqual(parsed["additional_left"], "0 tokens left")
|
||||
|
||||
def test_parse_usage_active_pip(self):
|
||||
sample_pip = """
|
||||
Usage
|
||||
Free plan
|
||||
Weekly limit resets on Oct 10
|
||||
100% used
|
||||
Additional tokens
|
||||
Never expires
|
||||
10% used (901M tokens left)
|
||||
Upgrade
|
||||
"""
|
||||
parsed = invite.parse_usage_text(sample_pip)
|
||||
self.assertEqual(parsed["weekly_reset"], "Oct 10")
|
||||
self.assertEqual(parsed["weekly_used_pct"], 100)
|
||||
self.assertEqual(parsed["additional_expires"], "Never expires")
|
||||
self.assertEqual(parsed["additional_used_pct"], 10)
|
||||
self.assertEqual(parsed["additional_left"], "901M tokens left")
|
||||
self.assertTrue(parsed["has_redeemed"])
|
||||
|
||||
def test_parse_usage_fresh_account_no_extra_tokens(self):
|
||||
sample_fresh = """
|
||||
Usage
|
||||
Free plan
|
||||
Weekly limit resets on Oct 12
|
||||
15% used
|
||||
Redeem invite code
|
||||
"""
|
||||
parsed = invite.parse_usage_text(sample_fresh)
|
||||
self.assertEqual(parsed["weekly_reset"], "Oct 12")
|
||||
self.assertEqual(parsed["weekly_used_pct"], 15)
|
||||
self.assertIsNone(parsed["additional_left"])
|
||||
self.assertFalse(parsed["has_redeemed"])
|
||||
|
||||
def test_parse_usage_empty(self):
|
||||
parsed = invite.parse_usage_text("")
|
||||
self.assertIsNone(parsed["weekly_reset"])
|
||||
self.assertIsNone(parsed["weekly_used_pct"])
|
||||
self.assertIsNone(parsed["additional_left"])
|
||||
self.assertFalse(parsed["has_redeemed"])
|
||||
|
||||
|
||||
class TestInviteHandlerMocked(unittest.TestCase):
|
||||
@patch("invite.get_cdp_ws")
|
||||
@patch("invite.cdp_evaluate")
|
||||
def test_get_invite_api_success(self, mock_eval, mock_ws):
|
||||
mock_ws.return_value = (MagicMock(), MagicMock())
|
||||
mock_eval.return_value = {
|
||||
"status": 200,
|
||||
"data": {
|
||||
"code": "REDCJ7",
|
||||
"uses_remaining": 30,
|
||||
"use_count": 0,
|
||||
"has_redeemed_invite_code": True,
|
||||
"reward": None,
|
||||
},
|
||||
}
|
||||
|
||||
res = invite.get_invite("646")
|
||||
self.assertTrue(res["ok"])
|
||||
self.assertEqual(res["code"], "REDCJ7")
|
||||
self.assertTrue(res["has_redeemed"])
|
||||
self.assertEqual(res["uses_remaining"], 30)
|
||||
|
||||
@patch("invite.get_cdp_ws")
|
||||
@patch("invite.cdp_evaluate")
|
||||
def test_redeem_invite_already_redeemed(self, mock_eval, mock_ws):
|
||||
mock_ws.return_value = (MagicMock(), MagicMock())
|
||||
mock_eval.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"])
|
||||
|
||||
@patch("invite.get_cdp_ws")
|
||||
@patch("invite.cdp_evaluate")
|
||||
def test_redeem_invite_success(self, mock_eval, mock_ws):
|
||||
mock_ws.return_value = (MagicMock(), MagicMock())
|
||||
mock_eval.return_value = {
|
||||
"status": 200,
|
||||
"ok": True,
|
||||
"data": {
|
||||
"success": True,
|
||||
"redemptionStatus": "redeemed",
|
||||
"detail": "Congratulations!",
|
||||
},
|
||||
}
|
||||
|
||||
res = invite.redeem_invite("def", "REDCJ7")
|
||||
self.assertTrue(res["ok"])
|
||||
self.assertEqual(res["redemption_status"], "redeemed")
|
||||
|
||||
def test_salvage_blocked_node_diagnosis(self):
|
||||
with patch.object(InviteHandler, "find_code") as mock_find:
|
||||
mock_find.return_value = InviteCodeInfo(
|
||||
node="646",
|
||||
code="REDCJ7",
|
||||
uses_remaining=30,
|
||||
use_count=0,
|
||||
max_uses=30,
|
||||
has_redeemed=True,
|
||||
invite_state="ELIGIBLE",
|
||||
reward=None,
|
||||
method_used="api",
|
||||
)
|
||||
# All peers already redeemed
|
||||
res = salvage_blocked_node("646")
|
||||
self.assertFalse(res["success"])
|
||||
self.assertEqual(res["invite_code"], "REDCJ7")
|
||||
self.assertIn("An onboarding agent or fresh client profile must redeem this code", res["error"])
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user