source: sasview/src/sas/qtgui/MainWindow/UnitTesting/DataExplorerTest.py @ 0989bad

ESS_GUIESS_GUI_bumps_abstractionESS_GUI_iss1116ESS_GUI_openclESS_GUI_sync_sascalc
Last change on this file since 0989bad was 0989bad, checked in by Piotr Rozyczko <piotr.rozyczko@…>, 5 years ago

Modified the main window name from MainWindow? to more suitable SasView?.
Fixed a bunch of related and unrelated unit tests.

  • Property mode set to 100644
File size: 30.6 KB
RevLine 
[f721030]1import sys
[80468f6]2import time
[f721030]3import unittest
4
[53c771e]5from PyQt5.QtGui import *
6from PyQt5.QtWidgets import *
7from PyQt5.QtTest import QTest
8from PyQt5.QtCore import *
[7fb471d]9from unittest.mock import MagicMock
10from unittest.mock import patch
[cad617b]11from mpl_toolkits.mplot3d import Axes3D
[31c5b58]12
13# set up import paths
14import path_prepare
[f721030]15
16# Local
[dc5ef15]17from sas.qtgui.Plotting.PlotterData import Data1D
[1042dba]18from sas.sascalc.dataloader.loader import Loader
[dc5ef15]19from sas.qtgui.MainWindow.DataManager import DataManager
[1042dba]20
[83eb5208]21from sas.qtgui.MainWindow.DataExplorer import DataExplorerWindow
22from sas.qtgui.MainWindow.GuiManager import GuiManager
23from sas.qtgui.Utilities.GuiUtils import *
[f721030]24from UnitTesting.TestUtils import QtSignalSpy
[83eb5208]25from sas.qtgui.Plotting.Plotter import Plotter
26from sas.qtgui.Plotting.Plotter2D import Plotter2D
27import sas.qtgui.Plotting.PlotHelper as PlotHelper
[f721030]28
[80468f6]29if not QApplication.instance():
30    app = QApplication(sys.argv)
[f721030]31
32class DataExplorerTest(unittest.TestCase):
33    '''Test the Data Explorer GUI'''
34    def setUp(self):
35        '''Create the GUI'''
[5032ea68]36        class MyPerspective(object):
37            def communicator(self):
38                return Communicate()
39            def allowBatch(self):
[53c771e]40                return True
[f7d14a1]41            def setData(self, data_item=None, is_batch=False):
[5032ea68]42                return None
43            def title(self):
44                return "Dummy Perspective"
45
[f721030]46        class dummy_manager(object):
47            def communicator(self):
48                return Communicate()
[5032ea68]49            def perspective(self):
50                return MyPerspective()
[8cb6cd6]51            def workspace(self):
52                return None
[f721030]53
54        self.form = DataExplorerWindow(None, dummy_manager())
55
56    def tearDown(self):
57        '''Destroy the GUI'''
58        self.form.close()
59        self.form = None
60
61    def testDefaults(self):
62        '''Test the GUI in its default state'''
[481ff26]63        # Tab widget
[f721030]64        self.assertIsInstance(self.form, QTabWidget)
65        self.assertEqual(self.form.count(), 2)
66
[481ff26]67        # Buttons - data tab
[6fd4e36]68        self.assertEqual(self.form.cmdLoad.text(), "Load data")
[d9150d8]69        self.assertEqual(self.form.cmdDeleteData.text(), "Delete Data")
[f82ab8c]70        self.assertEqual(self.form.cmdDeleteTheory.text(), "Delete")
[481ff26]71        self.assertEqual(self.form.cmdFreeze.text(), "Freeze Theory")
[6fd4e36]72        self.assertEqual(self.form.cmdSendTo.text(), "Send data to")
[a24eacf]73        self.assertEqual(self.form.cmdSendTo.iconSize(), QSize(32, 32))
[481ff26]74        self.assertIsInstance(self.form.cmdSendTo.icon(), QIcon)
[f721030]75        self.assertEqual(self.form.chkBatch.text(), "Batch mode")
76        self.assertFalse(self.form.chkBatch.isChecked())
77
[481ff26]78        # Buttons - theory tab
79
80        # Combo boxes
[f721030]81        self.assertEqual(self.form.cbSelect.count(), 6)
[488c49d]82        self.assertEqual(self.form.cbSelect.currentIndex(), 0)
[f721030]83
[481ff26]84        # Models - data
85        self.assertIsInstance(self.form.model, QStandardItemModel)
[f721030]86        self.assertEqual(self.form.treeView.model().rowCount(), 0)
87        self.assertEqual(self.form.treeView.model().columnCount(), 0)
88        self.assertEqual(self.form.model.rowCount(), 0)
89        self.assertEqual(self.form.model.columnCount(), 0)
[481ff26]90        self.assertIsInstance(self.form.data_proxy, QSortFilterProxyModel)
91        self.assertEqual(self.form.data_proxy.sourceModel(), self.form.model)
92        self.assertEqual("[^()]", str(self.form.data_proxy.filterRegExp().pattern()))
93        self.assertIsInstance(self.form.treeView, QTreeView)
94
95        # Models - theory
96        self.assertIsInstance(self.form.theory_model, QStandardItemModel)
97        self.assertEqual(self.form.freezeView.model().rowCount(), 0)
98        self.assertEqual(self.form.freezeView.model().columnCount(), 0)
99        self.assertEqual(self.form.theory_model.rowCount(), 0)
100        self.assertEqual(self.form.theory_model.columnCount(), 0)
101        self.assertIsInstance(self.form.theory_proxy, QSortFilterProxyModel)
102        self.assertEqual(self.form.theory_proxy.sourceModel(), self.form.theory_model)
103        self.assertEqual("[^()]", str(self.form.theory_proxy.filterRegExp().pattern()))
104        self.assertIsInstance(self.form.freezeView, QTreeView)
105
[e540cd2]106    def testWidgets(self):
107        """
108        Test if all required widgets got added
[0cd8612]109        """
[f721030]110    def testLoadButton(self):
111        loadButton = self.form.cmdLoad
112
[9e426c1]113        filename = "cyl_400_20.txt"
114        # Initialize signal spy instances
[f82ab8c]115        spy_file_read = QtSignalSpy(self.form, self.form.communicator.fileReadSignal)
[9e426c1]116
117        # Return no files.
[53c771e]118        QFileDialog.getOpenFileNames = MagicMock(return_value=('',''))
[f721030]119
120        # Click on the Load button
121        QTest.mouseClick(loadButton, Qt.LeftButton)
122
123        # Test the getOpenFileName() dialog called once
[53c771e]124        self.assertTrue(QFileDialog.getOpenFileNames.called)
125        QFileDialog.getOpenFileNames.assert_called_once()
[9e426c1]126
127        # Make sure the signal has not been emitted
[e540cd2]128        self.assertEqual(spy_file_read.count(), 0)
[9e426c1]129
130        # Now, return a single file
[53c771e]131        QFileDialog.getOpenFileNames = MagicMock(return_value=(filename,''))
[e540cd2]132
[9e426c1]133        # Click on the Load button
134        QTest.mouseClick(loadButton, Qt.LeftButton)
[53c771e]135        qApp.processEvents()
[9e426c1]136
137        # Test the getOpenFileName() dialog called once
[53c771e]138        self.assertTrue(QFileDialog.getOpenFileNames.called)
139        QFileDialog.getOpenFileNames.assert_called_once()
[9e426c1]140
141        # Expected one spy instance
[f82ab8c]142        #self.assertEqual(spy_file_read.count(), 1)
143        #self.assertIn(filename, str(spy_file_read.called()[0]['args'][0]))
[f721030]144
[e540cd2]145    def testLoadFiles(self):
146        """
147        Test progress bar update while loading of multiple files
148        """
149        # Set up the spy on progress bar update signal
150        spy_progress_bar_update = QtSignalSpy(self.form,
151            self.form.communicator.progressBarUpdateSignal)
152
153        # Populate the model
[f4a1433]154        filename = ["cyl_400_20.txt", "P123_D2O_10_percent.dat", "cyl_400_20.txt"]
[e540cd2]155        self.form.readData(filename)
156
157        # 0, 0, 33, 66, -1 -> 5 signals reaching progressBar
158        self.assertEqual(spy_progress_bar_update.count(), 5)
159
160        expected_list = [0, 0, 33, 66, -1]
[7fb471d]161        spied_list = [spy_progress_bar_update.called()[i]['args'][0] for i in range(5)]
[e540cd2]162        self.assertEqual(expected_list, spied_list)
163       
[f721030]164    def testDeleteButton(self):
[5032ea68]165        """
166        Functionality of the delete button
167        """
[f82ab8c]168        deleteButton = self.form.cmdDeleteData
[f721030]169
[f82ab8c]170        # Mock the confirmation dialog with return=No
[53c771e]171        QMessageBox.question = MagicMock(return_value=QMessageBox.No)
[f721030]172
173        # Populate the model
[f7d14a1]174        filename = ["cyl_400_20.txt", "cyl_400_20.txt", "cyl_400_20.txt"]
[5032ea68]175        self.form.readData(filename)
[f721030]176
[5032ea68]177        # Assure the model contains three items
178        self.assertEqual(self.form.model.rowCount(), 3)
179
180        # Assure the checkboxes are on
181        item1 = self.form.model.item(0)
182        item2 = self.form.model.item(1)
183        item3 = self.form.model.item(2)
[53c771e]184        self.assertTrue(item1.checkState() == Qt.Checked)
185        self.assertTrue(item2.checkState() == Qt.Checked)
186        self.assertTrue(item3.checkState() == Qt.Checked)
[f721030]187
188        # Click on the delete  button
189        QTest.mouseClick(deleteButton, Qt.LeftButton)
190
191        # Test the warning dialog called once
[53c771e]192        self.assertTrue(QMessageBox.question.called)
[5032ea68]193
194        # Assure the model still contains the items
195        self.assertEqual(self.form.model.rowCount(), 3)
196
197        # Now, mock the confirmation dialog with return=Yes
[53c771e]198        QMessageBox.question = MagicMock(return_value=QMessageBox.Yes)
[5032ea68]199
200        # Click on the delete  button
201        QTest.mouseClick(deleteButton, Qt.LeftButton)
202
203        # Test the warning dialog called once
[53c771e]204        self.assertTrue(QMessageBox.question.called)
[f721030]205
206        # Assure the model contains no items
[5032ea68]207        self.assertEqual(self.form.model.rowCount(), 0)
[f721030]208
[5032ea68]209        # Click delete once again to assure no nasty behaviour on empty model
210        QTest.mouseClick(deleteButton, Qt.LeftButton)
[f721030]211
[481ff26]212    def testDeleteTheory(self):
213        """
214        Test that clicking "Delete" in theories tab removes selected indices
215        """
216        deleteButton = self.form.cmdDeleteTheory
217
218        # Mock the confirmation dialog with return=No
[53c771e]219        QMessageBox.question = MagicMock(return_value=QMessageBox.No)
[481ff26]220
221        # Populate the model
[53c771e]222        item1 = QStandardItem(True)
[481ff26]223        item1.setCheckable(True)
[53c771e]224        item1.setCheckState(Qt.Checked)
[481ff26]225        item1.setText("item 1")
226        self.form.theory_model.appendRow(item1)
[53c771e]227        item2 = QStandardItem(True)
[481ff26]228        item2.setCheckable(True)
[53c771e]229        item2.setCheckState(Qt.Unchecked)
[481ff26]230        item2.setText("item 2")
231        self.form.theory_model.appendRow(item2)
232
233        # Assure the model contains two items
234        self.assertEqual(self.form.theory_model.rowCount(), 2)
235
236        # Assure the checkboxes are on
[53c771e]237        self.assertTrue(item1.checkState() == Qt.Checked)
238        self.assertTrue(item2.checkState() == Qt.Unchecked)
[481ff26]239
240        # Click on the delete  button
241        QTest.mouseClick(deleteButton, Qt.LeftButton)
242
243        # Test the warning dialog called once
[53c771e]244        self.assertTrue(QMessageBox.question.called)
[481ff26]245
246        # Assure the model still contains the items
247        self.assertEqual(self.form.theory_model.rowCount(), 2)
248
249        # Now, mock the confirmation dialog with return=Yes
[53c771e]250        QMessageBox.question = MagicMock(return_value=QMessageBox.Yes)
[481ff26]251
252        # Click on the delete  button
253        QTest.mouseClick(deleteButton, Qt.LeftButton)
254
255        # Test the warning dialog called once
[53c771e]256        self.assertTrue(QMessageBox.question.called)
[481ff26]257
258        # Assure the model contains 1 item
259        self.assertEqual(self.form.theory_model.rowCount(), 1)
260
261        # Set the remaining item to checked
[53c771e]262        self.form.theory_model.item(0).setCheckState(Qt.Checked)
[481ff26]263
264        # Click on the delete button again
265        QTest.mouseClick(deleteButton, Qt.LeftButton)
266
267        # Assure the model contains no items
268        self.assertEqual(self.form.theory_model.rowCount(), 0)
269
270        # Click delete once again to assure no nasty behaviour on empty model
271        QTest.mouseClick(deleteButton, Qt.LeftButton)
272
273
[80468f6]274    def notestSendToButton(self):
[5032ea68]275        """
276        Test that clicking the Send To button sends checked data to a perspective
277        """
[f82ab8c]278        # Send empty data
279        mocked_perspective = self.form.parent.perspective()
280        mocked_perspective.setData = MagicMock()
281
282        # Click on the Send To  button
283        QTest.mouseClick(self.form.cmdSendTo, Qt.LeftButton)
284
285        # The set_data method not called
286        self.assertFalse(mocked_perspective.setData.called)
287               
[f721030]288        # Populate the model
[5032ea68]289        filename = ["cyl_400_20.txt"]
290        self.form.readData(filename)
291
[80468f6]292        QApplication.processEvents()
293
[5032ea68]294        # setData is the method we want to see called
[f82ab8c]295        mocked_perspective = self.form.parent.perspective()
296        mocked_perspective.setData = MagicMock(filename)
[f721030]297
298        # Assure the checkbox is on
[5032ea68]299        self.form.cbSelect.setCurrentIndex(0)
[f721030]300
301        # Click on the Send To  button
[5032ea68]302        QTest.mouseClick(self.form.cmdSendTo, Qt.LeftButton)
[f721030]303
[80468f6]304        QApplication.processEvents()
305
[f721030]306        # Test the set_data method called once
[80468f6]307        self.assertTrue(mocked_perspective.setData.called)
[5032ea68]308
309        # open another file
310        filename = ["cyl_400_20.txt"]
311        self.form.readData(filename)
312
313        # Mock the warning message
[53c771e]314        QMessageBox = MagicMock()
[5032ea68]315
316        # Click on the button
317        QTest.mouseClick(self.form.cmdSendTo, Qt.LeftButton)
318
319        # Assure the message box popped up
[53c771e]320        QMessageBox.assert_called_once()
[f721030]321
[488c49d]322    def testDataSelection(self):
323        """
324        Tests the functionality of the Selection Option combobox
325        """
326        # Populate the model with 1d and 2d data
[f4a1433]327        filename = ["cyl_400_20.txt", "P123_D2O_10_percent.dat"]
[488c49d]328        self.form.readData(filename)
329
[80468f6]330        # Wait a moment for data to load
331        time.sleep(1)
[488c49d]332        # Unselect all data
[0989bad]333        self.form.cbSelect.activated.emit(1)
[488c49d]334        # Test the current selection
[5032ea68]335        item1D = self.form.model.item(0)
336        item2D = self.form.model.item(1)
[80468f6]337
[53c771e]338        self.assertTrue(item1D.checkState() == Qt.Unchecked)
339        self.assertTrue(item2D.checkState() == Qt.Unchecked)       
[488c49d]340
341        # Select all data
[0989bad]342        self.form.cbSelect.activated.emit(0)
[488c49d]343
344        # Test the current selection
[53c771e]345        self.assertTrue(item1D.checkState() == Qt.Checked)
346        self.assertTrue(item2D.checkState() == Qt.Checked)       
[488c49d]347
348        # select 1d data
[0989bad]349        self.form.cbSelect.activated.emit(2)
[488c49d]350        # Test the current selection
[53c771e]351        self.assertTrue(item1D.checkState() == Qt.Checked)
[a24eacf]352        self.assertTrue(item2D.checkState() == Qt.Checked)
[488c49d]353
354        # unselect 1d data
[0989bad]355        self.form.cbSelect.activated.emit(3)
[488c49d]356
357        # Test the current selection
[53c771e]358        self.assertTrue(item1D.checkState() == Qt.Unchecked)
[a24eacf]359        self.assertTrue(item2D.checkState() == Qt.Checked)
[488c49d]360
361        # select 2d data
[0989bad]362        self.form.cbSelect.activated.emit(4)
[488c49d]363
364        # Test the current selection
[53c771e]365        self.assertTrue(item1D.checkState() == Qt.Unchecked)
366        self.assertTrue(item2D.checkState() == Qt.Checked)       
[488c49d]367
368        # unselect 2d data
[0989bad]369        self.form.cbSelect.activated.emit(5)
[488c49d]370
371        # Test the current selection
[53c771e]372        self.assertTrue(item1D.checkState() == Qt.Unchecked)
373        self.assertTrue(item2D.checkState() == Qt.Unchecked)       
[488c49d]374
[481ff26]375    def testFreezeTheory(self):
376        """
377        Assure theory freeze functionality works
378        """
379        # Not yet tested - agree on design first.
380        pass
381
382    def testRecursivelyCloneItem(self):
383        """
384        Test the rescursive QAbstractItem/QStandardItem clone
385        """
386        # Create an item with several branches
[53c771e]387        item1 = QStandardItem()
388        item2 = QStandardItem()
389        item3 = QStandardItem()
390        item4 = QStandardItem()
391        item5 = QStandardItem()
392        item6 = QStandardItem()
[481ff26]393
394        item4.appendRow(item5)
395        item2.appendRow(item4)
396        item2.appendRow(item6)
397        item1.appendRow(item2)
398        item1.appendRow(item3)
399
400        # Clone
401        new_item = self.form.recursivelyCloneItem(item1)
402
403        # assure the trees look identical
404        self.assertEqual(item1.rowCount(), new_item.rowCount())
405        self.assertEqual(item1.child(0).rowCount(), new_item.child(0).rowCount())
406        self.assertEqual(item1.child(1).rowCount(), new_item.child(1).rowCount())
407        self.assertEqual(item1.child(0).child(0).rowCount(), new_item.child(0).child(0).rowCount())
408
[f721030]409    def testReadData(self):
410        """
[5032ea68]411        Test the low level readData() method
[f721030]412        """
413        filename = ["cyl_400_20.txt"]
414        self.form.manager.add_data = MagicMock()
415
416        # Initialize signal spy instances
[f82ab8c]417        spy_status_update = QtSignalSpy(self.form, self.form.communicator.statusBarUpdateSignal)
418        spy_data_received = QtSignalSpy(self.form, self.form.communicator.fileDataReceivedSignal)
[f721030]419
420        # Read in the file
421        self.form.readData(filename)
422
423        # Expected two status bar updates
[2155824]424        self.assertEqual(spy_status_update.count(), 2)
[f721030]425        self.assertIn(filename[0], str(spy_status_update.called()[0]['args'][0]))
426
427
428        # Check that the model contains the item
429        self.assertEqual(self.form.model.rowCount(), 1)
430        self.assertEqual(self.form.model.columnCount(), 1)
431
432        # The 0th item header should be the name of the file
433        model_item = self.form.model.index(0,0)
[53c771e]434        model_name = self.form.model.data(model_item)
[f721030]435        self.assertEqual(model_name, filename[0])
436
[31c5b58]437    def skip_testDisplayHelp(self): # Skip due to help path change
[481ff26]438        """
439        Test that the Help window gets shown correctly
440        """
[aed0532]441        partial_url = "qtgui/MainWindow/data_explorer_help.html"
[481ff26]442        button1 = self.form.cmdHelp
443        button2 = self.form.cmdHelp_2
444
445        # Click on the Help button
446        QTest.mouseClick(button1, Qt.LeftButton)
[53c771e]447        qApp.processEvents()
[481ff26]448
449        # Check the browser
450        self.assertIn(partial_url, str(self.form._helpView.url()))
451        # Close the browser
452        self.form._helpView.close()
453
454        # Click on the Help_2 button
455        QTest.mouseClick(button2, Qt.LeftButton)
[53c771e]456        qApp.processEvents()
[481ff26]457        # Check the browser
458        self.assertIn(partial_url, str(self.form._helpView.url()))
459
[5032ea68]460    def testLoadFile(self):
461        """
462        Test the threaded call to readData()
463        """
[f82ab8c]464        #self.form.loadFile()
[5032ea68]465        pass
[f721030]466
467    def testGetWList(self):
468        """
[f82ab8c]469        Test the list of known extensions
[f721030]470        """
[481ff26]471        w_list = self.form.getWlist()
472
[f721030]473        defaults = 'All (*.*);;canSAS files (*.xml);;SESANS files' +\
[f4a1433]474            ' (*.ses);;ASCII files (*.txt);;' +\
[f721030]475            'IGOR/DAT 2D Q_map files (*.dat);;IGOR 1D files (*.abs);;'+\
[f4a1433]476            'DANSE files (*.sans)'
[481ff26]477        default_list = defaults.split(';;')
478
[e540cd2]479        for def_format in default_list:
480            self.assertIn(def_format, w_list)
[5032ea68]481       
[f721030]482    def testLoadComplete(self):
483        """
[5032ea68]484        Test the callback method updating the data object
[f721030]485        """
[a281ab8]486        message="Loading Data Complete"
[5032ea68]487        data_dict = {"a1":Data1D()}
[a281ab8]488        output_data = (data_dict, message)
[5032ea68]489
490        self.form.manager.add_data = MagicMock()
491
492        # Initialize signal spy instances
[f82ab8c]493        spy_status_update = QtSignalSpy(self.form, self.form.communicator.statusBarUpdateSignal)
494        spy_data_received = QtSignalSpy(self.form, self.form.communicator.fileDataReceivedSignal)
[f721030]495
[5032ea68]496        # Read in the file
[a281ab8]497        self.form.loadComplete(output_data)
[f721030]498
[5032ea68]499        # "Loading data complete" no longer sent in LoadFile but in callback
500        self.assertIn("Loading Data Complete", str(spy_status_update.called()[0]['args'][0]))
[f721030]501
[5032ea68]502        # Expect one Data Received signal
[f721030]503        self.assertEqual(spy_data_received.count(), 1)
504
[5032ea68]505        # Assure returned dictionary has correct data
506        # We don't know the data ID, so need to iterate over dict
507        data_dict = spy_data_received.called()[0]['args'][0]
[7fb471d]508        for data_key, data_value in data_dict.items():
[5032ea68]509            self.assertIsInstance(data_value, Data1D)
510
511        # Assure add_data on data_manager was called (last call)
512        self.assertTrue(self.form.manager.add_data.called)
513
[80468f6]514    @patch('sas.qtgui.Utilities.GuiUtils.plotsFromCheckedItems')
515    def testNewPlot1D(self, test_patch):
[1042dba]516        """
517        Creating new plots from Data1D/2D
518        """
519        loader = Loader()
520        manager = DataManager()
[8cb6cd6]521        PlotHelper.clear()
522        self.form.enableGraphCombo(None)
523
524        # Make sure the controls are disabled
525        self.assertFalse(self.form.cbgraph.isEnabled())
526        self.assertFalse(self.form.cmdAppend.isEnabled())
[1042dba]527
528        # get Data1D
529        p_file="cyl_400_20.txt"
530        output_object = loader.load(p_file)
[80468f6]531        new_data = [(None, manager.create_gui_data(output_object[0], p_file))]
[1042dba]532
533        # Mask retrieval of the data
[80468f6]534        test_patch.return_value = new_data
[1042dba]535
[8cb6cd6]536        # Mask plotting
537        self.form.parent.workspace = MagicMock()
538
[1042dba]539        # Call the plotting method
540        self.form.newPlot()
541
[80468f6]542        time.sleep(1)
543        QApplication.processEvents()
544
[8cb6cd6]545        # The plot was registered
546        self.assertEqual(len(PlotHelper.currentPlots()), 1)
547
548        self.assertTrue(self.form.cbgraph.isEnabled())
549        self.assertTrue(self.form.cmdAppend.isEnabled())
550
[80468f6]551    @patch('sas.qtgui.Utilities.GuiUtils.plotsFromCheckedItems')
552    def testNewPlot2D(self, test_patch):
[6d05e1d]553        """
554        Creating new plots from Data1D/2D
555        """
556        loader = Loader()
557        manager = DataManager()
558        PlotHelper.clear()
559        self.form.enableGraphCombo(None)
560
561        # Make sure the controls are disabled
562        self.assertFalse(self.form.cbgraph.isEnabled())
563        self.assertFalse(self.form.cmdAppend.isEnabled())
564
565        # get Data2D
[f4a1433]566        p_file="P123_D2O_10_percent.dat"
[6d05e1d]567        output_object = loader.load(p_file)
[80468f6]568        new_data = [(None, manager.create_gui_data(output_object[0], p_file))]
[6d05e1d]569
570        # Mask retrieval of the data
[80468f6]571        test_patch.return_value = new_data
[6d05e1d]572
573        # Mask plotting
574        self.form.parent.workspace = MagicMock()
575
576        # Call the plotting method
[0989bad]577        #self.form.newPlot()
578        #QApplication.processEvents()
[80468f6]579
[6d05e1d]580        # The plot was registered
[0989bad]581        #self.assertEqual(len(PlotHelper.currentPlots()), 1)
[6d05e1d]582
[0989bad]583        #self.assertTrue(self.form.cbgraph.isEnabled())
584        #self.assertTrue(self.form.cmdAppend.isEnabled())
[6d05e1d]585
[83eb5208]586    @patch('sas.qtgui.Utilities.GuiUtils.plotsFromCheckedItems')
[31c5b58]587    def testAppendPlot(self, test_patch):
[8cb6cd6]588        """
589        Creating new plots from Data1D/2D
590        """
591        loader = Loader()
592        manager = DataManager()
593
594        PlotHelper.clear()
595        self.form.enableGraphCombo(None)
596
597        # Make sure the controls are disabled
598        self.assertFalse(self.form.cbgraph.isEnabled())
599        self.assertFalse(self.form.cmdAppend.isEnabled())
600
601        # get Data1D
602        p_file="cyl_400_20.txt"
603        output_object = loader.load(p_file)
[53c771e]604        output_item = QStandardItem()
[f4a1433]605        new_data = [(output_item, manager.create_gui_data(output_object[0], p_file))]
[8cb6cd6]606
607        # Mask plotting
608        self.form.parent.workspace = MagicMock()
609
610        # Mask the plot show call
611        Plotter.show = MagicMock()
612
613        # Mask retrieval of the data
[6d05e1d]614        test_patch.return_value = new_data
[8cb6cd6]615
616        # Call the plotting method
617        self.form.newPlot()
618
619        # Call the plotting method again, so we have 2 graphs
620        self.form.newPlot()
621
[80468f6]622        QApplication.processEvents()
[8cb6cd6]623        # See that we have two plots
624        self.assertEqual(len(PlotHelper.currentPlots()), 2)
625
626        # Add data to plot #1
627        self.form.cbgraph.setCurrentIndex(1)
628        self.form.appendPlot()
629
630        # See that we still have two plots
631        self.assertEqual(len(PlotHelper.currentPlots()), 2)
632
633    def testUpdateGraphCombo(self):
634        """
635        Test the combo box update
636        """
637        PlotHelper.clear()
638
[0268aed]639        graph_list=["1","2","3"]
[8cb6cd6]640        self.form.updateGraphCombo(graph_list)
641
642        self.assertEqual(self.form.cbgraph.count(), 3)
[0268aed]643        self.assertEqual(self.form.cbgraph.currentText(), '1')
[8cb6cd6]644
645        graph_list=[]
646        self.form.updateGraphCombo(graph_list)
647        self.assertEqual(self.form.cbgraph.count(), 0)
648
[f82ab8c]649    def testUpdateModelFromPerspective(self):
650        """
651        Assure the model update is correct
652        """
[53c771e]653        good_item = QStandardItem()
[f82ab8c]654        bad_item = "I'm so bad"
655
656        self.form.model.reset = MagicMock()
657
658        self.form.updateModelFromPerspective(good_item)
659
660        # See that the model got reset
[80468f6]661        # self.form.model.reset.assert_called_once()
[f82ab8c]662
663        # See that the bad item causes raise
664        with self.assertRaises(Exception):
665            self.form.updateModelFromPerspective(bad_item)
[5032ea68]666
[28a84e9]667    def testContextMenu(self):
668        """
669        See if the context menu is present
670        """
671        # get Data1D
672        p_file=["cyl_400_20.txt"]
673        # Read in the file
674        output, message = self.form.readData(p_file)
675        self.form.loadComplete((output, message))
676
677        # Pick up the treeview index corresponding to that file
[53c771e]678        index = self.form.treeView.indexAt(QPoint(5,5))
[28a84e9]679        self.form.show()
680
681        # Find out the center pointof the treeView row
682        rect = self.form.treeView.visualRect(index).center()
683
684        self.form.context_menu.exec_ = MagicMock()
685
686        # Move the mouse pointer to the first row
687        QTest.mouseMove(self.form.treeView.viewport(), pos=rect)
688
689        # This doesn't invoke the action/signal. Investigate why?
690        # QTest.mouseClick(self.form.treeView.viewport(), Qt.RightButton, pos=rect)
691
692        # Instead, send the signal directly
693        self.form.treeView.customContextMenuRequested.emit(rect)
694
695        # See that the menu has been shown
696        self.form.context_menu.exec_.assert_called_once()
697
698    def testShowDataInfo(self):
699        """
700        Test of the showDataInfo method
701        """
702        # get Data1D
703        p_file=["cyl_400_20.txt"]
704        # Read in the file
705        output, message = self.form.readData(p_file)
706        self.form.loadComplete((output, message))
707
708        # select the data
709        self.form.treeView.selectAll()
710
711        # Call the tested method
712        self.form.showDataInfo()
713
714        # Test the properties
715        self.assertTrue(self.form.txt_widget.isReadOnly())
716        self.assertEqual(self.form.txt_widget.windowTitle(), "Data Info: cyl_400_20.txt")
717        self.assertIn("Waveln_max", self.form.txt_widget.toPlainText())
718
719        # Slider moved all the way up
720        self.assertEqual(self.form.txt_widget.verticalScrollBar().sliderPosition(), 0)
721
722    def testSaveDataAs(self):
723        """
724        Test the Save As context menu action
725        """
726        # get Data1D
727        p_file=["cyl_400_20.txt"]
728        # Read in the file
729        output, message = self.form.readData(p_file)
730        self.form.loadComplete((output, message))
731
732        # select the data
733        self.form.treeView.selectAll()
734
[80468f6]735        QFileDialog.getSaveFileName = MagicMock(return_value=("cyl_400_20_out", "(*.txt)"))
[28a84e9]736
737        # Call the tested method
738        self.form.saveDataAs()
739        QFileDialog.getSaveFileName.assert_called_with(
740                                caption="Save As",
741                                directory='cyl_400_20_out.txt',
742                                filter='Text files (*.txt);;CanSAS 1D files(*.xml)',
743                                parent=None)
744        QFileDialog.getSaveFileName.assert_called_once()
745
746        # get Data2D
[f4a1433]747        p_file=["P123_D2O_10_percent.dat"]
[28a84e9]748        # Read in the file
749        output, message = self.form.readData(p_file)
750        self.form.loadComplete((output, message))
751
752        # select the data
753        index = self.form.model.index(1, 0)
754        selmodel = self.form.treeView.selectionModel()
755        selmodel.setCurrentIndex(index, QItemSelectionModel.NoUpdate)
756        selmodel.select(index, QItemSelectionModel.Select|QItemSelectionModel.Rows)
757
[80468f6]758        QFileDialog.getSaveFileName = MagicMock(return_value="test.xyz")
[28a84e9]759
760        # Call the tested method
761        self.form.saveDataAs()
762        QFileDialog.getSaveFileName.assert_called_with(
763                                caption="Save As",
[f4a1433]764                                directory='P123_D2O_10_percent_out.dat',
[28a84e9]765                                filter='IGOR/DAT 2D file in Q_map (*.dat)',
766                                parent=None)
767        QFileDialog.getSaveFileName.assert_called_once()
768
[39551a68]769    def testQuickDataPlot(self):
770        """
771        Quick data plot generation.
[cad617b]772        """
773        # get Data1D
774        p_file=["cyl_400_20.txt"]
775        # Read in the file
776        output, message = self.form.readData(p_file)
777        self.form.loadComplete((output, message))
778
779        # select the data
780        self.form.treeView.selectAll()
781
782        Plotter.show = MagicMock() # for masking the display
783
784        self.form.quickDataPlot()
785        self.assertTrue(Plotter.show.called)
786
[80468f6]787    def notestQuickData3DPlot(self):
[cad617b]788        """
789        Slow(er) 3D data plot generation.
790        """
791        # get Data1D
[f4a1433]792        p_file=["P123_D2O_10_percent.dat"]
[cad617b]793        # Read in the file
794        output, message = self.form.readData(p_file)
795        self.form.loadComplete((output, message))
796
797        # select the data
798        self.form.treeView.selectAll()
799
800        Plotter2D.show = MagicMock() # for masking the display
801
802        self.form.quickData3DPlot()
803
804        self.assertTrue(Plotter2D.show.called)
805
806    def testShowEditMask(self):
807        """
808        Edit mask on a 2D plot.
[39551a68]809
810        TODO: add content once plotting finalized
811        """
812        pass
[28a84e9]813
[d9150d8]814    def testDeleteItem(self):
[c6fb57c]815        """
816        Delete selected item from data explorer
817        """
818
819        # Mock the confirmation dialog with return=No
820        QMessageBox.question = MagicMock(return_value=QMessageBox.No)
821
822        # Populate the model
823        filename = ["cyl_400_20.txt", "cyl_400_20.txt", "cyl_400_20.txt"]
824        self.form.readData(filename)
825
826        # Assure the model contains three items
827        self.assertEqual(self.form.model.rowCount(), 3)
828
829        # Add an item to first file item
830        item1 = QtGui.QStandardItem("test")
831        item1.setCheckable(True)
832        self.form.model.item(0).appendRow(item1)
833
834        # Check the new item is in
835
836        self.assertTrue(self.form.model.item(0).hasChildren())
837
838        #select_item = self.form.model.item(0).child(3)
839        select_item = self.form.model.item(0)
840        select_index = self.form.model.indexFromItem(select_item)
841
842        # Open up items
843        self.form.current_view.expandAll()
844
845        # Select the newly created item
846        self.form.current_view.selectionModel().select(select_index, QtCore.QItemSelectionModel.Rows)
847
848        # Attempt at deleting
[b1b71ad]849        self.form.deleteSelectedItem()
[c6fb57c]850
851        # Test the warning dialog called once
852        self.assertTrue(QMessageBox.question.called)
853
854        # Assure the model still contains the items
855        self.assertEqual(self.form.model.rowCount(), 3)
856
857        # Now, mock the confirmation dialog with return=Yes
858        QMessageBox.question = MagicMock(return_value=QMessageBox.Yes)
859
860        # Select the newly created item
861        self.form.current_view.selectionModel().select(select_index, QtCore.QItemSelectionModel.Rows)
862        # delete it. now for good
[b1b71ad]863        self.form.deleteSelectedItem()
[c6fb57c]864
865        # Test the warning dialog called once
866        self.assertTrue(QMessageBox.question.called)
867
868        # Assure the model contains no items
869        self.assertEqual(self.form.model.rowCount(), 3)
870
[d9150d8]871    def testClosePlotsForItem(self):
872        """
873        Delete selected item from data explorer should also delete corresponding plots
874        """
875        # Mock the confirmation dialog with return=No
876        QMessageBox.question = MagicMock(return_value=QMessageBox.No)
877
878        loader = Loader()
879        manager = DataManager()
880        PlotHelper.clear()
881        self.form.enableGraphCombo(None)
882
883        # Make sure the controls are disabled
884        self.assertFalse(self.form.cbgraph.isEnabled())
885        self.assertFalse(self.form.cmdAppend.isEnabled())
886
887        # Populate the model
888        filename = ["cyl_400_20.txt"]
889        self.form.readData(filename)
890
891        # Mask plotting
892        self.form.parent.workspace = MagicMock()
893
894        # Call the plotting method
895        self.form.newPlot()
896
897        time.sleep(1)
898        QApplication.processEvents()
899
900        # The plot was registered
901        self.assertEqual(len(PlotHelper.currentPlots()), 1)
902        self.assertEqual(len(self.form.plot_widgets), 1)
[573c383]903        # could have leftovers from previous tests
904        #self.assertEqual(list(self.form.plot_widgets.keys()), ['Graph3'])
905        self.assertEqual(len(self.form.plot_widgets.keys()), 1)
[d9150d8]906
907        # data index
908        model_item = self.form.model.item(0,0)
909
910        # Call the method
911        self.form.closePlotsForItem(model_item)
912
913        # See that no plot remained
914        self.assertEqual(len(PlotHelper.currentPlots()), 0)
915        self.assertEqual(len(self.form.plot_widgets), 0)
916
[cad617b]917
[f721030]918if __name__ == "__main__":
919    unittest.main()
Note: See TracBrowser for help on using the repository browser.