"""GUI tests for the Material Tester dialog.""" from __future__ import annotations import pytest pytest.importorskip("PySide6") pytest.importorskip("openseespy.opensees") from otko.core import ElasticUniaxial from otko.viewmodels import ProjectViewModel from otko.views.dialogs.material_tester import MaterialTesterDialog def _make_vm() -> ProjectViewModel: """View-model with one elastic uniaxial material to probe.""" vm = ProjectViewModel() vm.new_project() assert vm.project is not None vm.project.materials.append(ElasticUniaxial(id=1, name="TestMat", E=200e9)) return vm @pytest.mark.gui def test_monotonic_run_plots_service_result(qtbot) -> None: # type: ignore[no-untyped-def] vm = _make_vm() dlg = MaterialTesterDialog(vm) qtbot.addWidget(dlg) dlg._comp_spin.setValue(-0.005) dlg._tens_spin.setValue(0.005) dlg._steps_spin.setValue(5) protocol = dlg.build_protocol() assert protocol.kind == "monotonic" result = dlg.run_test() assert result is not None assert len(result.strain) == 10 # 2 branches x 5 steps assert len(result.stress) == len(result.strain) assert dlg.last_result is result # NOTE: getOriginalDataset, not getData — pyqtgraph >= 0.14 clips the # *display* dataset to +/- dynamicRangeLimit (1e6) x view height, and # the view never autoranges in a hidden (headless) widget. x, y = dlg._curve.getOriginalDataset() assert list(x) == pytest.approx(result.strain) assert list(y) == pytest.approx(result.stress) @pytest.mark.gui def test_cyclic_protocol_builds_segment_and_runs(qtbot) -> None: # type: ignore[no-untyped-def] vm = _make_vm() dlg = MaterialTesterDialog(vm) qtbot.addWidget(dlg) assert not dlg._cycles_spin.isEnabled() dlg._kind_cb.setCurrentIndex(1) assert dlg._cycles_spin.isEnabled() dlg._comp_spin.setValue(-0.004) dlg._tens_spin.setValue(0.004) dlg._steps_spin.setValue(4) dlg._cycles_spin.setValue(2) protocol = dlg.build_protocol() assert protocol.kind == "cyclic" assert protocol.cycles is not None and len(protocol.cycles) == 1 assert protocol.cycles[0].n_cycles == 2 result = dlg.run_test() assert result is not None assert len(result.strain) == 2 * 3 * 4 # cycles x branches x steps @pytest.mark.gui def test_cyclic_without_tensile_peak_shows_message(qtbot) -> None: # type: ignore[no-untyped-def] vm = _make_vm() dlg = MaterialTesterDialog(vm) qtbot.addWidget(dlg) dlg._kind_cb.setCurrentIndex(1) dlg._tens_spin.setValue(0.0) assert dlg.run_test() is None assert "tensile" in dlg._message.text().lower() assert dlg.last_result is None @pytest.mark.gui def test_empty_project_disables_run(qtbot) -> None: # type: ignore[no-untyped-def] vm = ProjectViewModel() vm.new_project() dlg = MaterialTesterDialog(vm) qtbot.addWidget(dlg) assert not dlg._run_btn.isEnabled() assert dlg.selected_material() is None assert dlg.run_test() is None