intelligence-radar/tests/test_workflow.py

80 lines
3.5 KiB
Python
Raw Normal View History

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()