from pathlib import Path import ast folder=Path(__file__).resolve().parent;payload=folder/'payload' css=payload/'assets/ui/console-responsive.css' with css.open('a',encoding='utf-8') as f: f.write(''' #stage .anomaly, #stage .anomaly-card { flex-wrap: wrap; } #stage .anomaly-action { max-width: 100%; } #stage .log-mid > .panel > .row { flex-wrap: wrap; } #stage .log-mid > .panel > .row > div { flex: 1 1 180px; } ''') js=payload/'assets/ui/console-app.js';s=js.read_text(encoding='utf-8') i=s.index('id="sys-scale"');print('Scale control:',s[i:i+550]) # Support both menu forms without depending on whitespace in the source template. old='["自动", "100%", "125%", "150%", "200%"]' s=s.replace(old,'["自动", "100%", "125%", "150%", "200%", "250%", "300%"]') js.write_text(s,encoding='utf-8',newline='\n') p=payload/'test_qt_console_bridge.py';s=p.read_text(encoding='utf-8') replacements={ 'test_no_layout_scrolls_anywhere':''' def test_long_pages_scroll_without_shrinking_text(self): css = Path(CONSOLE_HTML).with_name("console-responsive.css").read_text(encoding="utf-8") self.assertIn("overflow: auto", css) self.assertIn("html.embedded .main", css) self.assertIn("min-height: 0", css) ''', 'test_the_stage_and_pages_grow_with_their_content':''' def test_responsive_styles_are_bundled_after_reference_styles(self): html = Path(CONSOLE_HTML).read_text(encoding="utf-8") self.assertGreater(html.index('href="console-responsive.css'), html.rindex('')) css = Path(CONSOLE_HTML).with_name("console-responsive.css").read_text(encoding="utf-8") self.assertIn('data-layout="compact"', css) self.assertIn('data-layout="narrow"', css) ''', 'test_the_scale_never_depends_on_which_page_is_open':''' def test_the_scale_never_depends_on_page_height_or_device_pixel_ratio(self): script = Path(CONSOLE_HTML).with_name("console-app.js").read_text(encoding="utf-8") body = script[script.index("fit = function()"):script.index("function connectQt(")] self.assertNotIn("scrollHeight", body) self.assertNotIn("devicePixelRatio", body) self.assertNotIn("innerHeight / DESIGN_H", body) self.assertIn("choices[preference]", body) ''', 'test_the_canvas_fills_the_window_in_both_directions':''' def test_canvas_uses_available_logical_space_without_design_minimum(self): script = Path(CONSOLE_HTML).with_name("console-app.js").read_text(encoding="utf-8") body = script[script.index("fit = function()"):script.index("function connectQt(")] self.assertIn("innerWidth / scale", body) self.assertIn("innerHeight / scale", body) self.assertNotIn("Math.max(DESIGN_", body) self.assertIn('stage.style.transform = "none"', body) '''} tree=ast.parse(s);lines=s.splitlines(keepends=True) nodes=sorted((n for n in ast.walk(tree) if isinstance(n,ast.FunctionDef) and n.name in replacements),key=lambda n:n.lineno,reverse=True) assert len(nodes)==len(replacements) for n in nodes:lines[n.lineno-1:n.end_lineno]=[replacements[n.name]] s=''.join(lines);ast.parse(s);p.write_text(s,encoding='utf-8',newline='\n') # A compact visual check copy, without changing the browser artifacts. from PIL import Image for name in ['1080-auto','1080-300-automation','1080-300-system']: im=Image.open(folder/'qa'/f'{name}.png');im.thumbnail((1100,750));im.convert('RGB').save(folder/'qa'/f'{name}.jpg',quality=75) print('Updated layout contracts and visual previews')