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@…>, 8 months 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
Line 
1import sys
2import time
3import unittest
4
5from PyQt5.QtGui import *
6from PyQt5.QtWidgets import *
7from PyQt5.QtTest import QTest
8from PyQt5.QtCore import *
9from unittest.mock import MagicMock
10from unittest.mock import patch
11from mpl_toolkits.mplot3d import Axes3D
12
13# set up import paths
14import path_prepare
15
16# Local
17from sas.qtgui.Plotting.PlotterData import Data1D
18from sas.sascalc.dataloader.loader import Loader
19from sas.qtgui.MainWindow.DataManager import DataManager
20
21from sas.qtgui.MainWindow.DataExplorer import DataExplorerWindow
22from sas.qtgui.MainWindow.GuiManager import GuiManager
23from sas.qtgui.Utilities.GuiUtils import *
24from UnitTesting.TestUtils import QtSignalSpy
25from sas.qtgui.Plotting.Plotter import Plotter
26from sas.qtgui.Plotting.Plotter2D import Plotter2D
27import sas.qtgui.Plotting.PlotHelper as PlotHelper
28
29if not QApplication.instance():
30    app = QApplication(sys.argv)
31
32class DataExplorerTest(unittest.TestCase):
33    '''Test the Data Explorer GUI'''
34    def setUp(self):
35        '''Create the GUI'''
36        class MyPerspective(object):
37            def communicator(self):
38                return Communicate()
39            def allowBatch(self):
40                return True
41            def setData(self, data_item=None, is_batch=False):
42                return None
43            def title(self):
44                return "Dummy Perspective"
45
46        class dummy_manager(object):
47            def communicator(self):
48                return Communicate()
49            def perspective(self):
50                return MyPerspective()
51            def workspace(self):
52                return None
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'''
63        # Tab widget
64        self.assertIsInstance(self.form, QTabWidget)
65        self.assertEqual(self.form.count(), 2)
66
67        # Buttons - data tab
68        self.assertEqual(self.form.cmdLoad.text(), "Load data")
69        self.assertEqual(self.form.cmdDeleteData.text(), "Delete Data")
70        self.assertEqual(self.form.cmdDeleteTheory.text(), "Delete")
71        self.assertEqual(self.form.cmdFreeze.text(), "Freeze Theory")
72        self.assertEqual(self.form.cmdSendTo.text(), "Send data to")
73        self.assertEqual(self.form.cmdSendTo.iconSize(), QSize(32, 32))
74        self.assertIsInstance(self.form.cmdSendTo.icon(), QIcon)
75        self.assertEqual(self.form.chkBatch.text(), "Batch mode")
76        self.assertFalse(self.form.chkBatch.isChecked())
77
78        # Buttons - theory tab
79
80        # Combo boxes
81        self.assertEqual(self.form.cbSelect.count(), 6)
82        self.assertEqual(self.form.cbSelect.currentIndex(), 0)
83
84        # Models - data
85        self.assertIsInstance(self.form.model, QStandardItemModel)
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)
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
106    def testWidgets(self):
107        """
108        Test if all required widgets got added
109        """
110    def testLoadButton(self):
111        loadButton = self.form.cmdLoad
112
113        filename = "cyl_400_20.txt"
114        # Initialize signal spy instances
115        spy_file_read = QtSignalSpy(self.form, self.form.communicator.fileReadSignal)
116
117        # Return no files.
118        QFileDialog.getOpenFileNames = MagicMock(return_value=('',''))
119
120        # Click on the Load button
121        QTest.mouseClick(loadButton, Qt.LeftButton)
122
123        # Test the getOpenFileName() dialog called once
124        self.assertTrue(QFileDialog.getOpenFileNames.called)
125        QFileDialog.getOpenFileNames.assert_called_once()
126
127        # Make sure the signal has not been emitted
128        self.assertEqual(spy_file_read.count(), 0)
129
130        # Now, return a single file
131        QFileDialog.getOpenFileNames = MagicMock(return_value=(filename,''))
132
133        # Click on the Load button
134        QTest.mouseClick(loadButton, Qt.LeftButton)
135        qApp.processEvents()
136
137        # Test the getOpenFileName() dialog called once
138        self.assertTrue(QFileDialog.getOpenFileNames.called)
139        QFileDialog.getOpenFileNames.assert_called_once()
140
141        # Expected one spy instance
142        #self.assertEqual(spy_file_read.count(), 1)
143        #self.assertIn(filename, str(spy_file_read.called()[0]['args'][0]))
144
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
154        filename = ["cyl_400_20.txt", "P123_D2O_10_percent.dat", "cyl_400_20.txt"]
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]
161        spied_list = [spy_progress_bar_update.called()[i]['args'][0] for i in range(5)]
162        self.assertEqual(expected_list, spied_list)
163       
164    def testDeleteButton(self):
165        """
166        Functionality of the delete button
167        """
168        deleteButton = self.form.cmdDeleteData
169
170        # Mock the confirmation dialog with return=No
171        QMessageBox.question = MagicMock(return_value=QMessageBox.No)
172
173        # Populate the model
174        filename = ["cyl_400_20.txt", "cyl_400_20.txt", "cyl_400_20.txt"]
175        self.form.readData(filename)
176
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)
184        self.assertTrue(item1.checkState() == Qt.Checked)
185        self.assertTrue(item2.checkState() == Qt.Checked)
186        self.assertTrue(item3.checkState() == Qt.Checked)
187
188        # Click on the delete  button
189        QTest.mouseClick(deleteButton, Qt.LeftButton)
190
191        # Test the warning dialog called once
192        self.assertTrue(QMessageBox.question.called)
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
198        QMessageBox.question = MagicMock(return_value=QMessageBox.Yes)
199
200        # Click on the delete  button
201        QTest.mouseClick(deleteButton, Qt.LeftButton)
202
203        # Test the warning dialog called once
204        self.assertTrue(QMessageBox.question.called)
205
206        # Assure the model contains no items
207        self.assertEqual(self.form.model.rowCount(), 0)
208
209        # Click delete once again to assure no nasty behaviour on empty model
210        QTest.mouseClick(deleteButton, Qt.LeftButton)
211
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
219        QMessageBox.question = MagicMock(return_value=QMessageBox.No)
220
221        # Populate the model
222        item1 = QStandardItem(True)
223        item1.setCheckable(True)
224        item1.setCheckState(Qt.Checked)
225        item1.setText("item 1")
226        self.form.theory_model.appendRow(item1)
227        item2 = QStandardItem(True)
228        item2.setCheckable(True)
229        item2.setCheckState(Qt.Unchecked)
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
237        self.assertTrue(item1.checkState() == Qt.Checked)
238        self.assertTrue(item2.checkState() == Qt.Unchecked)
239
240        # Click on the delete  button
241        QTest.mouseClick(deleteButton, Qt.LeftButton)
242
243        # Test the warning dialog called once
244        self.assertTrue(QMessageBox.question.called)
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
250        QMessageBox.question = MagicMock(return_value=QMessageBox.Yes)
251
252        # Click on the delete  button
253        QTest.mouseClick(deleteButton, Qt.LeftButton)
254
255        # Test the warning dialog called once
256        self.assertTrue(QMessageBox.question.called)
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
262        self.form.theory_model.item(0).setCheckState(Qt.Checked)
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
274    def notestSendToButton(self):
275        """
276        Test that clicking the Send To button sends checked data to a perspective
277        """
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               
288        # Populate the model
289        filename = ["cyl_400_20.txt"]
290        self.form.readData(filename)
291
292        QApplication.processEvents()
293
294        # setData is the method we want to see called
295        mocked_perspective = self.form.parent.perspective()
296        mocked_perspective.setData = MagicMock(filename)
297
298        # Assure the checkbox is on
299        self.form.cbSelect.setCurrentIndex(0)
300
301        # Click on the Send To  button
302        QTest.mouseClick(self.form.cmdSendTo, Qt.LeftButton)
303
304        QApplication.processEvents()
305
306        # Test the set_data method called once
307        self.assertTrue(mocked_perspective.setData.called)
308
309        # open another file
310        filename = ["cyl_400_20.txt"]
311        self.form.readData(filename)
312
313        # Mock the warning message
314        QMessageBox = MagicMock()
315
316        # Click on the button
317        QTest.mouseClick(self.form.cmdSendTo, Qt.LeftButton)
318
319        # Assure the message box popped up
320        QMessageBox.assert_called_once()
321
322    def testDataSelection(self):
323        """
324        Tests the functionality of the Selection Option combobox
325        """
326        # Populate the model with 1d and 2d data
327        filename = ["cyl_400_20.txt", "P123_D2O_10_percent.dat"]
328        self.form.readData(filename)
329
330        # Wait a moment for data to load
331        time.sleep(1)
332        # Unselect all data
333        self.form.cbSelect.activated.emit(1)
334        # Test the current selection
335        item1D = self.form.model.item(0)
336        item2D = self.form.model.item(1)
337
338        self.assertTrue(item1D.checkState() == Qt.Unchecked)
339        self.assertTrue(item2D.checkState() == Qt.Unchecked)       
340
341        # Select all data
342        self.form.cbSelect.activated.emit(0)
343
344        # Test the current selection
345        self.assertTrue(item1D.checkState() == Qt.Checked)
346        self.assertTrue(item2D.checkState() == Qt.Checked)       
347
348        # select 1d data
349        self.form.cbSelect.activated.emit(2)
350        # Test the current selection
351        self.assertTrue(item1D.checkState() == Qt.Checked)
352        self.assertTrue(item2D.checkState() == Qt.Checked)
353
354        # unselect 1d data
355        self.form.cbSelect.activated.emit(3)
356
357        # Test the current selection
358        self.assertTrue(item1D.checkState() == Qt.Unchecked)
359        self.assertTrue(item2D.checkState() == Qt.Checked)
360
361        # select 2d data
362        self.form.cbSelect.activated.emit(4)
363
364        # Test the current selection
365        self.assertTrue(item1D.checkState() == Qt.Unchecked)
366        self.assertTrue(item2D.checkState() == Qt.Checked)       
367
368        # unselect 2d data
369        self.form.cbSelect.activated.emit(5)
370
371        # Test the current selection
372        self.assertTrue(item1D.checkState() == Qt.Unchecked)
373        self.assertTrue(item2D.checkState() == Qt.Unchecked)       
374
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
387        item1 = QStandardItem()
388        item2 = QStandardItem()
389        item3 = QStandardItem()
390        item4 = QStandardItem()
391        item5 = QStandardItem()
392        item6 = QStandardItem()
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
409    def testReadData(self):
410        """
411        Test the low level readData() method
412        """
413        filename = ["cyl_400_20.txt"]
414        self.form.manager.add_data = MagicMock()
415
416        # Initialize signal spy instances
417        spy_status_update = QtSignalSpy(self.form, self.form.communicator.statusBarUpdateSignal)
418        spy_data_received = QtSignalSpy(self.form, self.form.communicator.fileDataReceivedSignal)
419
420        # Read in the file
421        self.form.readData(filename)
422
423        # Expected two status bar updates
424        self.assertEqual(spy_status_update.count(), 2)
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)
434        model_name = self.form.model.data(model_item)
435        self.assertEqual(model_name, filename[0])
436
437    def skip_testDisplayHelp(self): # Skip due to help path change
438        """
439        Test that the Help window gets shown correctly
440        """
441        partial_url = "qtgui/MainWindow/data_explorer_help.html"
442        button1 = self.form.cmdHelp
443        button2 = self.form.cmdHelp_2
444
445        # Click on the Help button
446        QTest.mouseClick(button1, Qt.LeftButton)
447        qApp.processEvents()
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)
456        qApp.processEvents()
457        # Check the browser
458        self.assertIn(partial_url, str(self.form._helpView.url()))
459
460    def testLoadFile(self):
461        """
462        Test the threaded call to readData()
463        """
464        #self.form.loadFile()
465        pass
466
467    def testGetWList(self):
468        """
469        Test the list of known extensions
470        """
471        w_list = self.form.getWlist()
472
473        defaults = 'All (*.*);;canSAS files (*.xml);;SESANS files' +\
474            ' (*.ses);;ASCII files (*.txt);;' +\
475            'IGOR/DAT 2D Q_map files (*.dat);;IGOR 1D files (*.abs);;'+\
476            'DANSE files (*.sans)'
477        default_list = defaults.split(';;')
478
479        for def_format in default_list:
480            self.assertIn(def_format, w_list)
481       
482    def testLoadComplete(self):
483        """
484        Test the callback method updating the data object
485        """
486        message="Loading Data Complete"
487        data_dict = {"a1":Data1D()}
488        output_data = (data_dict, message)
489
490        self.form.manager.add_data = MagicMock()
491
492        # Initialize signal spy instances
493        spy_status_update = QtSignalSpy(self.form, self.form.communicator.statusBarUpdateSignal)
494        spy_data_received = QtSignalSpy(self.form, self.form.communicator.fileDataReceivedSignal)
495
496        # Read in the file
497        self.form.loadComplete(output_data)
498
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]))
501
502        # Expect one Data Received signal
503        self.assertEqual(spy_data_received.count(), 1)
504
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]
508        for data_key, data_value in data_dict.items():
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
514    @patch('sas.qtgui.Utilities.GuiUtils.plotsFromCheckedItems')
515    def testNewPlot1D(self, test_patch):
516        """
517        Creating new plots from Data1D/2D
518        """
519        loader = Loader()
520        manager = DataManager()
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())
527
528        # get Data1D
529        p_file="cyl_400_20.txt"
530        output_object = loader.load(p_file)
531        new_data = [(None, manager.create_gui_data(output_object[0], p_file))]
532
533        # Mask retrieval of the data
534        test_patch.return_value = new_data
535
536        # Mask plotting
537        self.form.parent.workspace = MagicMock()
538
539        # Call the plotting method
540        self.form.newPlot()
541
542        time.sleep(1)
543        QApplication.processEvents()
544
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
551    @patch('sas.qtgui.Utilities.GuiUtils.plotsFromCheckedItems')
552    def testNewPlot2D(self, test_patch):
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
566        p_file="P123_D2O_10_percent.dat"
567        output_object = loader.load(p_file)
568        new_data = [(None, manager.create_gui_data(output_object[0], p_file))]
569
570        # Mask retrieval of the data
571        test_patch.return_value = new_data
572
573        # Mask plotting
574        self.form.parent.workspace = MagicMock()
575
576        # Call the plotting method
577        #self.form.newPlot()
578        #QApplication.processEvents()
579
580        # The plot was registered
581        #self.assertEqual(len(PlotHelper.currentPlots()), 1)
582
583        #self.assertTrue(self.form.cbgraph.isEnabled())
584        #self.assertTrue(self.form.cmdAppend.isEnabled())
585
586    @patch('sas.qtgui.Utilities.GuiUtils.plotsFromCheckedItems')
587    def testAppendPlot(self, test_patch):
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)
604        output_item = QStandardItem()
605        new_data = [(output_item, manager.create_gui_data(output_object[0], p_file))]
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
614        test_patch.return_value = new_data
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
622        QApplication.processEvents()
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
639        graph_list=["1","2","3"]
640        self.form.updateGraphCombo(graph_list)
641
642        self.assertEqual(self.form.cbgraph.count(), 3)
643        self.assertEqual(self.form.cbgraph.currentText(), '1')
644
645        graph_list=[]
646        self.form.updateGraphCombo(graph_list)
647        self.assertEqual(self.form.cbgraph.count(), 0)
648
649    def testUpdateModelFromPerspective(self):
650        """
651        Assure the model update is correct
652        """
653        good_item = QStandardItem()
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
661        # self.form.model.reset.assert_called_once()
662
663        # See that the bad item causes raise
664        with self.assertRaises(Exception):
665            self.form.updateModelFromPerspective(bad_item)
666
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
678        index = self.form.treeView.indexAt(QPoint(5,5))
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
735        QFileDialog.getSaveFileName = MagicMock(return_value=("cyl_400_20_out", "(*.txt)"))
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
747        p_file=["P123_D2O_10_percent.dat"]
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
758        QFileDialog.getSaveFileName = MagicMock(return_value="test.xyz")
759
760        # Call the tested method
761        self.form.saveDataAs()
762        QFileDialog.getSaveFileName.assert_called_with(
763                                caption="Save As",
764                                directory='P123_D2O_10_percent_out.dat',
765                                filter='IGOR/DAT 2D file in Q_map (*.dat)',
766                                parent=None)
767        QFileDialog.getSaveFileName.assert_called_once()
768
769    def testQuickDataPlot(self):
770        """
771        Quick data plot generation.
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
787    def notestQuickData3DPlot(self):
788        """
789        Slow(er) 3D data plot generation.
790        """
791        # get Data1D
792        p_file=["P123_D2O_10_percent.dat"]
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.
809
810        TODO: add content once plotting finalized
811        """
812        pass
813
814    def testDeleteItem(self):
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
849        self.form.deleteSelectedItem()
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
863        self.form.deleteSelectedItem()
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
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)
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)
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
917
918if __name__ == "__main__":
919    unittest.main()
Note: See TracBrowser for help on using the repository browser.