Commit 3692086c authored by Flavio TARSETTI's avatar Flavio TARSETTI Committed by Samuel GAIST
Browse files

[widgets/tests][parameterwidget] Implement ParameterWidget

This widget will be used for algorithm related parameter
setup. Used for example in the AlgorithmEditor.

Fixes #215
parent b7e2364f
# vim: set fileencoding=utf-8 :
###############################################################################
# #
# Copyright (c) 2019 Idiap Research Institute, http://www.idiap.ch/ #
# Contact: beat.support@idiap.ch #
# #
# This file is part of the beat.editor module of the BEAT platform. #
# #
# Commercial License Usage #
# Licensees holding valid commercial BEAT licenses may use this file in #
# accordance with the terms contained in a written agreement between you #
# and Idiap. For further information contact tto@idiap.ch #
# #
# Alternatively, this file may be used under the terms of the GNU Affero #
# Public License version 3 as published by the Free Software and appearing #
# in the file LICENSE.AGPL included in the packaging of this file. #
# The BEAT platform is distributed in the hope that it will be useful, but #
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY #
# or FITNESS FOR A PARTICULAR PURPOSE. #
# #
# You should have received a copy of the GNU Affero Public License along #
# with the BEAT platform. If not, see http://www.gnu.org/licenses/. #
# #
###############################################################################
import pytest
import numpy as np
from PyQt5 import QtCore
from PyQt5.QtCore import QTimer
from PyQt5.QtWidgets import QApplication
from ..widgets.parameter import ParameterWidget
from ..widgets.parameter import InputType
from ..utils import dataformat_basetypes
@pytest.fixture(
params=[
item
for item in InputType
if item not in [InputType.UNKNOWN, InputType.BOOL, InputType.STRING]
]
)
def input_type(request):
return request.param
@pytest.fixture()
def expected_values():
return [
(np.uint8, 477218588),
(np.uint16, 477218588),
(np.uint32, 477218588),
(np.uint64, 4444444444444444444),
(np.int8, -84),
(np.int16, 24564),
(np.int32, 1081950908),
(np.int64, 4444444444444444444),
(np.float32, 4.444445e16),
(np.float64, 4.444444444444445e164),
]
class TestParameterWidget:
"""Test that the parameter widget works correctly"""
def test_add_parameter(self, qtbot):
default_parameter_set = {
"basetype": dataformat_basetypes()[0],
"data": {"default": 0, "type": "Unrestricted"},
"description": "",
"name": "",
}
parameter = ParameterWidget()
qtbot.addWidget(parameter)
assert parameter.dump() == default_parameter_set
def test_load_dump_parameter_numpy_type_unrestricted(self, qtbot, input_type):
new_parameter_set = {
"basetype": input_type.name.lower(),
"data": {"default": 3, "type": "Unrestricted"},
"description": "some description",
"name": "some name",
}
parameter = ParameterWidget()
qtbot.addWidget(parameter)
with qtbot.waitSignal(parameter.dataChanged):
parameter.load(new_parameter_set)
assert parameter.dump() == new_parameter_set
def test_load_dump_parameter_numpy_type_choices(self, qtbot, input_type):
new_parameter_set = {
"basetype": input_type.name.lower(),
"data": {"default": 3, "type": "Choices", "choices": [0, 3]},
"description": "some description",
"name": "some name",
}
parameter = ParameterWidget()
qtbot.addWidget(parameter)
with qtbot.waitSignal(parameter.dataChanged):
parameter.load(new_parameter_set)
assert parameter.dump() == new_parameter_set
def test_load_dump_parameter_numpy_type_range(self, qtbot, input_type):
new_parameter_set = {
"basetype": input_type.name.lower(),
"data": {"default": 3, "type": "Range", "minimum": 1, "maximum": 4},
"description": "some description",
"name": "some name",
}
parameter = ParameterWidget()
qtbot.addWidget(parameter)
with qtbot.waitSignal(parameter.dataChanged):
parameter.load(new_parameter_set)
assert parameter.dump() == new_parameter_set
def test_load_dump_parameter_string_unrestricted(self, qtbot):
new_parameter_set = {
"basetype": "string",
"data": {"default": "some text", "type": "Unrestricted"},
"description": "some description",
"name": "some name",
}
parameter = ParameterWidget()
qtbot.addWidget(parameter)
with qtbot.waitSignal(parameter.dataChanged):
parameter.load(new_parameter_set)
assert parameter.dump() == new_parameter_set
def test_load_dump_parameter_string_choices(self, qtbot):
new_parameter_set = {
"basetype": "string",
"data": {
"default": "some text",
"type": "Choices",
"choices": ["text 1", "text 2"],
},
"description": "some description",
"name": "some name",
}
parameter = ParameterWidget()
qtbot.addWidget(parameter)
with qtbot.waitSignal(parameter.dataChanged):
parameter.load(new_parameter_set)
assert parameter.dump() == new_parameter_set
def test_load_dump_parameter_bool_default(self, qtbot):
new_parameter_set = {
"basetype": "bool",
"data": {"default": True},
"description": "some description",
"name": "some name",
}
parameter = ParameterWidget()
qtbot.addWidget(parameter)
with qtbot.waitSignal(parameter.dataChanged):
parameter.load(new_parameter_set)
assert parameter.dump() == new_parameter_set
def test_change_type(self, qtbot, input_type):
default_parameter_set = {
"basetype": input_type.name.lower(),
"data": {"default": 0, "type": "Unrestricted"},
"description": "",
"name": "",
}
parameter = ParameterWidget()
qtbot.addWidget(parameter)
with qtbot.waitSignal(parameter.dataChanged):
qtbot.keyClicks(parameter.basetype_comboxbox, input_type.name.lower())
assert parameter.dump() == default_parameter_set
def test_change_type_to_string(self, qtbot):
default_parameter_set = {
"basetype": "string",
"data": {"default": "", "type": "Unrestricted"},
"description": "",
"name": "",
}
parameter = ParameterWidget()
qtbot.addWidget(parameter)
with qtbot.waitSignal(parameter.dataChanged):
qtbot.keyClicks(parameter.basetype_comboxbox, "string")
assert parameter.dump() == default_parameter_set
def test_change_type_to_bool(self, qtbot):
default_parameter_set = {
"basetype": "bool",
"data": {"default": True},
"description": "",
"name": "",
}
parameter = ParameterWidget()
qtbot.addWidget(parameter)
with qtbot.waitSignal(parameter.dataChanged):
qtbot.keyClicks(parameter.basetype_comboxbox, "bool")
assert parameter.dump() == default_parameter_set
def test_numpy_type_change_name(self, qtbot, input_type):
name = "name"
updated_parameter_set = {
"basetype": input_type.name.lower(),
"data": {"default": 0, "type": "Unrestricted"},
"description": "",
"name": name,
}
parameter = ParameterWidget()
qtbot.addWidget(parameter)
with qtbot.waitSignal(parameter.dataChanged):
qtbot.keyClicks(parameter.basetype_comboxbox, input_type.name.lower())
qtbot.keyClicks(parameter.name, name)
assert parameter.dump() == updated_parameter_set
def test_string_type_change_name(self, qtbot):
name = "name"
updated_parameter_set = {
"basetype": "string",
"data": {"default": "", "type": "Unrestricted"},
"description": "",
"name": name,
}
parameter = ParameterWidget()
qtbot.addWidget(parameter)
with qtbot.waitSignal(parameter.dataChanged):
qtbot.keyClicks(parameter.basetype_comboxbox, "string")
qtbot.keyClicks(parameter.name, name)
assert parameter.dump() == updated_parameter_set
def test_bool_type_change_name(self, qtbot):
name = "name"
updated_parameter_set = {
"basetype": "bool",
"data": {"default": True},
"description": "",
"name": name,
}
parameter = ParameterWidget()
qtbot.addWidget(parameter)
with qtbot.waitSignal(parameter.dataChanged):
qtbot.keyClicks(parameter.basetype_comboxbox, "bool")
qtbot.keyClicks(parameter.name, name)
assert parameter.dump() == updated_parameter_set
def test_numpy_type_change_description(self, qtbot, input_type):
description = "description"
updated_parameter_set = {
"basetype": input_type.name.lower(),
"data": {"default": 0, "type": "Unrestricted"},
"description": description,
"name": "",
}
parameter = ParameterWidget()
qtbot.addWidget(parameter)
with qtbot.waitSignal(parameter.dataChanged):
qtbot.keyClicks(parameter.basetype_comboxbox, input_type.name.lower())
qtbot.keyClicks(parameter.description, description)
assert parameter.dump() == updated_parameter_set
def test_string_type_change_description(self, qtbot):
description = "description"
updated_parameter_set = {
"basetype": "string",
"data": {"default": "", "type": "Unrestricted"},
"description": description,
"name": "",
}
parameter = ParameterWidget()
qtbot.addWidget(parameter)
with qtbot.waitSignal(parameter.dataChanged):
qtbot.keyClicks(parameter.basetype_comboxbox, "string")
qtbot.keyClicks(parameter.description, description)
assert parameter.dump() == updated_parameter_set
def test_bool_type_change_description(self, qtbot):
description = "description"
updated_parameter_set = {
"basetype": "bool",
"data": {"default": True},
"description": description,
"name": "",
}
parameter = ParameterWidget()
qtbot.addWidget(parameter)
with qtbot.waitSignal(parameter.dataChanged):
qtbot.keyClicks(parameter.basetype_comboxbox, "bool")
qtbot.keyClicks(parameter.description, description)
assert parameter.dump() == updated_parameter_set
def test_numpy_type_change_default_valid_input(self, qtbot, input_type):
value = "4"
updated_parameter_set = {
"basetype": input_type.name.lower(),
"data": {"default": 4, "type": "Unrestricted"},
"description": "",
"name": "",
}
parameter = ParameterWidget()
qtbot.addWidget(parameter)
with qtbot.waitSignal(parameter.dataChanged):
qtbot.keyClicks(parameter.basetype_comboxbox, input_type.name.lower())
qtbot.keyClicks(parameter.choices_range_widget.default_spinbox, value)
assert parameter.dump() == updated_parameter_set
def test_numpy_type_change_default_invalid_input(
self, qtbot, input_type, expected_values
):
value = "44444444444444444444444444444444444444444444444444444444444"
parameter = ParameterWidget()
spinbox = parameter.choices_range_widget.default_spinbox
qtbot.addWidget(parameter)
qtbot.keyClicks(parameter.basetype_comboxbox, input_type.name.lower())
expected_value = None
for item in expected_values:
if spinbox.numpy_type == item[0]:
expected_value = item[1]
break
assert expected_value is not None
with qtbot.waitSignal(parameter.dataChanged):
qtbot.keyClicks(spinbox, value)
assert spinbox.value() == spinbox.numpy_type(expected_value)
def test_type_string_change_default_input(self, qtbot):
value = "somevalue"
updated_parameter_set = {
"basetype": "string",
"data": {"default": value, "type": "Unrestricted"},
"description": "",
"name": "",
}
parameter = ParameterWidget()
qtbot.addWidget(parameter)
with qtbot.waitSignal(parameter.dataChanged):
qtbot.keyClicks(parameter.basetype_comboxbox, "string")
qtbot.keyClicks(parameter.choices_widget.default_ledit, value)
assert parameter.dump() == updated_parameter_set
def test_type_bool_change_default_input(self, qtbot):
default_parameter_set = {
"basetype": "bool",
"data": {"default": True},
"description": "",
"name": "",
}
parameter = ParameterWidget()
qtbot.addWidget(parameter)
with qtbot.waitSignal(parameter.dataChanged):
qtbot.keyClicks(parameter.basetype_comboxbox, "bool")
assert parameter.dump() == default_parameter_set
default_parameter_set["data"]["default"] = False
with qtbot.waitSignal(parameter.dataChanged):
qtbot.mouseClick(parameter.bool_widget.false_button, QtCore.Qt.LeftButton)
assert parameter.dump() == default_parameter_set
def test_change_types_restrictions_choices(self, qtbot, input_type):
default_parameter_set = {
"basetype": input_type.name.lower(),
"data": {"choices": [], "default": 0, "type": "Choices"},
"description": "",
"name": "",
}
parameter = ParameterWidget()
qtbot.addWidget(parameter)
with qtbot.waitSignal(parameter.dataChanged):
qtbot.keyClicks(parameter.basetype_comboxbox, input_type.name.lower())
qtbot.keyClicks(
parameter.choices_range_widget.restricts_combobox, "Choices"
)
assert parameter.dump() == default_parameter_set
def test_change_type_to_string_choices(self, qtbot):
default_parameter_set = {
"basetype": "string",
"data": {"choices": [], "default": "", "type": "Choices"},
"description": "",
"name": "",
}
parameter = ParameterWidget()
qtbot.addWidget(parameter)
with qtbot.waitSignal(parameter.dataChanged):
qtbot.keyClicks(parameter.basetype_comboxbox, "string")
qtbot.keyClicks(parameter.choices_widget.restricts_combobox, "Choices")
assert parameter.dump() == default_parameter_set
def test_change_types_restrictions_range(self, qtbot, input_type):
default_parameter_set = {
"basetype": input_type.name.lower(),
"data": {"default": 0, "maximum": 0, "minimum": 0, "type": "Range"},
"description": "",
"name": "",
}
parameter = ParameterWidget()
qtbot.addWidget(parameter)
with qtbot.waitSignal(parameter.dataChanged):
qtbot.keyClicks(parameter.basetype_comboxbox, input_type.name.lower())
qtbot.keyClicks(parameter.choices_range_widget.restricts_combobox, "Range")
assert parameter.dump() == default_parameter_set
def test_change_types_restrictions_range_valid_input(self, qtbot, input_type):
value = "4"
np_value = input_type.np_type(value)
default_parameter_set = {
"basetype": input_type.name.lower(),
"data": {"default": 0, "maximum": 0, "minimum": 0, "type": "Range"},
"description": "",
"name": "",
}
parameter = ParameterWidget()
qtbot.addWidget(parameter)
with qtbot.waitSignal(parameter.dataChanged):
qtbot.keyClicks(parameter.basetype_comboxbox, input_type.name.lower())
qtbot.keyClicks(parameter.choices_range_widget.restricts_combobox, "Range")
assert parameter.dump() == default_parameter_set
default_parameter_set["data"]["default"] = np_value
default_parameter_set["data"]["minimum"] = np_value
default_parameter_set["data"]["maximum"] = np_value
with qtbot.waitSignal(parameter.dataChanged):
qtbot.keyClicks(parameter.choices_range_widget.default_spinbox, value)
qtbot.keyClicks(parameter.choices_range_widget.minimum_value, value)
qtbot.keyClicks(parameter.choices_range_widget.maximum_value, value)
assert parameter.dump() == default_parameter_set
def test_change_types_restrictions_range_invalid_input(
self, qtbot, input_type, expected_values
):
value = "44444444444444444444444444444444444444444444444444444444444"
parameter = ParameterWidget()
spinbox_default = parameter.choices_range_widget.default_spinbox
spinbox_min = parameter.choices_range_widget.minimum_value
spinbox_max = parameter.choices_range_widget.maximum_value
qtbot.addWidget(parameter)
qtbot.keyClicks(parameter.basetype_comboxbox, input_type.name.lower())
expected_value = None
for item in expected_values:
if spinbox_default.numpy_type == item[0]:
expected_value = item[1]
break
assert expected_value is not None
with qtbot.waitSignal(parameter.dataChanged):
qtbot.keyClicks(spinbox_default, value)
qtbot.keyClicks(spinbox_min, value)
qtbot.keyClicks(spinbox_max, value)
assert spinbox_default.value() == spinbox_default.numpy_type(expected_value)
assert spinbox_min.value() == spinbox_min.numpy_type(expected_value)
assert spinbox_max.value() == spinbox_max.numpy_type(expected_value)
def test_change_numpy_types_restrictions_choices_input(self, qtbot, input_type):
def handle_dialog(value, ok_cancel):
# QApplication topLevelWidgets()/activeModalWidget() give insights on upper/active objects
dialog = QApplication.activeModalWidget()
qtbot.keyClicks(dialog.spinbox, value)
qtbot.mouseClick(dialog.buttons.buttons()[ok_cancel], QtCore.Qt.LeftButton)
default_value = "9"
np_value = input_type.np_type(default_value)
value_1 = "1"
value_2 = "2"
value_3 = "3"
default_parameter_set = {
"basetype": input_type.name.lower(),
"data": {"choices": [], "default": 0, "type": "Choices"},
"description": "",
"name": "",
}
parameter = ParameterWidget()
qtbot.addWidget(parameter)
with qtbot.waitSignal(parameter.dataChanged):
qtbot.keyClicks(parameter.basetype_comboxbox, input_type.name.lower())
qtbot.keyClicks(
parameter.choices_range_widget.restricts_combobox, "Choices"
)
assert parameter.dump() == default_parameter_set
# Change default value
default_parameter_set["data"]["default"] = np_value
with qtbot.waitSignal(parameter.dataChanged):
qtbot.keyClicks(
parameter.choices_range_widget.default_spinbox, default_value
)
assert parameter.dump() == default_parameter_set
ok_button = 0
cancel_button = 1
# add 3 choices and click on Cancel each time
QTimer.singleShot(1, lambda: handle_dialog(value_1, cancel_button))
qtbot.mouseClick(
parameter.choices_range_widget.add_button, QtCore.Qt.LeftButton
)
QTimer.singleShot(1, lambda: handle_dialog(value_2, cancel_button))
qtbot.mouseClick(
parameter.choices_range_widget.add_button, QtCore.Qt.LeftButton
)
QTimer.singleShot(1, lambda: handle_dialog(value_3, cancel_button))
qtbot.mouseClick(
parameter.choices_range_widget.add_button, QtCore.Qt.LeftButton
)
assert parameter.dump() == default_parameter_set
# add 3 choices and click on Ok each time
default_parameter_set["data"]["choices"] = [1, 2, 3]
QTimer.singleShot(1, lambda: handle_dialog(value_1, ok_button))
qtbot.mouseClick(
parameter.choices_range_widget.add_button, QtCore.Qt.LeftButton
)
QTimer.singleShot(1, lambda: handle_dialog(value_2, ok_button))
qtbot.mouseClick(
parameter.choices_range_widget.add_button, QtCore.Qt.LeftButton
)
QTimer.singleShot(1, lambda: handle_dialog(value_3, ok_button))
qtbot.mouseClick(
parameter.choices_range_widget.add_button, QtCore.Qt.LeftButton
)
assert parameter.dump() == default_parameter_set
# vim: set fileencoding=utf-8 :
###############################################################################
# #
# Copyright (c) 2019 Idiap Research Institute, http://www.idiap.ch/ #
# Contact: beat.support@idiap.ch #
# #
# This file is part of the beat.editor module of the BEAT platform. #
# #
# Commercial License Usage #
# Licensees holding valid commercial BEAT licenses may use this file in #
# accordance with the terms contained in a written agreement between you #
# and Idiap. For further information contact tto@idiap.ch #
# #
# Alternatively, this file may be used under the terms of the GNU Affero #
# Public License version 3 as published by the Free Software and appearing #
# in the file LICENSE.AGPL included in the packaging of this file. #
# The BEAT platform is distributed in the hope that it will be useful, but #
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY #
# or FITNESS FOR A PARTICULAR PURPOSE. #
# #
# You should have received a copy of the GNU Affero Public License along #
# with the BEAT platform. If not, see http://www.gnu.org/licenses/. #