otko/tests/gui/test_material_tester_dialog.py
smillmorel 612936a00b
Some checks failed
CI / lint (push) Has been cancelled
CI / test (macos-latest, 3.10) (push) Has been cancelled
CI / test (macos-latest, 3.11) (push) Has been cancelled
CI / test (macos-latest, 3.12) (push) Has been cancelled
CI / test (ubuntu-latest, 3.10) (push) Has been cancelled
CI / test (ubuntu-latest, 3.11) (push) Has been cancelled
CI / test (ubuntu-latest, 3.12) (push) Has been cancelled
CI / test (windows-latest, 3.10) (push) Has been cancelled
CI / test (windows-latest, 3.11) (push) Has been cancelled
CI / test (windows-latest, 3.12) (push) Has been cancelled
feat: initial otko import
2026-09-08 02:12:15 -04:00

99 lines
3 KiB
Python

"""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