import os os.environ.setdefault('QT_QPA_PLATFORM', 'offscreen') import time import tempfile from pathlib import Path import unittest from unittest.mock import patch try: from PySide6.QtWidgets import QApplication from samsara.ui.window import MainWindow except ImportError: QApplication = None from samsara.collectors.demo import collect_demo, LINUX_DEMO_HOST @unittest.skipIf(QApplication is None, 'PySide6 not installed') class UITests(unittest.TestCase): @classmethod def setUpClass(cls): cls.app = QApplication.instance() or QApplication([]) def finish(self, window): deadline = time.monotonic() + 5 while window.job is not None and time.monotonic() < deadline: self.app.processEvents() time.sleep(.01) self.assertIsNone(window.job) def test_default_workflow_navigation_and_no_fabricated_history(self): window = MainWindow() self.assertEqual(window.windowTitle(), 'Samsara') self.assertEqual(window.source.currentData(), 'local') self.assertEqual(window.target.currentData(), 'auto') self.assertIsNone(window.data) self.assertEqual(window.history, []) self.assertFalse(window.report_buttons[0].isEnabled()) self.assertEqual(window.nav.item(0).text(), 'Summary') for index in range(5): window.nav.setCurrentRow(index) self.assertEqual(window.pages.currentIndex(), {0: 1, 1: 0, 2: 2, 3: 3, 4: 4}[index]) window.close() def test_samples_details_and_history(self): window = MainWindow() for source, expected in [('linux_demo', 'linux'), ('windows_demo', 'windows')]: window.source.setCurrentIndex(window.source.findData(source)) self.assertFalse(window.target.isEnabled()) window.start_collection() self.finish(window) self.assertEqual(window.data['server']['platform'], expected) self.assertIn('Synthetic', window.banner.text()) self.assertEqual(window.nav.currentRow(), 0) self.assertEqual(window.result_tabs.tabText(0), 'Summary') self.assertIn('/100', window.retirement_score.text()) self.assertIn('Version:', window.os_version.text()) for index in range(1, window.result_tabs.count()): window.result_tabs.setCurrentIndex(index) self.assertGreaterEqual(list(window.detail_areas.values())[index - 1].count(), 1) window.open_history(window.history_list.item(0)) self.assertEqual(window.data['server']['platform'], 'linux') self.assertEqual(len(window.records), 2) window.close() def test_auto_detect_runs_local_collector_and_saves_report(self): data = collect_demo(LINUX_DEMO_HOST) data['synthetic'] = False data['server']['collection_source'] = 'Local Linux read-only collection' detected = {'platform': 'linux', 'family': 'linux', 'version': '22', 'name': 'Local Linux'} with patch('samsara.ui.window.detect_local_os', return_value=detected) as detection, patch('samsara.ui.window.collect_local_linux', return_value=data) as collector: window = MainWindow() window.analyze_button.click() self.assertFalse(window.analyze_button.isEnabled()) self.finish(window) detection.assert_called_once() collector.assert_called_once() self.assertIn('Local Linux', window.banner.text()) self.assertTrue(window.analyze_button.isEnabled()) self.assertTrue(window.report_buttons[0].isEnabled()) with tempfile.TemporaryDirectory() as folder: report = Path(folder) / 'local.html' with patch('samsara.core.storage._verify_windows_acl'), patch('samsara.core.storage.report_directory',return_value=Path(folder)), patch('samsara.ui.window.report_directory',return_value=Path(folder)), patch('samsara.ui.window.QFileDialog.getSaveFileName', return_value=(str(report), '')), patch('samsara.ui.window.QMessageBox.information'): window.quick_save.click() self.assertIn('LOCAL LINUX INVENTORY', report.read_text()) window.close() def test_mismatched_profile_and_windows_failure_keep_prior_results(self): window = MainWindow() window.collection_done(collect_demo(LINUX_DEMO_HOST)) previous = window.data detected = {'platform': 'linux', 'family': 'linux', 'version': '22', 'name': 'Local Linux'} with patch('samsara.ui.window.detect_local_os', return_value=detected), patch('samsara.ui.window.collect_local_linux') as collector: window.target.setCurrentIndex(window.target.findData('rhel:9')) window.start_collection() self.finish(window) collector.assert_not_called() self.assertIn('does not match', window.status.text()) self.assertIs(window.data, previous) with patch('samsara.ui.window.detect_local_os', return_value={'platform': 'windows', 'family': 'windows', 'version': '', 'name': 'Windows'}), patch('samsara.ui.window.collect_local_windows', side_effect=ValueError('Windows identity collection failed.')): window.start_collection() self.finish(window) self.assertIn('identity collection failed', window.status.text()) self.assertIs(window.data, previous) window.close() def test_import_requires_file_and_reads_recorded_os(self): window = MainWindow() window.source.setCurrentIndex(window.source.findData('file')) self.assertFalse(window.target.isEnabled()) window.start_collection() self.assertIn('Choose an inventory', window.status.text()) with patch('samsara.ui.window.load_inventory', return_value=collect_demo(LINUX_DEMO_HOST)) as loader, patch('samsara.ui.window.detect_local_os') as detect: window.inventory_path.setText('/tmp/saved-inventory.json') window.start_collection() self.finish(window) loader.assert_called_once_with('/tmp/saved-inventory.json') detect.assert_not_called() window.close() def test_windows_local_route_preserves_summary_history_and_export(self): import json data = json.loads(Path('tests/fixtures/windows/server-2025.json').read_text()) data['synthetic'] = False data['server']['collection_source'] = 'Local Windows read-only collection' with patch('samsara.ui.window.detect_local_os', return_value={'platform': 'windows', 'family': 'windows', 'version': '', 'name': 'Windows'}), patch('samsara.ui.window.collect_local_windows', return_value=data) as collector, patch('samsara.ui.window.collect_local_linux') as linux: window = MainWindow() window.target.setCurrentIndex(window.target.findData('windows:2025')) window.start_collection() self.assertFalse(window.analyze_button.isEnabled()) self.finish(window) collector.assert_called_once() self.assertEqual(collector.call_args.kwargs['profile'], 'windows:2025') linux.assert_not_called() self.assertIn('Local Windows', window.banner.text()) self.assertIn('2025', window.os_version.text()) self.assertEqual(len(window.records), 1) self.assertEqual(window.nav.currentRow(), 0) self.assertTrue(window.report_buttons[0].isEnabled()) with tempfile.TemporaryDirectory() as folder: report = Path(folder)/'windows.html' with patch('samsara.core.storage._verify_windows_acl'), patch('samsara.core.storage.report_directory',return_value=Path(folder)), patch('samsara.ui.window.report_directory',return_value=Path(folder)), patch('samsara.ui.window.QFileDialog.getSaveFileName', return_value=(str(report), '')), patch('samsara.ui.window.QMessageBox.information'): window.quick_save.click() self.assertIn('LOCAL WINDOWS INVENTORY', report.read_text()) window.close() def test_policy_changes_preserve_history_and_confidence_is_visible(self): import json from samsara.analyzers.policy import load_policy window=MainWindow() fixture=Path('tests/fixtures/scoring/active_sql_server.json') window.collection_done(json.loads(fixture.read_text())) self.assertEqual(window.assessment['score'],70) original_policy=window.assessment['scoring']['policy_id'] self.assertIn('Confidence:',window.coverage_note.text()) self.assertIn('Coverage gaps do not add risk points',window.coverage_note.text()) with tempfile.TemporaryDirectory() as folder: policy=load_policy() policy['scores']['observed_application_clients']=55 path=Path(folder)/'policy.json' path.write_text(json.dumps(policy)) with patch('samsara.ui.window.QFileDialog.getOpenFileName',return_value=(str(path),'')): window.choose_policy() window.source.setCurrentIndex(window.source.findData('file')) window.inventory_path.setText(str(fixture.resolve())) window.start_collection() self.assertFalse(window.policy_button.isEnabled()) self.finish(window) self.assertEqual(window.assessment['score'],55) self.assertNotEqual(window.assessment['scoring']['policy_id'],original_policy) window.open_history(window.history_list.item(0)) self.assertEqual(window.assessment['score'],70) self.assertEqual(window.assessment['scoring']['policy_id'],original_policy) window.reset_policy() window.close() def test_privacy_and_bounded_history_clear(self): import json window=MainWindow() raw=collect_demo(LINUX_DEMO_HOST) raw['server']['hostname']='SYNTHETIC_PERSON_UI_CANARY' for _ in range(12): window.collection_done(raw) self.assertEqual(len(window.records),10) self.assertEqual(window.history_list.count(),10) self.assertNotIn('SYNTHETIC_PERSON_UI_CANARY',json.dumps(window.records)) window.clear_history_button.click() self.assertEqual(window.records,[]) self.assertEqual(window.history,[]) self.assertIsNone(window.data) self.assertFalse(window.quick_save.isEnabled()) self.assertEqual(window.scheduled_jobs.text(),'') window.close()