import json from pathlib import Path import subprocess import sys import tempfile import unittest from intelligence_radar.__main__ import draft, ledger, record, validate FIXTURE = Path(__file__).resolve().parents[1] / 'examples/observation.json' class WorkflowTests(unittest.TestCase): def setUp(self): self.temp = tempfile.TemporaryDirectory() self.addCleanup(self.temp.cleanup) self.root = Path(self.temp.name) self.value = json.loads(FIXTURE.read_text()) def test_idempotence_and_append_only_correction(self): original = record(self.root, self.value) self.assertEqual(record(self.root, self.value), original) replacement = dict(self.value, claim='Corrected synthetic claim', supersedes=original) correction = record(self.root, replacement) self.assertNotEqual(original, correction) self.assertEqual(len(ledger(self.root)), 2) text = draft(self.root, '2026-09-13').read_text() self.assertIn(f'Supersedes: {original}', text) with self.assertRaises(FileExistsError): draft(self.root, '2026-09-13') def test_tampered_record_is_rejected_by_reader_and_writer(self): ident = record(self.root, self.value) path = self.root / 'data/observations' / f'{ident}.json' envelope = json.loads(path.read_text()) envelope['record']['claim'] = 'tampered' path.write_text(json.dumps(envelope)) for fn in (lambda: ledger(self.root), lambda: record(self.root, self.value)): with self.assertRaisesRegex(ValueError, 'integrity'): fn() def test_timezone_date_hash_and_shape_validation(self): for change in ({'observed_at': '2026-09-13T20:00:00'}, {'event_date': '2026-09-14'}, {'content_sha256': 'bad'}, {'source_url': 'https://user:password@example.invalid'}, {'schema_version': True}, {'status': 'verified_by_magic'}, {'unexpected': 'field'}): with self.subTest(change=change), self.assertRaises(ValueError): validate(dict(self.value, **change)) def test_unknown_correction_target_rejected(self): with self.assertRaisesRegex(ValueError, 'existing observation'): record(self.root, dict(self.value, supersedes='0' * 64)) def test_iso_week_year_boundary_and_event_date_filter(self): ident = record(self.root, dict(self.value, event_date='2025-12-29', observed_at='2026-01-02T12:00:00Z')) self.assertIn(ident, draft(self.root, '2026-W01').read_text()) self.assertIn('No recorded observations', draft(self.root, '2026-01-02').read_text()) with self.assertRaises(ValueError): draft(self.root, '2026-W99') def test_invalid_cli_input_exits_nonzero_without_traceback(self): invalid = self.root / 'invalid.json' invalid.write_text('[]') result = subprocess.run([sys.executable, '-m', 'intelligence_radar', '--root', str(self.root), 'record', str(invalid)], capture_output=True, text=True) self.assertEqual(result.returncode, 1) self.assertIn('record must be an object', result.stderr) self.assertNotIn('Traceback', result.stderr) def test_empty_period_does_not_invent_news(self): self.assertIn('does not establish that no events occurred', draft(self.root, '2026-09-13').read_text()) if __name__ == '__main__': unittest.main()