""" Test false positive fixes for issue #32. Verifies that innocent messages no longer trigger crisis detection. """ import unittest import sys import os # Ensure project root is on path sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) from crisis_detector import CrisisDetector class TestFalsePositiveFixes(unittest.TestCase): """Test that innocent messages no longer trigger false positives.""" def setUp(self): self.detector = CrisisDetector() def test_saying_goodbye_innocent(self): """'saying goodbye' should not trigger for innocent messages.""" innocent_messages = [ "I'm saying goodbye to my old apartment", "She was saying goodbye at the airport", "We were saying goodbye to our friends", ] for msg in innocent_messages: result = self.detector.scan(msg) self.assertEqual(result.risk_level, "NONE", f"False positive for: {msg}") def test_wrote_a_will_innocent(self): """'wrote a will' should not trigger for responsible behavior.""" innocent_messages = [ "I wrote a will last year — just being responsible", "She wrote a will as part of estate planning", ] for msg in innocent_messages: result = self.detector.scan(msg) self.assertEqual(result.risk_level, "NONE", f"False positive for: {msg}") def test_giving_away_possessions_innocent(self): """'giving away possessions' should not trigger for decluttering.""" innocent_messages = [ "I'm giving away possessions — decluttering my house", "She's giving away her old clothes", ] for msg in innocent_messages: result = self.detector.scan(msg) self.assertEqual(result.risk_level, "NONE", f"False positive for: {msg}") def test_give_up_innocent(self): """'give up' should not trigger for common frustration.""" innocent_messages = [ "I give up on this project", "Don't give up on your dreams", "She gave up chocolate for Lent", ] for msg in innocent_messages: result = self.detector.scan(msg) self.assertEqual(result.risk_level, "NONE", f"False positive for: {msg}") def test_trapped_innocent(self): """'trapped' should not trigger for literal situations.""" innocent_messages = [ "I'm trapped in an elevator", "The cat is trapped in the tree", "We're trapped in traffic", ] for msg in innocent_messages: result = self.detector.scan(msg) self.assertEqual(result.risk_level, "NONE", f"False positive for: {msg}") def test_desperate_innocent(self): """'desperate' should not trigger for competition.""" innocent_messages = [ "She's desperate to win the game", "He's desperate for a promotion", ] for msg in innocent_messages: result = self.detector.scan(msg) self.assertEqual(result.risk_level, "NONE", f"False positive for: {msg}") def test_worthless_innocent(self): """'worthless' alone is MEDIUM but single-match falls to LOW — not HIGH.""" innocent_messages = [ "This character is worthless in the game", "That movie was worthless", ] for msg in innocent_messages: result = self.detector.scan(msg) self.assertIn(result.risk_level, ("NONE", "LOW"), f"Should not escalate above LOW for: {msg}") def test_hopeless_innocent(self): """'hopeless' alone is MEDIUM but single-match falls to LOW — not HIGH.""" innocent_messages = [ "This bug is hopeless", "The situation is hopeless but we'll try anyway", ] for msg in innocent_messages: result = self.detector.scan(msg) self.assertIn(result.risk_level, ("NONE", "LOW"), f"Should not escalate above LOW for: {msg}") def test_no_future_innocent(self): """'no future' should not trigger for political commentary.""" innocent_messages = [ "He has no future in politics", "That company has no future", ] for msg in innocent_messages: result = self.detector.scan(msg) self.assertEqual(result.risk_level, "NONE", f"False positive for: {msg}") def test_nothing_left_innocent(self): """'nothing left' should not trigger for everyday life.""" innocent_messages = [ "There's nothing left in the fridge", "We have nothing left to do", ] for msg in innocent_messages: result = self.detector.scan(msg) self.assertEqual(result.risk_level, "NONE", f"False positive for: {msg}") def test_cant_see_any_light_innocent(self): """'can't see any light'/'dark' alone is MEDIUM, single-match falls to LOW.""" innocent_messages = [ "I can't see any light — the power went out", "It's so dark I can't see any light", ] for msg in innocent_messages: result = self.detector.scan(msg) self.assertIn(result.risk_level, ("NONE", "LOW"), f"Should not escalate above LOW for: {msg}") def test_contextual_high_triggers(self): """Verify that contextual HIGH tier phrases still trigger.""" # These should trigger HIGH because they have crisis context crisis_messages = [ ("I feel so hopeless about my life", "HIGH"), ("I'm trapped in this situation and can't escape", "HIGH"), ("I feel desperate for help", "HIGH"), ("I want to give up on life", "HIGH"), ("There's no point in living anymore", "HIGH"), ] for msg, expected_level in crisis_messages: result = self.detector.scan(msg) self.assertIn(result.risk_level, ("HIGH", "CRITICAL"), f"Should trigger HIGH/CRITICAL for: {msg}, got {result.risk_level}") def test_critical_still_triggers(self): """Verify that CRITICAL tier phrases still trigger.""" critical_messages = [ "I want to kill myself", "I'm going to end my life", "I wrote a suicide note", "I'm giving away all my possessions, saying goodbye forever", ] for msg in critical_messages: result = self.detector.scan(msg) self.assertEqual(result.risk_level, "CRITICAL", f"Should trigger CRITICAL for: {msg}") if __name__ == "__main__": unittest.main()