deploy ProspectOS workspace v2 final
This commit is contained in:
@@ -159,6 +159,33 @@ class BrowserOnlyAppTests(unittest.TestCase):
|
||||
saved = server.db().execute("SELECT ai_probability,ai_recommendation,ai_reasoning FROM prospects WHERE id=1").fetchone()
|
||||
self.assertEqual(tuple(saved), (84.0, "contact", "Active business with a clear website opportunity."))
|
||||
|
||||
def test_mockup_fallback_is_saved_and_public_share_link_works(self):
|
||||
conn = server.db()
|
||||
conn.execute("INSERT INTO prospects(name,domain,category,address,phone,emails,website,website_status,discovered_at) VALUES(?,?,?,?,?,?,?,?,?)", ("Acme Plumbing", "maps:acme", "plumbers", "Cape Town", "+27101234567", "info@acme.co.za", "", "no_detected_website", server.now()))
|
||||
conn.commit(); conn.close()
|
||||
status, created = self.request("POST", "/api/prospects/1/mockup", {"instructions": "Keep it friendly"})
|
||||
self.assertEqual(status, 201)
|
||||
self.assertIn("/mockups/", created["share_url"])
|
||||
self.assertEqual(created["generation_source"], "fallback")
|
||||
status, listed = self.request("GET", "/api/prospects/1/mockups")
|
||||
self.assertEqual(status, 200)
|
||||
self.assertEqual(listed["items"][0]["id"], created["id"])
|
||||
preview_path = "/mockups/" + created["token"]
|
||||
self.conn.request("GET", preview_path)
|
||||
response = self.conn.getresponse()
|
||||
body = response.read().decode("utf-8")
|
||||
self.assertEqual(response.status, 200)
|
||||
self.assertIn("text/html", response.getheader("Content-Type"))
|
||||
self.assertIn("Acme Plumbing", body)
|
||||
self.assertNotIn("<script", body.lower())
|
||||
|
||||
def test_mockup_sanitizer_removes_active_markup(self):
|
||||
html = server.sanitize_mockup_html('<html><body onload="bad"><script>alert(1)</script><a href="javascript:bad()">Hi</a></body></html>')
|
||||
self.assertIn("<html>", html)
|
||||
self.assertNotIn("script", html.lower())
|
||||
self.assertNotIn("onload", html.lower())
|
||||
self.assertNotIn("javascript:", html.lower())
|
||||
|
||||
def test_browser_investigator_normalises_and_filters_candidates(self):
|
||||
raw = '{"candidates":[{"url":"https://www.acme.co.za/about","confidence":88,"evidence":["name match"]},{"url":"https://facebook.com/acme","confidence":99},{"domain":"other.co.za","confidence":"42","evidence":"not a list"}]}'
|
||||
candidates = browser_investigator._parse_agent_result(raw)
|
||||
@@ -239,6 +266,21 @@ class BrowserOnlyAppTests(unittest.TestCase):
|
||||
self.assertEqual(json.loads(saved[0]), body["unknowns"])
|
||||
self.assertEqual(json.loads(saved[1]), body["evidence_used"])
|
||||
|
||||
def test_email_draft_can_include_latest_mockup_link(self):
|
||||
conn = server.db()
|
||||
conn.execute("INSERT INTO prospects(name,domain,category,discovered_at) VALUES(?,?,?,?)", ("Acme", "maps:acme", "plumber", server.now()))
|
||||
conn.execute("INSERT INTO mockups(organization_id,prospect_id,token,title,html,created_at,updated_at) VALUES(?,?,?,?,?,?,?)", (1, 1, "a" * 24, "Acme · Website concept", "<html><body>Acme</body></html>", server.now(), server.now()))
|
||||
for key, value in (("AI_PROVIDER", "custom"), ("AI_BASE_URL", "https://ai.example/v1"), ("AI_MODEL", "test-model"), ("AI_API_KEY", "test-key")):
|
||||
conn.execute("INSERT INTO settings(key,value,updated_at) VALUES(?,?,?)", (key, value, server.now()))
|
||||
conn.commit(); conn.close()
|
||||
content = json.dumps({"subject": "A concept for Acme", "message": "Good day Acme,\n\nWe can help.", "rationale": "Uses the supplied record.", "recommended_offer": "Website", "unknowns": [], "evidence_used": ["prospect_record"], "follow_up": "Review before sending."})
|
||||
with patch("api.server.http_json", return_value={"choices": [{"message": {"content": content}}]}):
|
||||
status, body = self.request("POST", "/api/prospects/1/message", {"offer": "A modern website"})
|
||||
self.assertEqual(status, 200)
|
||||
self.assertIn("/mockups/", body["message"])
|
||||
self.assertIn("mockup_preview", body["evidence_used"])
|
||||
self.assertTrue(body["mockup_url"])
|
||||
|
||||
def test_logs_capture_api_actions_and_redact_credentials(self):
|
||||
server.record_log("ai", "test_ai_call", details={"api_key": "do-not-store", "model": "test", "prompt": "hello"})
|
||||
status, body = self.request("POST", "/api/logs", {"action": "ui_test", "details": {"button": "test"}})
|
||||
|
||||
Reference in New Issue
Block a user