def setUp(self):
        # Store an empty widget to parent all the views, and ensure they are deleted correctly
        self.obj = QWidget()

        setup_context_for_tests(self)

        self.data_context.instrument = 'EMU'
        self.view = LoadRunWidgetView(parent=self.obj)
        self.model = LoadRunWidgetModel(self.loaded_data, self.context)
        self.presenter = LoadRunWidgetPresenter(self.view, self.model)

        self.model.load_workspace_from_filename = mock.Mock(
            return_value=([1, 2, 3], "currentRun.nxs", 1234, False))
        self.view.warning_popup = mock.Mock()
        self.view.disable_load_buttons = mock.Mock()
        self.view.enable_load_buttons = mock.Mock()

        self.presenter.set_current_instrument("EMU")

        fileUtils.get_current_run_filename = mock.Mock(
            return_value="EMU0001234.nxs")

        patcher = mock.patch(
            'Muon.GUI.Common.load_run_widget.load_run_model.load_utils')
        self.addCleanup(patcher.stop)
        self.load_utils_patcher = patcher.start()
        self.load_utils_patcher.exception_message_for_failed_files.return_value = ''
    def setUp(self):
        # Store an empty widget to parent all the views, and ensure they are deleted correctly
        self.obj = QWidget()

        setup_context_for_tests(self)

        self.view = LoadRunWidgetView(parent=self.obj)
        self.model = LoadRunWidgetModel(self.loaded_data, self.context)
        self.presenter = LoadRunWidgetPresenter(self.view, self.model)

        self.view.warning_popup = mock.Mock()
        self.presenter.set_current_instrument("EMU")

        patcher = mock.patch(
            'Muon.GUI.Common.load_run_widget.load_run_model.load_utils')
        self.addCleanup(patcher.stop)
        self.load_utils_patcher = patcher.start()
        self.load_utils_patcher.exception_message_for_failed_files.return_value = ''

        file_finder_patcher = mock.patch(
            'Muon.GUI.Common.load_run_widget.load_run_presenter.FileFinder')
        self.addCleanup(file_finder_patcher.stop)
        file_finder_patcher.start()

        self.load_single_run()
    def setUp(self):
        # Store an empty widget to parent all the views, and ensure they are deleted correctly
        self.obj = QWidget()
        ConfigService['default.instrument'] = 'MUSR'

        setup_context_for_tests(self)
        self.context.instrument = 'MUSR'
        self.load_file_view = BrowseFileWidgetView(self.obj)
        self.load_run_view = LoadRunWidgetView(self.obj)
        self.load_file_model = BrowseFileWidgetModel(self.loaded_data,
                                                     self.context)
        self.load_run_model = LoadRunWidgetModel(self.loaded_data,
                                                 self.context)

        self.view = LoadWidgetView(parent=self.obj,
                                   load_file_view=self.load_file_view,
                                   load_run_view=self.load_run_view)
        self.presenter = LoadWidgetPresenter(
            self.view, LoadWidgetModel(self.loaded_data, self.context))
        self.presenter.set_load_file_widget(
            BrowseFileWidgetPresenter(self.load_file_view,
                                      self.load_file_model))
        self.presenter.set_load_run_widget(
            LoadRunWidgetPresenter(self.load_run_view, self.load_run_model))

        self.presenter.load_file_widget._view.warning_popup = mock.MagicMock()
        self.presenter.load_run_widget._view.warning_popup = mock.MagicMock()

        self.view.multiple_loading_check.setCheckState(1)
        self.presenter.handle_multiple_files_option_changed()

        self.runs = [15196, 15197]
        self.workspaces = [self.create_fake_workspace(1) for _ in self.runs]
        self.filenames = FileFinder.findRuns(
            'MUSR00015196.nxs, MUSR00015197.nxs')
    def setUp(self):
        self._qapp = mock_widget.mockQapp()

        # Store an empty widget to parent all the views, and ensure they are deleted correctly
        self.obj = QtGui.QWidget()

        self.popup_patcher = mock.patch('Muon.GUI.Common.thread_model.warning')
        self.addCleanup(self.popup_patcher.stop)
        self.popup_mock = self.popup_patcher.start()

        self.load_patcher = mock.patch(
            'Muon.GUI.Common.load_file_widget.model.load_utils.load_workspace_from_filename'
        )
        self.addCleanup(self.load_patcher.stop)
        self.load_mock = self.load_patcher.start()

        self.load_run_patcher = mock.patch(
            'Muon.GUI.Common.load_run_widget.load_run_model.load_utils.load_workspace_from_filename'
        )
        self.addCleanup(self.load_run_patcher.stop)
        self.load_run_mock = self.load_run_patcher.start()

        self.data = MuonLoadData()
        self.context = MuonDataContext(self.data)
        self.context.instrument = 'EMU'
        self.load_file_view = BrowseFileWidgetView(self.obj)
        self.load_run_view = LoadRunWidgetView(self.obj)
        self.load_file_model = BrowseFileWidgetModel(self.data, self.context)
        self.load_run_model = LoadRunWidgetModel(self.data, self.context)

        self.model = LoadWidgetModel(self.data, self.context)
        self.view = LoadWidgetView(parent=self.obj,
                                   load_run_view=self.load_run_view,
                                   load_file_view=self.load_file_view)

        self.presenter = LoadWidgetPresenter(view=self.view, model=self.model)
        self.presenter.set_load_file_widget(
            BrowseFileWidgetPresenter(self.load_file_view,
                                      self.load_file_model))
        self.presenter.set_load_run_widget(
            LoadRunWidgetPresenter(self.load_run_view, self.load_run_model))
        self.presenter.load_run_widget.set_current_instrument('EMU')

        self.presenter.load_file_widget._view.warning_popup = mock.MagicMock()
        self.presenter.load_run_widget._view.warning_popup = mock.MagicMock()

        self.load_file_view.show_file_browser_and_return_selection = mock.Mock(
            return_value=["C:\\dir1\\EMU0001234.nxs"])
        self.workspace_mock = self.create_fake_workspace(1)
        self.load_mock.return_value = (self.workspace_mock, 1234,
                                       "C:\\dir1\\EMU0001234.nxs")
        self.load_run_mock.return_value = (self.workspace_mock, 1234,
                                           "C:\\dir1\\EMU0001234.nxs")

        self.presenter.load_file_widget.on_browse_button_clicked()
        self.wait_for_thread(self.presenter.load_file_widget._load_thread)

        self.mock_loading_to_throw()
        file_utils.get_current_run_filename = mock.Mock(
            return_value="EMU0001234.nxs")
    def setUp(self):
        self._qapp = mock_widget.mockQapp()
        # Store an empty widget to parent all the views, and ensure they are deleted correctly
        self.obj = QtGui.QWidget()

        setup_context_for_tests(self)

        self.data_context.instrument = 'EMU'
        self.view = LoadRunWidgetView(parent=self.obj)
        self.model = LoadRunWidgetModel(self.loaded_data, self.context)
        self.presenter = LoadRunWidgetPresenter(self.view, self.model)

        self.model.load_workspace_from_filename = mock.Mock(return_value=([1, 2, 3], "currentRun.nxs", 1234))
        self.view.warning_popup = mock.Mock()
        self.view.disable_load_buttons = mock.Mock()
        self.view.enable_load_buttons = mock.Mock()

        self.presenter.set_current_instrument("EMU")

        fileUtils.get_current_run_filename = mock.Mock(return_value="EMU0001234.nxs")

        patcher = mock.patch('Muon.GUI.Common.load_run_widget.load_run_model.load_utils')
        self.addCleanup(patcher.stop)
        self.load_utils_patcher = patcher.start()
        self.load_utils_patcher.exception_message_for_failed_files.return_value = ''
    def setUp(self):
        # Store an empty widget to parent all the views, and ensure they are deleted correctly
        self.obj = QWidget()

        setup_context_for_tests(self)
        self.context.instrument = 'EMU'
        self.load_file_view = BrowseFileWidgetView(self.obj)
        self.load_run_view = LoadRunWidgetView(self.obj)
        self.load_file_model = BrowseFileWidgetModel(self.loaded_data,
                                                     self.context)
        self.load_run_model = LoadRunWidgetModel(self.loaded_data,
                                                 self.context)

        self.presenter = LoadWidgetPresenter(
            LoadWidgetView(parent=self.obj,
                           load_file_view=self.load_file_view,
                           load_run_view=self.load_run_view),
            LoadWidgetModel(self.loaded_data, self.context))
        self.presenter.set_load_file_widget(
            BrowseFileWidgetPresenter(self.load_file_view,
                                      self.load_file_model))
        self.presenter.set_load_run_widget(
            LoadRunWidgetPresenter(self.load_run_view, self.load_run_model))

        self.filepath = FileFinder.findRuns('MUSR00022725.nxs')[0]

        self.load_patcher = mock.patch(
            'Muon.GUI.Common.load_file_widget.model.load_utils.load_workspace_from_filename'
        )
        self.addCleanup(self.load_patcher.stop)
        self.load_mock = self.load_patcher.start()

        self.load_run_patcher = mock.patch(
            'Muon.GUI.Common.load_run_widget.load_run_model.load_utils.load_workspace_from_filename'
        )
        self.addCleanup(self.load_run_patcher.stop)
        self.load_run_mock = self.load_run_patcher.start()

        self.mock_workspace = self.create_fake_workspace(1)
        self.mock_loading_from_browse(self.mock_workspace,
                                      "C:\dir1\dir2\dir3\EMU0001234.nxs", 1234)
        file_utils.get_current_run_filename = mock.Mock(
            return_value="C:\dir1\dir2\dir3\EMU0001234.nxs")

        self.presenter.load_file_widget._view.warning_popup = mock.MagicMock()
        self.presenter.load_run_widget._view.warning_popup = mock.MagicMock()

        self.popup_patcher = mock.patch('Muon.GUI.Common.thread_model.warning')
        self.addCleanup(self.popup_patcher.stop)
        self.popup_mock = self.popup_patcher.start()

        def setGroupAndPairsToEmptyList(grouping_context):
            grouping_context._groups = []
            grouping_context._pairs = []

        self.group_context.reset_group_and_pairs_to_default = mock.MagicMock(
            side_effect=setGroupAndPairsToEmptyList(self.group_context))
    def setUp(self):
        self._qapp = mock_widget.mockQapp()
        # Store an empty widget to parent all the views, and ensure they are deleted correctly
        self.obj = QtGui.QWidget()

        setup_context_for_tests(self)
        self.data_context.instrument = 'EMU'

        self.view = LoadRunWidgetView(parent=self.obj)
        self.model = LoadRunWidgetModel(self.loaded_data, self.context)
        self.presenter = LoadRunWidgetPresenter(self.view, self.model)
        self.presenter.set_current_instrument("EMU")

        patcher = mock.patch(
            'Muon.GUI.Common.load_run_widget.load_run_model.load_utils')
        self.addCleanup(patcher.stop)
        self.load_utils_patcher = patcher.start()
        self.load_utils_patcher.exception_message_for_failed_files.return_value = ''
Esempio n. 8
0
    def setUp(self):
        self._qapp = mock_widget.mockQapp()
        # Store an empty widget to parent all the views, and ensure they are deleted correctly
        self.obj = QtGui.QWidget()

        self.data = MuonLoadData()
        self.context = MuonDataContext(self.data)
        self.context.instrument = 'EMU'
        self.load_file_view = BrowseFileWidgetView(self.obj)
        self.load_run_view = LoadRunWidgetView(self.obj)
        self.load_file_model = BrowseFileWidgetModel(self.data, self.context)
        self.load_run_model = LoadRunWidgetModel(self.data, self.context)

        self.presenter = LoadWidgetPresenter(
            LoadWidgetView(parent=self.obj,
                           load_file_view=self.load_file_view,
                           load_run_view=self.load_run_view),
            LoadWidgetModel(self.data, self.context))
        self.presenter.set_load_file_widget(
            BrowseFileWidgetPresenter(self.load_file_view,
                                      self.load_file_model))
        self.presenter.set_load_run_widget(
            LoadRunWidgetPresenter(self.load_run_view, self.load_run_model))

        self.filepath = FileFinder.findRuns('MUSR00022725.nxs')[0]

        self.load_patcher = mock.patch(
            'Muon.GUI.Common.load_file_widget.model.load_utils.load_workspace_from_filename'
        )
        self.addCleanup(self.load_patcher.stop)
        self.load_mock = self.load_patcher.start()

        self.load_run_patcher = mock.patch(
            'Muon.GUI.Common.load_run_widget.load_run_model.load_utils.load_workspace_from_filename'
        )
        self.addCleanup(self.load_run_patcher.stop)
        self.load_run_mock = self.load_run_patcher.start()

        self.mock_workspace = self.create_fake_workspace(1)
        self.mock_loading_from_browse(self.mock_workspace,
                                      "C:\dir1\dir2\dir3\EMU0001234.nxs", 1234)
        file_utils.get_current_run_filename = mock.Mock(
            return_value="C:\dir1\dir2\dir3\EMU0001234.nxs")

        self.presenter.load_file_widget._view.warning_popup = mock.MagicMock()
        self.presenter.load_run_widget._view.warning_popup = mock.MagicMock()

        self.popup_patcher = mock.patch('Muon.GUI.Common.thread_model.warning')
        self.addCleanup(self.popup_patcher.stop)
        self.popup_mock = self.popup_patcher.start()
Esempio n. 9
0
    def __init__(self, loaded_data, context, parent):
        # set up the views
        self.load_file_view = BrowseFileWidgetView(parent)
        self.load_run_view = LoadRunWidgetView(parent)
        self.load_widget_view = LoadWidgetView(parent=parent,
                                               load_file_view=self.load_file_view,
                                               load_run_view=self.load_run_view)
        self.load_widget = LoadWidgetPresenter(self.load_widget_view,
                                               LoadWidgetModel(loaded_data, context))

        self.file_widget = BrowseFileWidgetPresenter(self.load_file_view, BrowseFileWidgetModel(loaded_data, context))
        self.run_widget = LoadRunWidgetPresenter(self.load_run_view, LoadRunWidgetModel(loaded_data, context))

        self.load_widget.set_load_file_widget(self.file_widget)
        self.load_widget.set_load_run_widget(self.run_widget)

        self.load_widget.set_current_instrument(context.instrument)
    def setUp(self):
        self._qapp = mock_widget.mockQapp()
        # Store an empty widget to parent all the views, and ensure they are deleted correctly
        self.obj = QtGui.QWidget()

        setup_context_for_tests(self)

        self.view = LoadRunWidgetView(parent=self.obj)
        self.model = LoadRunWidgetModel(self.loaded_data, self.context)
        self.presenter = LoadRunWidgetPresenter(self.view, self.model)

        self.view.warning_popup = mock.Mock()
        self.presenter.set_current_instrument("EMU")

        patcher = mock.patch('Muon.GUI.Common.load_run_widget.load_run_model.load_utils')
        self.addCleanup(patcher.stop)
        self.load_utils_patcher = patcher.start()
        self.load_utils_patcher.exception_message_for_failed_files.return_value = ''

        self.load_single_run()
Esempio n. 11
0
    def __init__(self, loaded_data, context, parent):
        # set up the views
        self.load_file_view = BrowseFileWidgetView(parent)
        self.load_run_view = LoadRunWidgetView(parent)
        self.load_widget_view = LoadWidgetView(
            parent=parent,
            load_file_view=self.load_file_view,
            load_run_view=self.load_run_view)
        self.load_widget = LoadWidgetPresenter(
            self.load_widget_view, LoadWidgetModel(loaded_data, context))

        self.file_widget = BrowseFileWidgetPresenter(
            self.load_file_view, BrowseFileWidgetModel(loaded_data, context))
        self.run_widget = LoadRunWidgetPresenter(
            self.load_run_view, LoadRunWidgetModel(loaded_data, context))

        self.load_widget.set_load_file_widget(self.file_widget)
        self.load_widget.set_load_run_widget(self.run_widget)

        self.load_widget.set_current_instrument(
            context.data_context.instrument)

        context.update_view_from_model_notifier.add_subscriber(
            self.load_widget.update_view_from_model_observer)
Esempio n. 12
0
class LoadRunWidgetIncrementDecrementMultipleFileModeTest(GuiTest):
    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.instance().processEvents()

    def setUp(self):
        # Store an empty widget to parent all the views, and ensure they are deleted correctly
        self.obj = QWidget()

        setup_context_for_tests(self)

        self.data_context.instrument = 'EMU'

        self.view = LoadRunWidgetView(self.obj)
        self.model = LoadRunWidgetModel(self.loaded_data, self.context)
        self.presenter = LoadRunWidgetPresenter(self.view, self.model)

        self.view.warning_popup = mock.Mock()

        self.presenter.set_current_instrument("EMU")

        patcher = mock.patch('Muon.GUI.Common.load_run_widget.load_run_model.load_utils')
        self.addCleanup(patcher.stop)
        self.load_utils_patcher = patcher.start()
        self.load_utils_patcher.exception_message_for_failed_files.return_value = ''

    def tearDown(self):
        self.obj = None

    def load_runs(self, runs, filenames, workspaces):
        self.load_utils_patcher.load_workspace_from_filename = mock.Mock(
            side_effect=iter(zip(workspaces, runs, filenames, [False] * len(filenames))))
        run_string = ",".join([str(run) for run in runs])
        self.view.set_run_edit_text(run_string)
        self.presenter.handle_run_changed_by_user()
        self.wait_for_thread(self.presenter._load_thread)

    def assert_model_empty(self):
        self.assertEqual(self.model.loaded_filenames, [])
        self.assertEqual(self.model.loaded_workspaces, [])
        self.assertEqual(self.model.loaded_runs, [])

    def assert_view_empty(self):
        self.assertEqual(self.view.get_run_edit_text(), "")

    def load_failure(self):
        raise ValueError("Error text")

    # ------------------------------------------------------------------------------------------------------------------
    # TESTS : Test the increment/decrement run buttons in "multiple file" mode
    # ------------------------------------------------------------------------------------------------------------------

    @run_test_with_and_without_threading
    def test_that_providing_no_runs_leaves_model_and_view_empty(self):
        self.view.set_run_edit_text("")
        self.presenter.handle_run_changed_by_user()
        self.wait_for_thread(self.presenter._load_thread)

        self.assert_view_empty()
        self.assert_model_empty()

    @run_test_with_and_without_threading
    def test_that_increment_run_does_nothing_if_no_runs_loaded(self):
        self.presenter.handle_increment_run()
        self.wait_for_thread(self.presenter._load_thread)

        self.assert_view_empty()
        self.assert_model_empty()

    @run_test_with_and_without_threading
    def test_that_decrement_run_does_nothing_if_no_runs_loaded(self):
        self.presenter.handle_decrement_run()
        self.wait_for_thread(self.presenter._load_thread)

        self.assert_view_empty()
        self.assert_model_empty()

    @run_test_with_and_without_threading
    def test_that_decrement_run_decrements_the_upper_end_of_the_range_of_loaded_runs(self):
        self.load_runs([2, 3, 4], ["file2.nxs", "file3.nxs", "file4.nxs"], [[2], [3], [4]])
        self.load_utils_patcher.load_workspace_from_filename = mock.Mock(return_value=([1], 1, "file1.nxs", False))

        self.presenter.handle_decrement_run()
        self.wait_for_thread(self.presenter._load_thread)

        six.assertCountEqual(self, self.model.loaded_filenames, ["file1.nxs", "file2.nxs", "file3.nxs", "file4.nxs"])
        six.assertCountEqual(self, self.model.loaded_workspaces, [[1], [2], [3], [4]])
        six.assertCountEqual(self, self.model.loaded_runs, [[1], [2], [3], [4]])

        self.assertEqual(self.view.get_run_edit_text(), "1")

    @run_test_with_and_without_threading
    def test_that_increment_run_increments_the_lower_end_of_the_range_of_loaded_runs(self):
        self.load_runs([2, 3, 4], ["file2.nxs", "file3.nxs", "file4.nxs"], [[2], [3], [4]])
        self.load_utils_patcher.load_workspace_from_filename = mock.Mock(return_value=([5], 5, "file5.nxs", False))

        self.presenter.handle_increment_run()
        self.wait_for_thread(self.presenter._load_thread)

        six.assertCountEqual(self, self.model.loaded_filenames, ["file2.nxs", "file3.nxs", "file4.nxs", "file5.nxs"])
        six.assertCountEqual(self, self.model.loaded_workspaces, [[2], [3], [4], [5]])
        six.assertCountEqual(self, self.model.loaded_runs, [[2], [3], [4], [5]])

        self.assertEqual(self.view.get_run_edit_text(), "5")

    @run_test_with_and_without_threading
    def test_that_if_decrement_run_fails_the_data_are_returned_to_previous_state(self):

        self.load_runs([2, 3, 4], ["file2.nxs", "file3.nxs", "file4.nxs"], [[2], [3], [4]])
        self.load_utils_patcher.load_workspace_from_filename = mock.Mock(side_effect=self.load_failure)

        self.presenter.handle_decrement_run()
        self.wait_for_thread(self.presenter._load_thread)

        six.assertCountEqual(self, self.model.loaded_filenames, ["file2.nxs", "file3.nxs", "file4.nxs"])
        six.assertCountEqual(self, self.model.loaded_workspaces, [[2], [3], [4]])
        six.assertCountEqual(self, self.model.loaded_runs, [[2], [3], [4]])

        self.assertEqual(self.view.get_run_edit_text(), '2-4')

    @run_test_with_and_without_threading
    def test_that_if_increment_run_fails_the_data_are_returned_to_previous_state(self):

        self.load_runs([2, 3, 4], ["file2.nxs", "file3.nxs", "file4.nxs"], [[2], [3], [4]])
        self.load_utils_patcher.load_workspace_from_filename = mock.Mock(side_effect=self.load_failure)

        self.presenter.handle_increment_run()
        self.wait_for_thread(self.presenter._load_thread)

        six.assertCountEqual(self, self.model.loaded_filenames, ["file2.nxs", "file3.nxs", "file4.nxs"])
        six.assertCountEqual(self, self.model.loaded_workspaces, [[2], [3], [4]])
        six.assertCountEqual(self, self.model.loaded_runs, [[2], [3], [4]])

        self.assertEqual(self.view.get_run_edit_text(), '2-4')

    @run_test_with_and_without_threading
    def test_that_if_increment_run_fails_warning_message_is_displayed(self):
        self.load_runs([2, 3, 4], ["file2.nxs", "file3.nxs", "file4.nxs"], [[2], [3], [4]])
        self.load_utils_patcher.load_workspace_from_filename = mock.Mock(side_effect=self.load_failure)

        self.presenter.handle_increment_run()
        self.wait_for_thread(self.presenter._load_thread)

        self.assertEqual(self.view.warning_popup.call_count, 1)

    @run_test_with_and_without_threading
    def test_that_if_decrement_run_fails_warning_message_is_displayed(self):
        self.load_runs([2, 3, 4], ["file2.nxs", "file3.nxs", "file4.nxs"], [[2], [3], [4]])
        self.load_utils_patcher.load_workspace_from_filename = mock.Mock(side_effect=self.load_failure)

        self.presenter.handle_decrement_run()
        self.wait_for_thread(self.presenter._load_thread)

        self.assertEqual(self.view.warning_popup.call_count, 1)
class LoadRunWidgetLoadCurrentRunTest(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 load_failure(self):
        raise ValueError("Error text")

    def wait_for_thread(self, thread_model):
        if thread_model:
            thread_model._thread.wait()
            self._qapp.processEvents()

    def create_fake_workspace(self):
        return {'MainFieldDirection': 'transverse'}

    def setUp(self):
        self._qapp = mock_widget.mockQapp()
        # Store an empty widget to parent all the views, and ensure they are deleted correctly
        self.obj = QtGui.QWidget()

        setup_context_for_tests(self)

        self.data_context.instrument = 'EMU'
        self.view = LoadRunWidgetView(parent=self.obj)
        self.model = LoadRunWidgetModel(self.loaded_data, self.context)
        self.presenter = LoadRunWidgetPresenter(self.view, self.model)

        self.model.load_workspace_from_filename = mock.Mock(return_value=([1, 2, 3], "currentRun.nxs", 1234))
        self.view.warning_popup = mock.Mock()
        self.view.disable_load_buttons = mock.Mock()
        self.view.enable_load_buttons = mock.Mock()

        self.presenter.set_current_instrument("EMU")

        fileUtils.get_current_run_filename = mock.Mock(return_value="EMU0001234.nxs")

        patcher = mock.patch('Muon.GUI.Common.load_run_widget.load_run_model.load_utils')
        self.addCleanup(patcher.stop)
        self.load_utils_patcher = patcher.start()
        self.load_utils_patcher.exception_message_for_failed_files.return_value = ''

    def tearDown(self):
        self.obj = None

    # ------------------------------------------------------------------------------------------------------------------
    # TESTS
    # ------------------------------------------------------------------------------------------------------------------

    @run_test_with_and_without_threading
    def test_load_current_run_loads_run_into_model(self):
        workspace = self.create_fake_workspace()
        self.load_utils_patcher.load_workspace_from_filename = mock.Mock(return_value=(workspace, 1234, "currentRun.nxs"))
        self.presenter.handle_load_current_run()
        self.wait_for_thread(self.presenter._load_thread)

        self.assertEqual(self.presenter.filenames, ["currentRun.nxs"])
        self.assertEqual(self.presenter.runs, [[1234]])
        self.assertEqual(self.presenter.workspaces, [workspace])

        self.assertEqual(self.model._data_context.current_runs, [[1234]])

    @run_test_with_and_without_threading
    def test_load_current_run_correctly_displays_run_if_load_successful(self):
        workspace = self.create_fake_workspace()
        self.load_utils_patcher.load_workspace_from_filename = mock.Mock(return_value=(workspace, 1234, "1234.nxs"))
        self.presenter.handle_load_current_run()
        self.wait_for_thread(self.presenter._load_thread)

        self.assertEqual(self.view.get_run_edit_text(), '1234')

    def test_load_current_run_displays_error_message_if_fails_to_load(self):
        self.load_utils_patcher.load_workspace_from_filename = mock.Mock(side_effect=self.load_failure)

        self.presenter.handle_load_current_run()
        self.wait_for_thread(self.presenter._load_thread)

        self.assertEqual(self.view.warning_popup.call_count, 1)

    @run_test_with_and_without_threading
    def test_load_current_run_reverts_to_previous_data_if_fails_to_load(self):
        # set up previous data
        workspace = self.create_fake_workspace()
        self.load_utils_patcher.load_workspace_from_filename = mock.Mock(return_value=(workspace, 1234, "1234.nxs"))
        self.view.set_run_edit_text("1234")
        self.presenter.handle_run_changed_by_user()
        self.wait_for_thread(self.presenter._load_thread)

        self.load_utils_patcher.load_workspace_from_filename = mock.Mock(side_effect=self.load_failure)
        self.presenter.handle_load_current_run()
        self.wait_for_thread(self.presenter._load_thread)

        self.assertEqual(self.presenter.filenames, ["1234.nxs"])
        self.assertEqual(self.presenter.runs, [[1234]])
        self.assertEqual(self.presenter.workspaces, [workspace])

    @run_test_with_and_without_threading
    def test_load_current_run_clears_previous_data_if_load_succeeds(self):
        # set up previous data
        workspace = self.create_fake_workspace()
        self.load_utils_patcher.return_value = (workspace, "1234.nxs", 1234)
        self.view.set_run_edit_text("1234")
        self.presenter.handle_run_changed_by_user()
        self.wait_for_thread(self.presenter._load_thread)

        self.load_utils_patcher.load_workspace_from_filename = mock.Mock(return_value=(workspace, 9999, "9999.nxs"))
        self.presenter.handle_load_current_run()
        self.wait_for_thread(self.presenter._load_thread)

        self.assertEqual(self.view.get_run_edit_text(), "9999")
        self.assertEqual(self.presenter.filenames, ["9999.nxs"])
        self.assertEqual(self.presenter.runs, [[9999]])
        self.assertEqual(self.presenter.workspaces, [workspace])

    @run_test_with_and_without_threading
    def test_load_current_run_displays_error_if_incrementing_past_current_run(self):
        # set up current run
        workspace = self.create_fake_workspace()
        self.load_utils_patcher.load_workspace_from_filename = mock.Mock(return_value=(workspace, 1234, "1234.nxs"))
        self.view.set_run_edit_text("1234")
        self.presenter.handle_load_current_run()
        self.wait_for_thread(self.presenter._load_thread)

        self.presenter.handle_increment_run()
        self.wait_for_thread(self.presenter._load_thread)

        self.assertEqual(self.view.warning_popup.call_count, 1)
class LoadRunWidgetLoadCurrentRunTest(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

    @staticmethod
    def load_failure(self):
        raise ValueError("Error text")

    def wait_for_thread(self, thread_model):
        if thread_model:
            thread_model._thread.wait()
            QApplication.sendPostedEvents()

    def create_fake_workspace(self):
        return {'MainFieldDirection': 'transverse'}

    def create_mock_signal_handler(self):
        self.thread_model = ThreadModel(self.model)
        self.thread_model_worker = ThreadModelWorker(self.thread_model)
        self.thread_model_worker.signals.error = mock.Mock()
        self.signal_handler = MockSignalHandler()
        self.thread_model_worker.signals.error.connect(
            self.signal_handler.signalReceived())

    def setUp(self):
        # Store an empty widget to parent all the views, and ensure they are deleted correctly
        self.obj = QWidget()

        setup_context_for_tests(self)

        self.data_context.instrument = 'EMU'
        self.view = LoadRunWidgetView(parent=self.obj)
        self.model = LoadRunWidgetModel(self.loaded_data, self.context)
        self.presenter = LoadRunWidgetPresenter(self.view, self.model)

        self.model.load_workspace_from_filename = mock.Mock(
            return_value=([1, 2, 3], "currentRun.nxs", 1234, False))
        self.view.warning_popup = mock.Mock()
        self.view.disable_load_buttons = mock.Mock()
        self.view.enable_load_buttons = mock.Mock()

        self.presenter.set_current_instrument("EMU")

        fileUtils.get_current_run_filename = mock.Mock(
            return_value="EMU0001234.nxs")

        patcher = mock.patch(
            'Muon.GUI.Common.load_run_widget.load_run_model.load_utils')
        self.addCleanup(patcher.stop)
        self.load_utils_patcher = patcher.start()
        self.load_utils_patcher.exception_message_for_failed_files.return_value = ''

    def tearDown(self):
        self.obj = None

    # ------------------------------------------------------------------------------------------------------------------
    # TESTS
    # ------------------------------------------------------------------------------------------------------------------

    @run_test_with_and_without_threading
    def test_load_current_run_loads_run_into_model(self):
        workspace = self.create_fake_workspace()
        self.load_utils_patcher.load_workspace_from_filename = mock.Mock(
            return_value=(workspace, 1234, "currentRun.nxs", False))
        self.presenter.handle_load_current_run()
        self.wait_for_thread(self.presenter._load_thread)

        self.assertEqual(self.presenter.filenames, ["currentRun.nxs"])
        self.assertEqual(self.presenter.runs, [[1234]])
        self.assertEqual(self.presenter.workspaces, [workspace])

        self.assertEqual(self.model._data_context.current_runs, [[1234]])

    @run_test_with_and_without_threading
    def test_load_current_run_correctly_displays_run_if_load_successful(self):
        workspace = self.create_fake_workspace()
        self.load_utils_patcher.load_workspace_from_filename = mock.Mock(
            return_value=(workspace, 1234, "1234.nxs", False))
        self.presenter.handle_load_current_run()
        self.wait_for_thread(self.presenter._load_thread)

        self.assertEqual(self.view.get_run_edit_text(), '1234')

    def test_load_current_run_emits_error_signal_if_fails_to_load(self):
        self.create_mock_signal_handler()
        self.load_utils_patcher.load_workspace_from_filename = mock.Mock(
            side_effect=self.load_failure)

        self.presenter.handle_load_current_run()
        self.wait_for_thread(self.presenter._load_thread)

        self.assertEqual(self.signal_handler.call_count, 1)

    @run_test_with_and_without_threading
    # the following patch is required because the warning popup originates from thread_model in this case
    @patch(
        "Muon.GUI.Common.load_run_widget.load_run_presenter.thread_model.warning"
    )
    def test_load_current_run_reverts_to_previous_data_if_fails_to_load(
            self, warning_mock):
        # set up previous data
        workspace = self.create_fake_workspace()
        self.load_utils_patcher.load_workspace_from_filename = mock.Mock(
            return_value=(workspace, 1234, "1234.nxs", False))
        self.view.set_run_edit_text("1234")
        self.presenter.handle_run_changed_by_user()
        self.wait_for_thread(self.presenter._load_thread)

        self.load_utils_patcher.load_workspace_from_filename = mock.Mock(
            side_effect=self.load_failure)
        self.presenter.handle_load_current_run()
        self.wait_for_thread(self.presenter._load_thread)

        self.assertEqual(self.presenter.filenames, ["1234.nxs"])
        self.assertEqual(self.presenter.runs, [[1234]])
        self.assertEqual(self.presenter.workspaces, [workspace])

    @run_test_with_and_without_threading
    def test_load_current_run_clears_previous_data_if_load_succeeds(self):
        # set up previous data
        workspace = self.create_fake_workspace()
        self.load_utils_patcher.return_value = (workspace, "1234.nxs", 1234)
        self.view.set_run_edit_text("1234")
        self.presenter.handle_run_changed_by_user()
        self.wait_for_thread(self.presenter._load_thread)

        self.load_utils_patcher.load_workspace_from_filename = mock.Mock(
            return_value=(workspace, 9999, "9999.nxs", False))
        self.presenter.handle_load_current_run()
        self.wait_for_thread(self.presenter._load_thread)

        self.assertEqual(self.view.get_run_edit_text(), "9999")
        self.assertEqual(self.presenter.filenames, ["9999.nxs"])
        self.assertEqual(self.presenter.runs, [[9999]])
        self.assertEqual(self.presenter.workspaces, [workspace])

    @run_test_with_and_without_threading
    # the following patch is required because the warning popup also originates from thread_model in this case
    @patch(
        "Muon.GUI.Common.load_run_widget.load_run_presenter.thread_model.warning"
    )
    def test_load_current_run_emits_error_signal_if_incrementing_past_current_run(
            self, warning_mock):
        self.create_mock_signal_handler()

        # set up current run
        workspace = self.create_fake_workspace()
        self.load_utils_patcher.load_workspace_from_filename = mock.Mock(
            return_value=(workspace, 1234, "1234.nxs", False))
        self.view.set_run_edit_text("1234")
        self.presenter.handle_load_current_run()
        self.wait_for_thread(self.presenter._load_thread)

        self.presenter.handle_increment_run()
        self.wait_for_thread(self.presenter._load_thread)

        self.assertEqual(self.signal_handler.call_count, 1)
class LoadRunWidgetIncrementDecrementMultipleFileModeTest(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()
            self._qapp.processEvents()

    def setUp(self):
        self._qapp = mock_widget.mockQapp()
        # Store an empty widget to parent all the views, and ensure they are deleted correctly
        self.obj = QtGui.QWidget()

        setup_context_for_tests(self)

        self.data_context.instrument = 'EMU'

        self.view = LoadRunWidgetView(self.obj)
        self.model = LoadRunWidgetModel(self.loaded_data, self.context)
        self.presenter = LoadRunWidgetPresenter(self.view, self.model)

        self.view.warning_popup = mock.Mock()

        self.presenter.set_current_instrument("EMU")

        patcher = mock.patch('Muon.GUI.Common.load_run_widget.load_run_model.load_utils')
        self.addCleanup(patcher.stop)
        self.load_utils_patcher = patcher.start()
        self.load_utils_patcher.exception_message_for_failed_files.return_value = ''

    def tearDown(self):
        self.obj = None

    def load_runs(self, runs, filenames, workspaces):
        self.load_utils_patcher.load_workspace_from_filename = mock.Mock(
            side_effect=iter(zip(workspaces, runs, filenames)))
        run_string = ",".join([str(run) for run in runs])
        self.view.set_run_edit_text(run_string)
        self.presenter.handle_run_changed_by_user()
        self.wait_for_thread(self.presenter._load_thread)

    def assert_model_empty(self):
        self.assertEqual(self.model.loaded_filenames, [])
        self.assertEqual(self.model.loaded_workspaces, [])
        self.assertEqual(self.model.loaded_runs, [])

    def assert_view_empty(self):
        self.assertEqual(self.view.get_run_edit_text(), "")

    def load_failure(self):
        raise ValueError("Error text")

    # ------------------------------------------------------------------------------------------------------------------
    # TESTS : Test the increment/decrement run buttons in "multiple file" mode
    # ------------------------------------------------------------------------------------------------------------------

    @run_test_with_and_without_threading
    def test_that_providing_no_runs_leaves_model_and_view_empty(self):
        self.view.set_run_edit_text("")
        self.presenter.handle_run_changed_by_user()
        self.wait_for_thread(self.presenter._load_thread)

        self.assert_view_empty()
        self.assert_model_empty()

    @run_test_with_and_without_threading
    def test_that_increment_run_does_nothing_if_no_runs_loaded(self):
        self.presenter.handle_increment_run()
        self.wait_for_thread(self.presenter._load_thread)

        self.assert_view_empty()
        self.assert_model_empty()

    @run_test_with_and_without_threading
    def test_that_decrement_run_does_nothing_if_no_runs_loaded(self):
        self.presenter.handle_decrement_run()
        self.wait_for_thread(self.presenter._load_thread)

        self.assert_view_empty()
        self.assert_model_empty()

    @run_test_with_and_without_threading
    def test_that_decrement_run_decrements_the_upper_end_of_the_range_of_loaded_runs(self):
        self.load_runs([2, 3, 4], ["file2.nxs", "file3.nxs", "file4.nxs"], [[2], [3], [4]])
        self.load_utils_patcher.load_workspace_from_filename = mock.Mock(return_value=([1], 1, "file1.nxs"))

        self.presenter.handle_decrement_run()
        self.wait_for_thread(self.presenter._load_thread)

        six.assertCountEqual(self, self.model.loaded_filenames, ["file1.nxs", "file2.nxs", "file3.nxs", "file4.nxs"])
        six.assertCountEqual(self, self.model.loaded_workspaces, [[1], [2], [3], [4]])
        six.assertCountEqual(self, self.model.loaded_runs, [[1], [2], [3], [4]])

        self.assertEqual(self.view.get_run_edit_text(), "1")

    @run_test_with_and_without_threading
    def test_that_increment_run_increments_the_lower_end_of_the_range_of_loaded_runs(self):
        self.load_runs([2, 3, 4], ["file2.nxs", "file3.nxs", "file4.nxs"], [[2], [3], [4]])
        self.load_utils_patcher.load_workspace_from_filename = mock.Mock(return_value=([5], 5, "file5.nxs"))

        self.presenter.handle_increment_run()
        self.wait_for_thread(self.presenter._load_thread)

        six.assertCountEqual(self, self.model.loaded_filenames, ["file2.nxs", "file3.nxs", "file4.nxs", "file5.nxs"])
        six.assertCountEqual(self, self.model.loaded_workspaces, [[2], [3], [4], [5]])
        six.assertCountEqual(self, self.model.loaded_runs, [[2], [3], [4], [5]])

        self.assertEqual(self.view.get_run_edit_text(), "5")

    @run_test_with_and_without_threading
    def test_that_if_decrement_run_fails_the_data_are_returned_to_previous_state(self):

        self.load_runs([2, 3, 4], ["file2.nxs", "file3.nxs", "file4.nxs"], [[2], [3], [4]])
        self.load_utils_patcher.load_workspace_from_filename = mock.Mock(side_effect=self.load_failure)

        self.presenter.handle_decrement_run()
        self.wait_for_thread(self.presenter._load_thread)

        six.assertCountEqual(self, self.model.loaded_filenames, ["file2.nxs", "file3.nxs", "file4.nxs"])
        six.assertCountEqual(self, self.model.loaded_workspaces, [[2], [3], [4]])
        six.assertCountEqual(self, self.model.loaded_runs, [[2], [3], [4]])

        self.assertEqual(self.view.get_run_edit_text(), "")

    @run_test_with_and_without_threading
    def test_that_if_increment_run_fails_the_data_are_returned_to_previous_state(self):

        self.load_runs([2, 3, 4], ["file2.nxs", "file3.nxs", "file4.nxs"], [[2], [3], [4]])
        self.load_utils_patcher.load_workspace_from_filename = mock.Mock(side_effect=self.load_failure)

        self.presenter.handle_increment_run()
        self.wait_for_thread(self.presenter._load_thread)

        six.assertCountEqual(self, self.model.loaded_filenames, ["file2.nxs", "file3.nxs", "file4.nxs"])
        six.assertCountEqual(self, self.model.loaded_workspaces, [[2], [3], [4]])
        six.assertCountEqual(self, self.model.loaded_runs, [[2], [3], [4]])

        self.assertEqual(self.view.get_run_edit_text(), "")

    @run_test_with_and_without_threading
    def test_that_if_increment_run_fails_warning_message_is_displayed(self):
        self.load_runs([2, 3, 4], ["file2.nxs", "file3.nxs", "file4.nxs"], [[2], [3], [4]])
        self.load_utils_patcher.load_workspace_from_filename = mock.Mock(side_effect=self.load_failure)

        self.presenter.handle_increment_run()
        self.wait_for_thread(self.presenter._load_thread)

        self.assertEqual(self.view.warning_popup.call_count, 1)

    @run_test_with_and_without_threading
    def test_that_if_decrement_run_fails_warning_message_is_displayed(self):
        self.load_runs([2, 3, 4], ["file2.nxs", "file3.nxs", "file4.nxs"], [[2], [3], [4]])
        self.load_utils_patcher.load_workspace_from_filename = mock.Mock(side_effect=self.load_failure)

        self.presenter.handle_decrement_run()
        self.wait_for_thread(self.presenter._load_thread)

        self.assertEqual(self.view.warning_popup.call_count, 1)
class LoadRunWidgetLoadCurrentRunTest(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 load_failure(self):
        raise ValueError("Error text")

    def wait_for_thread(self, thread_model):
        if thread_model:
            thread_model._thread.wait()
            self._qapp.processEvents()

    def setUp(self):
        self._qapp = mock_widget.mockQapp()
        # Store an empty widget to parent all the views, and ensure they are deleted correctly
        self.obj = QtGui.QWidget()

        self.context = MuonDataContext()
        self.context.instrument = 'EMU'
        self.data = MuonLoadData()
        self.view = LoadRunWidgetView(parent=self.obj)
        self.model = LoadRunWidgetModel(self.data, self.context)
        self.presenter = LoadRunWidgetPresenter(self.view, self.model)

        self.model.load_workspace_from_filename = mock.Mock(return_value=([1, 2, 3], "currentRun.nxs", 1234))
        self.view.warning_popup = mock.Mock()
        self.view.disable_load_buttons = mock.Mock()
        self.view.enable_load_buttons = mock.Mock()

        self.presenter.set_current_instrument("EMU")

        fileUtils.get_current_run_filename = mock.Mock(return_value="EMU0001234.nxs")

        patcher = mock.patch('Muon.GUI.Common.load_run_widget.load_run_model.load_utils')
        self.addCleanup(patcher.stop)
        self.load_utils_patcher = patcher.start()
        self.load_utils_patcher.exception_message_for_failed_files.return_value = ''

    def tearDown(self):
        self.obj = None

    # ------------------------------------------------------------------------------------------------------------------
    # TESTS
    # ------------------------------------------------------------------------------------------------------------------

    @run_test_with_and_without_threading
    def test_load_current_run_loads_run_into_model(self):
        self.load_utils_patcher.load_workspace_from_filename = mock.Mock(return_value=([1, 2, 3], 1234, "currentRun.nxs"))
        self.presenter.handle_load_current_run()
        self.wait_for_thread(self.presenter._load_thread)

        self.assertEqual(self.presenter.filenames, ["currentRun.nxs"])
        self.assertEqual(self.presenter.runs, [[1234]])
        self.assertEqual(self.presenter.workspaces, [[1, 2, 3]])

        self.assertEqual(self.model._context.current_runs, [[1234]])

    @run_test_with_and_without_threading
    def test_load_current_run_correctly_displays_run_if_load_successful(self):
        self.load_utils_patcher.load_workspace_from_filename = mock.Mock(return_value=([1], 1234, "1234.nxs"))
        self.presenter.handle_load_current_run()
        self.wait_for_thread(self.presenter._load_thread)

        self.assertEqual(self.view.get_run_edit_text(), '1234')

    def test_load_current_run_displays_error_message_if_fails_to_load(self):
        self.load_utils_patcher.load_workspace_from_filename = mock.Mock(side_effect=self.load_failure)

        self.presenter.handle_load_current_run()
        self.wait_for_thread(self.presenter._load_thread)

        self.assertEqual(self.view.warning_popup.call_count, 1)

    @run_test_with_and_without_threading
    def test_load_current_run_reverts_to_previous_data_if_fails_to_load(self):
        # set up previous data
        self.load_utils_patcher.load_workspace_from_filename = mock.Mock(return_value=([1], 1234, "1234.nxs"))
        self.view.set_run_edit_text("1234")
        self.presenter.handle_run_changed_by_user()
        self.wait_for_thread(self.presenter._load_thread)

        self.load_utils_patcher.load_workspace_from_filename = mock.Mock(side_effect=self.load_failure)
        self.presenter.handle_load_current_run()
        self.wait_for_thread(self.presenter._load_thread)

        self.assertEqual(self.presenter.filenames, ["1234.nxs"])
        self.assertEqual(self.presenter.runs, [[1234]])
        self.assertEqual(self.presenter.workspaces, [[1]])

    @run_test_with_and_without_threading
    def test_load_current_run_clears_previous_data_if_load_succeeds(self):
        # set up previous data
        self.load_utils_patcher.return_value = ([1], "1234.nxs", 1234)
        self.view.set_run_edit_text("1234")
        self.presenter.handle_run_changed_by_user()
        self.wait_for_thread(self.presenter._load_thread)

        self.load_utils_patcher.load_workspace_from_filename = mock.Mock(return_value=([2], 9999, "9999.nxs"))
        self.presenter.handle_load_current_run()
        self.wait_for_thread(self.presenter._load_thread)

        self.assertEqual(self.view.get_run_edit_text(), "9999")
        self.assertEqual(self.presenter.filenames, ["9999.nxs"])
        self.assertEqual(self.presenter.runs, [[9999]])
        self.assertEqual(self.presenter.workspaces, [[2]])

    @run_test_with_and_without_threading
    def test_load_current_run_displays_error_if_incrementing_past_current_run(self):
        # set up current run
        self.load_utils_patcher.load_workspace_from_filename = mock.Mock(return_value=([1], 1234, "1234.nxs"))
        self.view.set_run_edit_text("1234")
        self.presenter.handle_load_current_run()
        self.wait_for_thread(self.presenter._load_thread)

        self.presenter.handle_increment_run()
        self.wait_for_thread(self.presenter._load_thread)

        self.assertEqual(self.view.warning_popup.call_count, 1)
class LoadRunWidgetIncrementDecrementSingleFileModeTest(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.instance().processEvents()

    def setUp(self):
        # Store an empty widget to parent all the views, and ensure they are deleted correctly
        self.obj = QWidget()

        setup_context_for_tests(self)

        self.view = LoadRunWidgetView(parent=self.obj)
        self.model = LoadRunWidgetModel(self.loaded_data, self.context)
        self.presenter = LoadRunWidgetPresenter(self.view, self.model)

        self.view.warning_popup = mock.Mock()
        self.presenter.set_current_instrument("EMU")

        patcher = mock.patch(
            'Muon.GUI.Common.load_run_widget.load_run_model.load_utils')
        self.addCleanup(patcher.stop)
        self.load_utils_patcher = patcher.start()
        self.load_utils_patcher.exception_message_for_failed_files.return_value = ''

        file_finder_patcher = mock.patch(
            'Muon.GUI.Common.load_run_widget.load_run_presenter.FileFinder')
        self.addCleanup(file_finder_patcher.stop)
        file_finder_patcher.start()

        self.load_single_run()

    def tearDown(self):
        self.obj = None

    def load_single_run(self):
        self._loaded_run = 1234
        self._loaded_filename = "EMU00001234.nxs"
        self._loaded_workspace = {'MainFieldDirection': 'transverse'}

        self.load_utils_patcher.load_workspace_from_filename = mock.Mock(
            return_value=(self._loaded_workspace, self._loaded_run,
                          self._loaded_filename, False))
        self.view.set_run_edit_text(str(self._loaded_run))
        self.presenter.handle_run_changed_by_user()
        self.wait_for_thread(self.presenter._load_thread)

    def assert_model_has_not_changed(self):
        self.assertEqual(self.model.loaded_workspaces,
                         [self._loaded_workspace])
        self.assertEqual(self.model.loaded_runs, [[self._loaded_run]])
        self.assertEqual(self.model.loaded_filenames, [self._loaded_filename])

    def assert_view_has_not_changed(self):
        self.assertEqual(self.view.get_run_edit_text(), str(self._loaded_run))

    def load_failure(self):
        raise ValueError("Error text")

    def mock_model_to_throw(self):
        self.model.load_workspace_from_filename = mock.Mock(
            side_effect=self.load_failure)

    # ------------------------------------------------------------------------------------------------------------------
    # TESTS : Test the increment/decrement buttons in single file mode (can only load one run at a time)
    # ------------------------------------------------------------------------------------------------------------------

    @run_test_with_and_without_threading
    def test_that_decrement_run_attempts_to_load_the_correct_run(self):
        new_filename = "EMU00001233.nxs"
        load_call_count = self.load_utils_patcher.load_workspace_from_filename.call_count

        self.presenter.handle_decrement_run()
        self.wait_for_thread(self.presenter._load_thread)

        self.assertEqual(
            self.load_utils_patcher.load_workspace_from_filename.call_count,
            load_call_count + 1)
        filename = self.load_utils_patcher.load_workspace_from_filename.call_args[
            0][0]
        self.assertEqual(os.path.basename(filename), new_filename)

    @run_test_with_and_without_threading
    def test_that_increment_run_attempts_to_load_the_correct_run(self):
        new_filename = "EMU00001235.nxs"
        load_call_count = self.load_utils_patcher.load_workspace_from_filename.call_count

        self.presenter.handle_increment_run()
        self.wait_for_thread(self.presenter._load_thread)

        self.assertEqual(
            self.load_utils_patcher.load_workspace_from_filename.call_count,
            load_call_count + 1)
        filename = self.load_utils_patcher.load_workspace_from_filename.call_args[
            0][0]
        self.assertEqual(os.path.basename(filename), new_filename)

    @run_test_with_and_without_threading
    def test_that_decrement_run_loads_the_data_correctly(self):
        new_run = self._loaded_run - 1
        new_filename = "EMU00001233.nxs"
        self.load_utils_patcher.load_workspace_from_filename = mock.Mock(
            return_value=({
                'MainFieldDirection': 'transverse'
            }, new_run, new_filename, False))

        self.presenter.handle_decrement_run()
        self.wait_for_thread(self.presenter._load_thread)

        self.assertEqual(self.presenter.filenames,
                         [self._loaded_filename, new_filename])
        self.assertEqual(self.presenter.runs, [[self._loaded_run], [new_run]])
        self.assertEqual(
            self.presenter.workspaces,
            [self._loaded_workspace, {
                'MainFieldDirection': 'transverse'
            }])

        self.assertEqual(self.view.get_run_edit_text(), '1233')

    @run_test_with_and_without_threading
    def test_that_increment_run_loads_the_data_correctly(self):
        new_run = self._loaded_run + 1
        new_filename = "EMU00001235.nxs"
        self.load_utils_patcher.load_workspace_from_filename = mock.Mock(
            return_value=({
                'MainFieldDirection': 'transverse'
            }, new_run, new_filename, False))

        self.presenter.handle_increment_run()
        self.wait_for_thread(self.presenter._load_thread)

        self.assertEqual(self.presenter.filenames,
                         [self._loaded_filename, new_filename])
        self.assertEqual(self.presenter.runs, [[self._loaded_run], [new_run]])
        self.assertEqual(
            self.presenter.workspaces,
            [self._loaded_workspace, {
                'MainFieldDirection': 'transverse'
            }])

        self.assertEqual(self.view.get_run_edit_text(), '1235')

    @run_test_with_and_without_threading
    def test_that_if_decrement_run_fails_the_data_are_returned_to_previous_state(
            self):
        self.load_utils_patcher.load_workspace_from_filename = mock.Mock(
            side_effect=self.load_failure)

        self.presenter.handle_decrement_run()
        self.wait_for_thread(self.presenter._load_thread)

        self.assert_model_has_not_changed()
        self.assertEqual(self.view.get_run_edit_text(), '1234')

    @run_test_with_and_without_threading
    def test_that_if_increment_run_fails_the_data_are_returned_to_previous_state(
            self):
        self.load_utils_patcher.load_workspace_from_filename = mock.Mock(
            side_effect=self.load_failure)

        self.presenter.handle_increment_run()
        self.wait_for_thread(self.presenter._load_thread)

        self.assert_model_has_not_changed()
        self.assertEqual(self.view.get_run_edit_text(), '1234')

    @run_test_with_and_without_threading
    def test_that_if_decrement_run_fails_warning_message_is_displayed(self):
        self.load_utils_patcher.load_workspace_from_filename = mock.Mock(
            side_effect=self.load_failure)

        self.presenter.handle_decrement_run()
        self.wait_for_thread(self.presenter._load_thread)

        self.assertEqual(self.view.warning_popup.call_count, 1)

    @run_test_with_and_without_threading
    def test_that_if_increment_run_fails_warning_message_is_displayed(self):
        self.load_utils_patcher.load_workspace_from_filename = mock.Mock(
            side_effect=self.load_failure)

        self.presenter.handle_increment_run()
        self.wait_for_thread(self.presenter._load_thread)

        self.assertEqual(self.view.warning_popup.call_count, 1)
class LoadRunWidgetPresenterTest(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.instance().processEvents()

    def setUp(self):
        # Store an empty widget to parent all the views, and ensure they are deleted correctly
        self.obj = QWidget()

        setup_context_for_tests(self)
        self.data_context.instrument = 'EMU'

        self.view = LoadRunWidgetView(parent=self.obj)
        self.model = LoadRunWidgetModel(self.loaded_data, self.context)
        self.presenter = LoadRunWidgetPresenter(self.view, self.model)
        self.presenter.set_current_instrument("EMU")

        patcher = mock.patch('Muon.GUI.Common.load_run_widget.load_run_model.load_utils')
        self.addCleanup(patcher.stop)
        self.load_utils_patcher = patcher.start()
        self.load_utils_patcher.exception_message_for_failed_files.return_value = ''

    def tearDown(self):
        self.obj = None

    def mock_loading_via_user_input_run(self, workspace, filename, run):
        self.load_utils_patcher.load_workspace_from_filename = mock.Mock(
            return_value=(workspace, run, filename, False))
        self.view.set_run_edit_text("1234")

    # ------------------------------------------------------------------------------------------------------------------
    # TESTS
    # ------------------------------------------------------------------------------------------------------------------

    @run_test_with_and_without_threading
    def test_model_and_view_initialized_to_contain_no_data(self):
        self.assertEqual(self.presenter.filenames, [])
        self.assertEqual(self.presenter.runs, [])
        self.assertEqual(self.presenter.workspaces, [])

        self.assertEqual(self.view.get_run_edit_text(), "")

    @run_test_with_and_without_threading
    def test_user_can_enter_a_run_and_load_it_in_single_file_mode(self):
        self.mock_loading_via_user_input_run([1, 2, 3], "EMU00001234.nxs", 1234)

        self.presenter.handle_run_changed_by_user()
        self.wait_for_thread(self.presenter._load_thread)

        self.assertEqual(self.presenter.filenames, ["EMU00001234.nxs"])
        self.assertEqual(self.presenter.runs, [[1234]])
        self.assertEqual(self.presenter.workspaces, [[1, 2, 3]])

    @run_test_with_and_without_threading
    def test_warning_message_displayed_if_user_enters_multiple_files_in_single_file_mode(self):
        self.view.warning_popup = mock.Mock()
        self.view.set_run_edit_text("1234,1235,1236")

        self.presenter.handle_run_changed_by_user()
        self.wait_for_thread(self.presenter._load_thread)

        self.assertEqual(self.view.warning_popup.call_count, 1)
class LoadRunWidgetIncrementDecrementSingleFileModeTest(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()
            self._qapp.processEvents()

    def setUp(self):
        self._qapp = mock_widget.mockQapp()
        # Store an empty widget to parent all the views, and ensure they are deleted correctly
        self.obj = QtGui.QWidget()

        setup_context_for_tests(self)

        self.view = LoadRunWidgetView(parent=self.obj)
        self.model = LoadRunWidgetModel(self.loaded_data, self.context)
        self.presenter = LoadRunWidgetPresenter(self.view, self.model)

        self.view.warning_popup = mock.Mock()
        self.presenter.set_current_instrument("EMU")

        patcher = mock.patch('Muon.GUI.Common.load_run_widget.load_run_model.load_utils')
        self.addCleanup(patcher.stop)
        self.load_utils_patcher = patcher.start()
        self.load_utils_patcher.exception_message_for_failed_files.return_value = ''

        self.load_single_run()

    def tearDown(self):
        self.obj = None

    def load_single_run(self):
        self._loaded_run = 1234
        self._loaded_filename = "EMU00001234.nxs"
        self._loaded_workspace = {'MainFieldDirection': 'transverse'}

        self.load_utils_patcher.load_workspace_from_filename = mock.Mock(
            return_value=(self._loaded_workspace, self._loaded_run, self._loaded_filename))
        self.view.set_run_edit_text(str(self._loaded_run))
        self.presenter.handle_run_changed_by_user()
        self.wait_for_thread(self.presenter._load_thread)

    def assert_model_has_not_changed(self):
        self.assertEqual(self.model.loaded_workspaces, [self._loaded_workspace])
        self.assertEqual(self.model.loaded_runs, [[self._loaded_run]])
        self.assertEqual(self.model.loaded_filenames, [self._loaded_filename])

    def assert_view_has_not_changed(self):
        self.assertEqual(self.view.get_run_edit_text(), str(self._loaded_run))

    def load_failure(self):
        raise ValueError("Error text")

    def mock_model_to_throw(self):
        self.model.load_workspace_from_filename = mock.Mock(side_effect=self.load_failure)

    # ------------------------------------------------------------------------------------------------------------------
    # TESTS : Test the increment/decrement buttons in single file mode (can only load one run at a time)
    # ------------------------------------------------------------------------------------------------------------------

    @run_test_with_and_without_threading
    def test_that_decrement_run_attempts_to_load_the_correct_run(self):
        new_filename = "EMU00001233.nxs"
        load_call_count = self.load_utils_patcher.load_workspace_from_filename.call_count

        self.presenter.handle_decrement_run()
        self.wait_for_thread(self.presenter._load_thread)

        self.assertEqual(self.load_utils_patcher.load_workspace_from_filename.call_count, load_call_count + 1)
        filename = self.load_utils_patcher.load_workspace_from_filename.call_args[0][0]
        self.assertEqual(os.path.basename(filename), new_filename)

    @run_test_with_and_without_threading
    def test_that_increment_run_attempts_to_load_the_correct_run(self):
        new_filename = "EMU00001235.nxs"
        load_call_count = self.load_utils_patcher.load_workspace_from_filename.call_count

        self.presenter.handle_increment_run()
        self.wait_for_thread(self.presenter._load_thread)

        self.assertEqual(self.load_utils_patcher.load_workspace_from_filename.call_count, load_call_count + 1)
        filename = self.load_utils_patcher.load_workspace_from_filename.call_args[0][0]
        self.assertEqual(os.path.basename(filename), new_filename)

    @run_test_with_and_without_threading
    def test_that_decrement_run_loads_the_data_correctly(self):
        new_run = self._loaded_run - 1
        new_filename = "EMU00001233.nxs"
        self.load_utils_patcher.load_workspace_from_filename = mock.Mock(return_value=({'MainFieldDirection': 'transverse'}, new_run, new_filename))

        self.presenter.handle_decrement_run()
        self.wait_for_thread(self.presenter._load_thread)

        self.assertEqual(self.presenter.filenames, [self._loaded_filename, new_filename])
        self.assertEqual(self.presenter.runs, [[self._loaded_run], [new_run]])
        self.assertEqual(self.presenter.workspaces, [self._loaded_workspace, {'MainFieldDirection': 'transverse'}])

        self.assertEqual(self.view.get_run_edit_text(), '1233')

    @run_test_with_and_without_threading
    def test_that_increment_run_loads_the_data_correctly(self):
        new_run = self._loaded_run + 1
        new_filename = "EMU00001235.nxs"
        self.load_utils_patcher.load_workspace_from_filename = mock.Mock(return_value=({'MainFieldDirection': 'transverse'}, new_run, new_filename))

        self.presenter.handle_increment_run()
        self.wait_for_thread(self.presenter._load_thread)

        self.assertEqual(self.presenter.filenames, [self._loaded_filename, new_filename])
        self.assertEqual(self.presenter.runs, [[self._loaded_run], [new_run]])
        self.assertEqual(self.presenter.workspaces, [self._loaded_workspace, {'MainFieldDirection': 'transverse'}])

        self.assertEqual(self.view.get_run_edit_text(), '1235')

    @run_test_with_and_without_threading
    def test_that_if_decrement_run_fails_the_data_are_returned_to_previous_state(self):
        self.load_utils_patcher.load_workspace_from_filename = mock.Mock(side_effect=self.load_failure)

        self.presenter.handle_decrement_run()
        self.wait_for_thread(self.presenter._load_thread)

        self.assert_model_has_not_changed()
        self.assertEqual(self.view.get_run_edit_text(), '')

    @run_test_with_and_without_threading
    def test_that_if_increment_run_fails_the_data_are_returned_to_previous_state(self):
        self.load_utils_patcher.load_workspace_from_filename = mock.Mock(side_effect=self.load_failure)

        self.presenter.handle_increment_run()
        self.wait_for_thread(self.presenter._load_thread)

        self.assert_model_has_not_changed()
        self.assertEqual(self.view.get_run_edit_text(), '')

    @run_test_with_and_without_threading
    def test_that_if_decrement_run_fails_warning_message_is_displayed(self):
        self.load_utils_patcher.load_workspace_from_filename = mock.Mock(side_effect=self.load_failure)

        self.presenter.handle_decrement_run()
        self.wait_for_thread(self.presenter._load_thread)

        self.assertEqual(self.view.warning_popup.call_count, 1)

    @run_test_with_and_without_threading
    def test_that_if_increment_run_fails_warning_message_is_displayed(self):
        self.load_utils_patcher.load_workspace_from_filename = mock.Mock(side_effect=self.load_failure)

        self.presenter.handle_increment_run()
        self.wait_for_thread(self.presenter._load_thread)

        self.assertEqual(self.view.warning_popup.call_count, 1)