class LoadFileWidgetViewTest(unittest.TestCase): def setUp(self): self.view = BrowseFileWidgetView() # ------------------------------------------------------------------------------------------------------------------ # TESTS # ------------------------------------------------------------------------------------------------------------------ def test_view_initialized_with_empty_line_edit(self): self.assertEqual(self.view.get_file_edit_text(), "No data loaded") def test_reset_text_to_cache_resets_correctly(self): text = r"C:\dir1\dir2\EMU00012345.nxs;C:\dir1\dir2\EMU00012345.nxs" self.view.set_file_edit(text) # User may then overwrite the text in the LineEdit, causing a signal to be sent # and the corresponding slot should implement reset_edit_to_cached_value() self.view.reset_edit_to_cached_value() self.assertEqual(self.view.get_file_edit_text(), text) def test_text_clears_from_line_edit_correctly(self): text = r"C:\dir1\dir2\EMU00012345.nxs;C:\dir1\dir2\EMU00012345.nxs" self.view.set_file_edit(text) self.view.clear() self.assertEqual(self.view.get_file_edit_text(), "No data loaded") self.view.reset_edit_to_cached_value() self.assertEqual(self.view.get_file_edit_text(), "No data loaded") def test_text_stored_correctly_when_not_visible_in_line_edit(self): # This feature is currently unused text = r"C:\dir1\dir2\EMU00012345.nxs;C:\dir1\dir2\EMU00012345.nxs" self.view.set_file_edit(text, store=True) self.assertEqual(self.view.get_file_edit_text(), text) self.view.reset_edit_to_cached_value() self.assertEqual(self.view.get_file_edit_text(), text)
class LoadFileWidgetPresenterTest(unittest.TestCase): def run_test_with_and_without_threading(test_function): def run_twice(self): test_function(self) self.setUp() self.presenter._use_threading = False test_function(self) return run_twice def wait_for_thread(self, thread_model): if thread_model: thread_model._thread.wait() QApplication.sendPostedEvents() def setUp(self): self.view = BrowseFileWidgetView() self.view.on_browse_clicked = mock.Mock() self.view.set_file_edit = mock.Mock() self.view.reset_edit_to_cached_value = mock.Mock() self.view.show_file_browser_and_return_selection = mock.Mock( return_value=["C:/dir1/file1.nxs", "C:/dir2/file2.nxs"]) setup_context_for_tests(self) self.data_context.instrument = 'EMU' self.model = BrowseFileWidgetModel(self.loaded_data, self.context) self.model.exception_message_for_failed_files = mock.Mock() self.view.disable_load_buttons = mock.Mock() self.view.enable_load_buttons = mock.Mock() self.view.warning_popup = mock.Mock() self.presenter = BrowseFileWidgetPresenter(self.view, self.model) patcher = mock.patch('mantidqtinterfaces.Muon.GUI.Common.load_file_widget.model.load_utils.load_workspace_from_filename') self.addCleanup(patcher.stop) self.load_utils_patcher = patcher.start() self.load_utils_patcher.return_value = (self.create_fake_workspace(1), '22222', 'filename') def mock_browse_button_to_return_files(self, files): self.view.show_file_browser_and_return_selection = mock.Mock(return_value=files) def mock_user_input_text(self, text): self.view.get_file_edit_text = mock.Mock(return_value=text) def mock_model_to_load_workspaces(self, workspaces, runs, filenames): psi_data = [False] * len(filenames) self.load_utils_patcher.side_effect = zip(workspaces, runs, filenames, psi_data) def load_workspaces_into_model_and_view_from_browse(self, workspaces, runs, files): self.mock_model_to_load_workspaces(workspaces, runs, files) self.mock_browse_button_to_return_files(files) self.presenter.on_browse_button_clicked() self.wait_for_thread(self.presenter._load_thread) def load_failure(self, unused_arg): raise ValueError("Error text") def create_fake_workspace(self, name): workspace_mock = mock.MagicMock() instrument_mock = mock.MagicMock() instrument_mock.getName.return_value = 'EMU' workspace_mock.workspace.getInstrument.return_value = instrument_mock return {'OutputWorkspace': [workspace_mock]} # ------------------------------------------------------------------------------------------------------------------ # TESTS # ------------------------------------------------------------------------------------------------------------------ @run_test_with_and_without_threading def test_browser_dialog_opens_when_browse_button_clicked(self): self.mock_browse_button_to_return_files(["file.nxs"]) self.presenter.on_browse_button_clicked() self.wait_for_thread(self.presenter._load_thread) self.assertEqual(self.view.show_file_browser_and_return_selection.call_count, 1) @run_test_with_and_without_threading def test_loading_not_initiated_if_no_file_selected_from_browser(self): self.mock_model_to_load_workspaces([], [], []) self.mock_browse_button_to_return_files([]) self.presenter.on_browse_button_clicked() self.wait_for_thread(self.presenter._load_thread) self.assertEqual(self.load_utils_patcher.call_count, 0) @run_test_with_and_without_threading def test_buttons_disabled_while_load_thread_running(self): self.mock_browse_button_to_return_files(["file.nxs"]) self.presenter.on_browse_button_clicked() self.wait_for_thread(self.presenter._load_thread) self.load_utils_patcher.assert_called_once_with("file.nxs") self.assertEqual(self.view.disable_load_buttons.call_count, 1) self.assertEqual(self.view.enable_load_buttons.call_count, 1) @run_test_with_and_without_threading def test_buttons_enabled_after_load_even_if_load_thread_throws(self): self.mock_browse_button_to_return_files(["file.nxs"]) self.load_utils_patcher.side_effect = self.load_failure self.presenter.on_browse_button_clicked() self.wait_for_thread(self.presenter._load_thread) self.load_utils_patcher.assert_called_once_with("file.nxs") self.assertEqual(self.view.disable_load_buttons.call_count, 1) self.assertEqual(self.view.enable_load_buttons.call_count, 1) @run_test_with_and_without_threading def test_single_file_from_browse_loaded_into_model_and_view_in_single_file_mode(self): workspace = self.create_fake_workspace(1) self.mock_browse_button_to_return_files(["C:/dir1/file1.nxs"]) self.mock_model_to_load_workspaces([workspace], [1234], ["C:/dir1/file1.nxs"]) self.view.set_file_edit = mock.Mock() self.presenter.on_browse_button_clicked() self.wait_for_thread(self.presenter._load_thread) self.assertEqual(self.model.loaded_filenames, ["C:/dir1/file1.nxs"]) self.assertEqual(self.model.loaded_workspaces, [workspace]) self.assertEqual(self.model.loaded_runs, [[1234]]) self.view.set_file_edit.assert_called_once_with("C:/dir1/file1.nxs", mock.ANY) @run_test_with_and_without_threading def test_single_file_from_user_input_loaded_into_model_and_view_in_single_file_mode(self): workspace = self.create_fake_workspace(1) self.view.set_file_edit = mock.Mock() self.mock_model_to_load_workspaces([workspace], [1234], ["C:/dir1/file1.nxs"]) self.mock_user_input_text("C:/dir1/file1.nxs") self.presenter.handle_file_changed_by_user() self.wait_for_thread(self.presenter._load_thread) self.assertEqual(self.model.loaded_filenames, ["C:/dir1/file1.nxs"]) self.assertEqual(self.model.loaded_workspaces, [workspace]) self.assertEqual(self.model.loaded_runs, [[1234]]) self.view.set_file_edit.assert_called_once_with("C:/dir1/file1.nxs", mock.ANY) @run_test_with_and_without_threading def test_that_if_invalid_file_selected_in_browser_view_does_not_change(self): workspace = self.create_fake_workspace(1) self.mock_browse_button_to_return_files(["not_a_file"]) self.mock_model_to_load_workspaces([workspace], [1234], ["not_a_file"]) self.view.set_file_edit = mock.Mock() self.view.reset_edit_to_cached_value = mock.Mock() self.presenter.on_browse_button_clicked() self.wait_for_thread(self.presenter._load_thread) self.load_utils_patcher.side_effect = self.load_failure set_file_edit_count = self.view.set_file_edit.call_count self.presenter.on_browse_button_clicked() self.wait_for_thread(self.presenter._load_thread) self.assertEqual(self.view.set_file_edit.call_count, set_file_edit_count) self.assertEqual(self.view.reset_edit_to_cached_value.call_count, 0) @run_test_with_and_without_threading def test_that_view_reverts_to_previous_text_if_users_supplies_invalid_text(self): workspace = self.create_fake_workspace(1) self.load_workspaces_into_model_and_view_from_browse([workspace], [[1234]], ["C:/dir1/EMU0001234.nxs"]) invalid_user_input = ["some random text", "1+1=2", "..."] call_count = self.view.reset_edit_to_cached_value.call_count for invalid_text in invalid_user_input: call_count += 1 self.view.get_file_edit_text = mock.Mock(return_value=invalid_text) self.presenter.handle_file_changed_by_user() self.wait_for_thread(self.presenter._load_thread) self.assertEqual(self.view.reset_edit_to_cached_value.call_count, call_count) @run_test_with_and_without_threading def test_that_model_and_interface_revert_to_previous_values_if_load_fails_from_browse(self): workspace = self.create_fake_workspace(1) self.load_workspaces_into_model_and_view_from_browse([workspace], [1234], ["C:/dir1/EMU0001234.nxs"]) self.load_utils_patcher.side_effect = self.load_failure self.presenter.on_browse_button_clicked() self.wait_for_thread(self.presenter._load_thread) self.assertEqual(self.model.loaded_filenames, ["C:/dir1/EMU0001234.nxs"]) self.assertEqual(self.model.loaded_workspaces, [workspace]) self.assertEqual(self.model.loaded_runs, [[1234]]) self.assertEqual(self.view.reset_edit_to_cached_value.call_count, 0) self.assertEqual(self.view.set_file_edit.call_args[0][0], "C:/dir1/EMU0001234.nxs") @run_test_with_and_without_threading def test_that_model_and_interface_revert_to_previous_values_if_load_fails_from_user_input(self): workspace = self.create_fake_workspace(1) self.load_workspaces_into_model_and_view_from_browse([workspace], [1234], ["C:/dir1/EMU0001234.nxs"]) self.load_utils_patcher.side_effect = self.load_failure self.view.set_file_edit(r"C:\dir2\EMU000123.nxs") self.presenter.handle_file_changed_by_user() self.wait_for_thread(self.presenter._load_thread) self.assertEqual(self.model.loaded_filenames, ["C:/dir1/EMU0001234.nxs"]) self.assertEqual(self.model.loaded_workspaces, [workspace]) self.assertEqual(self.model.loaded_runs, [[1234]]) self.assertEqual(self.view.reset_edit_to_cached_value.call_count, 1)
class LoadFileWidgetPresenterMultipleFileModeTest(unittest.TestCase): def run_test_with_and_without_threading(test_function): def run_twice(self): test_function(self) self.setUp() self.presenter._use_threading = False test_function(self) return run_twice def wait_for_thread(self, thread_model): if thread_model: thread_model._thread.wait() QApplication.sendPostedEvents() def setUp(self): setup_context_for_tests(self) self.data_context.instrument = 'EMU' self.view = BrowseFileWidgetView() self.model = BrowseFileWidgetModel(self.loaded_data, self.context) self.view.disable_load_buttons = mock.Mock() self.view.enable_load_buttons = mock.Mock() self.view.warning_popup = mock.Mock() self.presenter = BrowseFileWidgetPresenter(self.view, self.model) patcher = mock.patch('mantidqtinterfaces.Muon.GUI.Common.load_file_widget.model.load_utils.load_workspace_from_filename') self.addCleanup(patcher.stop) self.load_utils_patcher = patcher.start() self.load_utils_patcher.return_value = (self.create_fake_workspace(1), '22222', 'filename') def mock_loading_multiple_files_from_browse(self, runs, workspaces, filenames): self.view.show_file_browser_and_return_selection = mock.Mock(return_value=filenames) psi_data = [False] * len(filenames) self.load_utils_patcher.side_effect = zip(workspaces, runs, filenames, psi_data) def create_fake_workspace(self, name): workspace_mock = mock.MagicMock() instrument_mock = mock.MagicMock() instrument_mock.getName.return_value = 'EMU' workspace_mock.workspace.getInstrument.return_value = instrument_mock return {'OutputWorkspace': [workspace_mock]} # ------------------------------------------------------------------------------------------------------------------ # TESTS : Multiple runs can be selected via browse and entered explicitly using the ";" separator # ------------------------------------------------------------------------------------------------------------------ @run_test_with_and_without_threading def test_that_cannot_load_same_file_twice_from_same_browse_even_if_filepaths_are_different(self): workspace_1 = self.create_fake_workspace(1) workspace_2 = self.create_fake_workspace(2) self.view.show_file_browser_and_return_selection = mock.Mock( return_value=["C:/dir1/file1.nxs", "C:/dir2/file1.nxs", "C:/dir2/file2.nxs"]) self.load_utils_patcher.load_workspace_from_filename = mock.Mock(side_effect=zip([workspace_1, workspace_2], [1234, 1234], ["C:/dir1/file1.nxs", "C:/dir2/file2.nxs"], [False, False])) self.presenter.on_browse_button_clicked() self.wait_for_thread(self.presenter._load_thread) self.assertEqual(self.load_utils_patcher.call_count, 2) self.load_utils_patcher.assert_any_call("C:/dir1/file1.nxs") self.load_utils_patcher.assert_any_call("C:/dir2/file2.nxs") @run_test_with_and_without_threading def test_that_cannot_load_same_file_twice_from_user_input_even_if_filepaths_are_different(self): workspace_1 = self.create_fake_workspace(1) workspace_2 = self.create_fake_workspace(2) self.load_utils_patcher.load_workspace_from_filename = mock.Mock(side_effect=zip([workspace_1, workspace_2], [1234, 1234], ["C:/dir1/file1.nxs", "C:/dir2/file2.nxs"], [False, False])) self.view.set_file_edit("C:/dir1/file1.nxs;C:/dir2/file1.nxs;C:/dir2/file2.nxs") self.presenter.handle_file_changed_by_user() self.wait_for_thread(self.presenter._load_thread) self.assertEqual(self.load_utils_patcher.call_count, 2) self.load_utils_patcher.assert_any_call("C:/dir1/file1.nxs") self.load_utils_patcher.assert_any_call("C:/dir2/file2.nxs") @run_test_with_and_without_threading def test_that_cannot_browse_and_load_same_run_twice_even_if_filenames_are_different(self): workspace_1 = self.create_fake_workspace(1) workspace_2 = self.create_fake_workspace(2) self.load_utils_patcher.side_effect = zip([workspace_1, workspace_2], [1234, 1234], ["C:/dir1/file1.nxs", "C:/dir1/file2.nxs"], [False, False]) self.view.show_file_browser_and_return_selection = mock.Mock( return_value=["C:/dir1/file1.nxs", "C:/dir1/file2.nxs"]) self.presenter.on_browse_button_clicked() self.wait_for_thread(self.presenter._load_thread) # Load will take the last occurrence of the run from the list self.assertCountEqual(self.model.loaded_filenames, ["C:/dir1/file2.nxs"]) self.assertCountEqual(self.model.loaded_workspaces, [workspace_2]) self.assertCountEqual(self.model.loaded_runs, [[1234]]) # @run_test_with_and_without_threading def test_that_cannot_input_and_load_same_run_twice_even_if_filenames_are_different(self): workspace_1 = self.create_fake_workspace(1) workspace_2 = self.create_fake_workspace(2) self.load_utils_patcher.side_effect = zip([workspace_1, workspace_2], [1234, 1234], ["C:/dir1/file1.nxs", "C:/dir1/file2.nxs"], [False, False]) self.view.set_file_edit("C:/dir1/file1.nxs;C:/dir1/file2.nxs") self.presenter.handle_file_changed_by_user() self.wait_for_thread(self.presenter._load_thread) # Load will take the last occurrence of the run from the user input self.assertCountEqual(self.model.loaded_filenames, ["C:/dir1/file2.nxs"]) self.assertCountEqual(self.model.loaded_workspaces, [workspace_2]) self.assertCountEqual(self.model.loaded_runs, [[1234]]) @run_test_with_and_without_threading def test_that_loading_two_files_from_browse_sets_model_and_interface_correctly(self): workspace_1 = self.create_fake_workspace(1) workspace_2 = self.create_fake_workspace(2) self.mock_loading_multiple_files_from_browse([1234, 1235], [workspace_1, workspace_2], ["C:/dir1/file1.nxs", "C:/dir2/file2.nxs"]) self.presenter.on_browse_button_clicked() self.wait_for_thread(self.presenter._load_thread) self.assertEqual(self.model.loaded_filenames, ["C:/dir1/file1.nxs", "C:/dir2/file2.nxs"]) self.assertEqual(self.model.loaded_workspaces, [workspace_1, workspace_2]) self.assertEqual(self.model.loaded_runs, [[1234], [1235]]) self.assertEqual(self.view.get_file_edit_text(), "C:/dir1/file1.nxs;C:/dir2/file2.nxs") @run_test_with_and_without_threading def test_that_loading_two_files_from_user_input_sets_model_and_interface_correctly(self): workspace_1 = self.create_fake_workspace(1) workspace_2 = self.create_fake_workspace(2) self.load_utils_patcher.side_effect = zip([workspace_1, workspace_2], [1234, 1235], ["C:/dir1/file1.nxs", "C:/dir2/file2.nxs"], [False, False]) self.view.set_file_edit("C:/dir1/file1.nxs;C:/dir2/file2.nxs") self.presenter.handle_file_changed_by_user() self.wait_for_thread(self.presenter._load_thread) self.assertEqual(self.model.loaded_filenames, ["C:/dir1/file1.nxs", "C:/dir2/file2.nxs"]) self.assertEqual(self.model.loaded_workspaces, [workspace_1, workspace_2]) self.assertEqual(self.model.loaded_runs, [[1234], [1235]]) self.assertEqual(self.view.get_file_edit_text(), "C:/dir1/file1.nxs;C:/dir2/file2.nxs") @run_test_with_and_without_threading def test_that_loading_two_files_from_browse_sets_interface_alphabetically(self): workspace_1 = self.create_fake_workspace(1) workspace_2 = self.create_fake_workspace(2) self.mock_loading_multiple_files_from_browse([1234, 1235], [workspace_1, workspace_2], ["C:/dir1/file2.nxs", "C:/dir1/file1.nxs"]) self.presenter.on_browse_button_clicked() self.wait_for_thread(self.presenter._load_thread) self.assertEqual(self.view.get_file_edit_text(), "C:/dir1/file1.nxs;C:/dir1/file2.nxs") @run_test_with_and_without_threading def test_that_loading_two_files_from_user_input_sets_interface_alphabetically(self): workspace_1 = self.create_fake_workspace(1) workspace_2 = self.create_fake_workspace(2) self.load_utils_patcher.side_effect = zip([workspace_2, workspace_1], [1235, 1234], ["C:/dir1/file2.nxs", "C:/dir1/file1.nxs"], [False, False]) self.view.set_file_edit("C:/dir1/file2.nxs;C:/dir1/file1.nxs") self.presenter.handle_file_changed_by_user() self.wait_for_thread(self.presenter._load_thread) self.assertEqual(self.view.get_file_edit_text(), "C:/dir1/file1.nxs;C:/dir1/file2.nxs") @run_test_with_and_without_threading def test_that_browse_allows_loading_of_additional_files(self): workspace_1 = self.create_fake_workspace(1) workspace_2 = self.create_fake_workspace(2) workspace_3 = self.create_fake_workspace(3) self.mock_loading_multiple_files_from_browse([1234, 1235], [workspace_1, workspace_2], ["C:/dir1/file1.nxs", "C:/dir2/file2.nxs"]) self.presenter.on_browse_button_clicked() self.wait_for_thread(self.presenter._load_thread) self.mock_loading_multiple_files_from_browse([1236], [workspace_3], ["C:/dir1/file3.nxs"]) self.presenter.on_browse_button_clicked() self.wait_for_thread(self.presenter._load_thread) self.assertCountEqual(self.model.loaded_filenames, ["C:/dir1/file1.nxs", "C:/dir2/file2.nxs", "C:/dir1/file3.nxs"]) self.assertCountEqual(self.model.loaded_workspaces, [workspace_1, workspace_2, workspace_3]) self.assertCountEqual(self.model.loaded_runs, [[1234], [1235], [1236]]) self.assertEqual(self.view.get_file_edit_text(), "C:/dir1/file3.nxs") @run_test_with_and_without_threading def test_that_loading_an_already_loaded_run_from_different_file_overwrites(self): workspace_1 = self.create_fake_workspace(1) workspace_2 = self.create_fake_workspace(2) workspace_3 = self.create_fake_workspace(3) self.mock_loading_multiple_files_from_browse([1234, 1235], [workspace_1, workspace_2], ["C:/dir1/file1.nxs", "C:/dir2/file2.nxs"]) self.presenter.on_browse_button_clicked() self.wait_for_thread(self.presenter._load_thread) # only checks runs, so can have a different file/workspace (this is why overwriting is # the most useful behaviour in this situation). self.mock_loading_multiple_files_from_browse([1234], [workspace_3], ["C:/dir2/file1.nxs"]) self.presenter.on_browse_button_clicked() self.wait_for_thread(self.presenter._load_thread) self.assertCountEqual(self.model.loaded_filenames, ["C:/dir2/file1.nxs", "C:/dir2/file2.nxs"]) self.assertCountEqual(self.model.loaded_workspaces, [workspace_3, workspace_2]) self.assertCountEqual(self.model.loaded_runs, [[1234], [1235]]) self.assertEqual(self.view.get_file_edit_text(), "C:/dir2/file1.nxs")