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

ESS_GUIESS_GUI_DocsESS_GUI_batch_fittingESS_GUI_bumps_abstractionESS_GUI_iss1116ESS_GUI_iss879ESS_GUI_iss959ESS_GUI_openclESS_GUI_orderingESS_GUI_sync_sascalc
Last change on this file since e90988c was c6fb57c, checked in by Piotr Rozyczko <rozyczko@…>, 7 years ago

Add "delete" to the data explorer context menu

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