"""Display geometry and native UI metrics without real accounts or listeners.""" import os os.environ.setdefault('QT_QPA_PLATFORM', 'offscreen') from types import SimpleNamespace from unittest import TestCase, mock from PySide6.QtCore import QRect from PySide6.QtWidgets import QApplication, QMainWindow, QWidget, QPushButton, QVBoxLayout import wechat_gui_qt as ui class DisplayHost(QMainWindow): _set_initial_geometry = ui.MainWindow._set_initial_geometry _display_metrics_changed = ui.MainWindow._display_metrics_changed _screen_changed = ui.MainWindow._screen_changed _apply_window_ui_scale = ui.MainWindow._apply_window_ui_scale def __init__(self, area): super().__init__() self.test_screen = SimpleNamespace(availableGeometry=lambda: area, availableGeometryChanged=mock.Mock(), logicalDotsPerInchChanged=mock.Mock()) self._scale_timer = mock.Mock() self.runtime_settings = {'scale_ratio': '自动'} def screen(self): return self.test_screen class DisplayTest(TestCase): @classmethod def setUpClass(cls): cls.app = QApplication.instance() or QApplication([]) def tearDown(self): ui.sync_ui_scale(1630, 920, factor=1) def test_initial_window_stays_inside_small_and_offset_displays(self): for area in [QRect(0,0,960,540), QRect(-1280,0,1280,680), QRect(1920,0,640,360), QRect(0,0,320,240)]: with self.subTest(area=area): host=DisplayHost(area) host._set_initial_geometry() self.assertTrue(area.contains(host.geometry()), (area,host.geometry())) host.deleteLater() def test_cross_monitor_clamps_to_current_available_geometry(self): area=QRect(-960,100,960,500);host=DisplayHost(area) host.setGeometry(0,0,1630,920) host.console_shell=SimpleNamespace(page_ready=True,page=lambda:SimpleNamespace(runJavaScript=mock.Mock())) host._display_metrics_changed() self.assertTrue(area.contains(host.geometry())) self.assertLessEqual(host.minimumWidth(),area.width()) self.assertLessEqual(host.minimumHeight(),area.height()) host._scale_timer.start.assert_called_once() host.deleteLater() def test_screen_notifications_are_not_duplicated(self): host=DisplayHost(QRect(0,0,960,540));first=host.screen() with mock.patch.object(ui.QTimer,'singleShot'): host._screen_changed(first);host._screen_changed(first) first.availableGeometryChanged.connect.assert_called_once() first.logicalDotsPerInchChanged.connect.assert_called_once() second=SimpleNamespace(availableGeometryChanged=mock.Mock(),logicalDotsPerInchChanged=mock.Mock()) host._screen_changed(second) first.availableGeometryChanged.disconnect.assert_called_once() second.availableGeometryChanged.connect.assert_called_once() host.deleteLater() def test_normal_window_resize_does_not_reduce_font_size(self): host=DisplayHost(QRect(0,0,1920,1080)) for width,height in [(1630,920),(960,500),(640,330)]: host.resize(width,height);host._apply_window_ui_scale() self.assertEqual(ui.ui_scale_factor(),1) host.runtime_settings['scale_ratio']='300%' host._apply_window_ui_scale();self.assertEqual(ui.ui_scale_factor(),3) host.deleteLater() def test_native_dimensions_font_and_spacing_scale_together_without_compounding(self): ui.sync_ui_scale(1630,920,factor=1) panel=QWidget();layout=QVBoxLayout(panel);layout.setContentsMargins(10,10,10,10);layout.setSpacing(8) button=QPushButton('测试',panel);button.setFixedSize(120,40);button.setStyleSheet('font-size:14px;') layout.addWidget(button) for scale in (2,3,1,2,1): ui.sync_ui_scale(640,330,panel,factor=scale) self.assertEqual(button.width(),120*scale) self.assertEqual(button.height(),40*scale) self.assertEqual(layout.spacing(),8*scale) self.assertEqual(layout.contentsMargins().left(),10*scale) self.assertIn(f'font-size:{14*scale}px',button.styleSheet()) panel.deleteLater() def test_automatic_and_invalid_preferences_follow_system(self): for preference in ('自动', '', None, 'nan', '999%', '2'): self.assertEqual(ui.interface_scale(preference),1) self.assertEqual(ui.interface_scale('125%'),1.25) self.assertEqual(ui.interface_scale('200%'),2) self.assertEqual(ui.interface_scale('300%'),3) def test_saved_preference_does_not_set_process_dpi_multiplier(self): import inspect self.assertNotIn('QT_SCALE_FACTOR',inspect.getsource(ui)) def test_monitor_removal_tolerates_a_deleted_screen_object(self): class DeletedScreen: def __getattr__(self, name): raise RuntimeError("Internal C++ object already deleted") host=DisplayHost(QRect(0,0,960,540));host._watched_screen=DeletedScreen() with mock.patch.object(ui.QTimer,'singleShot'): host._screen_changed(host.screen()) self.assertIs(host._watched_screen,host.screen()) host.deleteLater()