(root)/
Python-3.12.0/
Lib/
idlelib/
idle_test/
test_query.py
       1  """Test query, coverage 93%.
       2  
       3  Non-gui tests for Query, SectionName, ModuleName, and HelpSource use
       4  dummy versions that extract the non-gui methods and add other needed
       5  attributes.  GUI tests create an instance of each class and simulate
       6  entries and button clicks.  Subclass tests only target the new code in
       7  the subclass definition.
       8  
       9  The appearance of the widgets is checked by the Query and
      10  HelpSource htests.  These are run by running query.py.
      11  """
      12  from idlelib import query
      13  import unittest
      14  from test.support import requires
      15  from tkinter import Tk, END
      16  
      17  import sys
      18  from unittest import mock
      19  from idlelib.idle_test.mock_tk import Var
      20  
      21  
      22  # NON-GUI TESTS
      23  
      24  class ESC[4;38;5;81mQueryTest(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
      25      "Test Query base class."
      26  
      27      class ESC[4;38;5;81mDummy_Query:
      28          # Test the following Query methods.
      29          entry_ok = query.Query.entry_ok
      30          ok = query.Query.ok
      31          cancel = query.Query.cancel
      32          # Add attributes and initialization needed for tests.
      33          def __init__(self, dummy_entry):
      34              self.entry = Var(value=dummy_entry)
      35              self.entry_error = {'text': ''}
      36              self.result = None
      37              self.destroyed = False
      38          def showerror(self, message):
      39              self.entry_error['text'] = message
      40          def destroy(self):
      41              self.destroyed = True
      42  
      43      def test_entry_ok_blank(self):
      44          dialog = self.Dummy_Query(' ')
      45          self.assertEqual(dialog.entry_ok(), None)
      46          self.assertEqual((dialog.result, dialog.destroyed), (None, False))
      47          self.assertIn('blank line', dialog.entry_error['text'])
      48  
      49      def test_entry_ok_good(self):
      50          dialog = self.Dummy_Query('  good ')
      51          Equal = self.assertEqual
      52          Equal(dialog.entry_ok(), 'good')
      53          Equal((dialog.result, dialog.destroyed), (None, False))
      54          Equal(dialog.entry_error['text'], '')
      55  
      56      def test_ok_blank(self):
      57          dialog = self.Dummy_Query('')
      58          dialog.entry.focus_set = mock.Mock()
      59          self.assertEqual(dialog.ok(), None)
      60          self.assertTrue(dialog.entry.focus_set.called)
      61          del dialog.entry.focus_set
      62          self.assertEqual((dialog.result, dialog.destroyed), (None, False))
      63  
      64      def test_ok_good(self):
      65          dialog = self.Dummy_Query('good')
      66          self.assertEqual(dialog.ok(), None)
      67          self.assertEqual((dialog.result, dialog.destroyed), ('good', True))
      68  
      69      def test_cancel(self):
      70          dialog = self.Dummy_Query('does not matter')
      71          self.assertEqual(dialog.cancel(), None)
      72          self.assertEqual((dialog.result, dialog.destroyed), (None, True))
      73  
      74  
      75  class ESC[4;38;5;81mSectionNameTest(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
      76      "Test SectionName subclass of Query."
      77  
      78      class ESC[4;38;5;81mDummy_SectionName:
      79          entry_ok = query.SectionName.entry_ok  # Function being tested.
      80          used_names = ['used']
      81          def __init__(self, dummy_entry):
      82              self.entry = Var(value=dummy_entry)
      83              self.entry_error = {'text': ''}
      84          def showerror(self, message):
      85              self.entry_error['text'] = message
      86  
      87      def test_blank_section_name(self):
      88          dialog = self.Dummy_SectionName(' ')
      89          self.assertEqual(dialog.entry_ok(), None)
      90          self.assertIn('no name', dialog.entry_error['text'])
      91  
      92      def test_used_section_name(self):
      93          dialog = self.Dummy_SectionName('used')
      94          self.assertEqual(dialog.entry_ok(), None)
      95          self.assertIn('use', dialog.entry_error['text'])
      96  
      97      def test_long_section_name(self):
      98          dialog = self.Dummy_SectionName('good'*8)
      99          self.assertEqual(dialog.entry_ok(), None)
     100          self.assertIn('longer than 30', dialog.entry_error['text'])
     101  
     102      def test_good_section_name(self):
     103          dialog = self.Dummy_SectionName('  good ')
     104          self.assertEqual(dialog.entry_ok(), 'good')
     105          self.assertEqual(dialog.entry_error['text'], '')
     106  
     107  
     108  class ESC[4;38;5;81mModuleNameTest(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
     109      "Test ModuleName subclass of Query."
     110  
     111      class ESC[4;38;5;81mDummy_ModuleName:
     112          entry_ok = query.ModuleName.entry_ok  # Function being tested.
     113          text0 = ''
     114          def __init__(self, dummy_entry):
     115              self.entry = Var(value=dummy_entry)
     116              self.entry_error = {'text': ''}
     117          def showerror(self, message):
     118              self.entry_error['text'] = message
     119  
     120      def test_blank_module_name(self):
     121          dialog = self.Dummy_ModuleName(' ')
     122          self.assertEqual(dialog.entry_ok(), None)
     123          self.assertIn('no name', dialog.entry_error['text'])
     124  
     125      def test_bogus_module_name(self):
     126          dialog = self.Dummy_ModuleName('__name_xyz123_should_not_exist__')
     127          self.assertEqual(dialog.entry_ok(), None)
     128          self.assertIn('not found', dialog.entry_error['text'])
     129  
     130      def test_c_source_name(self):
     131          dialog = self.Dummy_ModuleName('itertools')
     132          self.assertEqual(dialog.entry_ok(), None)
     133          self.assertIn('source-based', dialog.entry_error['text'])
     134  
     135      def test_good_module_name(self):
     136          dialog = self.Dummy_ModuleName('idlelib')
     137          self.assertTrue(dialog.entry_ok().endswith('__init__.py'))
     138          self.assertEqual(dialog.entry_error['text'], '')
     139          dialog = self.Dummy_ModuleName('idlelib.idle')
     140          self.assertTrue(dialog.entry_ok().endswith('idle.py'))
     141          self.assertEqual(dialog.entry_error['text'], '')
     142  
     143  
     144  class ESC[4;38;5;81mGotoTest(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
     145      "Test Goto subclass of Query."
     146  
     147      class ESC[4;38;5;81mDummy_ModuleName:
     148          entry_ok = query.Goto.entry_ok  # Function being tested.
     149          def __init__(self, dummy_entry):
     150              self.entry = Var(value=dummy_entry)
     151              self.entry_error = {'text': ''}
     152          def showerror(self, message):
     153              self.entry_error['text'] = message
     154  
     155      def test_bogus_goto(self):
     156          dialog = self.Dummy_ModuleName('a')
     157          self.assertEqual(dialog.entry_ok(), None)
     158          self.assertIn('not a base 10 integer', dialog.entry_error['text'])
     159  
     160      def test_bad_goto(self):
     161          dialog = self.Dummy_ModuleName('0')
     162          self.assertEqual(dialog.entry_ok(), None)
     163          self.assertIn('not a positive integer', dialog.entry_error['text'])
     164  
     165      def test_good_goto(self):
     166          dialog = self.Dummy_ModuleName('1')
     167          self.assertEqual(dialog.entry_ok(), 1)
     168          self.assertEqual(dialog.entry_error['text'], '')
     169  
     170  
     171  # 3 HelpSource test classes each test one method.
     172  
     173  class ESC[4;38;5;81mHelpsourceBrowsefileTest(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
     174      "Test browse_file method of ModuleName subclass of Query."
     175  
     176      class ESC[4;38;5;81mDummy_HelpSource:
     177          browse_file = query.HelpSource.browse_file
     178          pathvar = Var()
     179  
     180      def test_file_replaces_path(self):
     181          dialog = self.Dummy_HelpSource()
     182          # Path is widget entry, either '' or something.
     183          # Func return is file dialog return, either '' or something.
     184          # Func return should override widget entry.
     185          # We need all 4 combinations to test all (most) code paths.
     186          for path, func, result in (
     187                  ('', lambda a,b,c:'', ''),
     188                  ('', lambda a,b,c: __file__, __file__),
     189                  ('htest', lambda a,b,c:'', 'htest'),
     190                  ('htest', lambda a,b,c: __file__, __file__)):
     191              with self.subTest():
     192                  dialog.pathvar.set(path)
     193                  dialog.askfilename = func
     194                  dialog.browse_file()
     195                  self.assertEqual(dialog.pathvar.get(), result)
     196  
     197  
     198  class ESC[4;38;5;81mHelpsourcePathokTest(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
     199      "Test path_ok method of HelpSource subclass of Query."
     200  
     201      class ESC[4;38;5;81mDummy_HelpSource:
     202          path_ok = query.HelpSource.path_ok
     203          def __init__(self, dummy_path):
     204              self.path = Var(value=dummy_path)
     205              self.path_error = {'text': ''}
     206          def showerror(self, message, widget=None):
     207              self.path_error['text'] = message
     208  
     209      orig_platform = query.platform  # Set in test_path_ok_file.
     210      @classmethod
     211      def tearDownClass(cls):
     212          query.platform = cls.orig_platform
     213  
     214      def test_path_ok_blank(self):
     215          dialog = self.Dummy_HelpSource(' ')
     216          self.assertEqual(dialog.path_ok(), None)
     217          self.assertIn('no help file', dialog.path_error['text'])
     218  
     219      def test_path_ok_bad(self):
     220          dialog = self.Dummy_HelpSource(__file__ + 'bad-bad-bad')
     221          self.assertEqual(dialog.path_ok(), None)
     222          self.assertIn('not exist', dialog.path_error['text'])
     223  
     224      def test_path_ok_web(self):
     225          dialog = self.Dummy_HelpSource('')
     226          Equal = self.assertEqual
     227          for url in 'www.py.org', 'http://py.org':
     228              with self.subTest():
     229                  dialog.path.set(url)
     230                  self.assertEqual(dialog.path_ok(), url)
     231                  self.assertEqual(dialog.path_error['text'], '')
     232  
     233      def test_path_ok_file(self):
     234          dialog = self.Dummy_HelpSource('')
     235          for platform, prefix in ('darwin', 'file://'), ('other', ''):
     236              with self.subTest():
     237                  query.platform = platform
     238                  dialog.path.set(__file__)
     239                  self.assertEqual(dialog.path_ok(), prefix + __file__)
     240                  self.assertEqual(dialog.path_error['text'], '')
     241  
     242  
     243  class ESC[4;38;5;81mHelpsourceEntryokTest(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
     244      "Test entry_ok method of HelpSource subclass of Query."
     245  
     246      class ESC[4;38;5;81mDummy_HelpSource:
     247          entry_ok = query.HelpSource.entry_ok
     248          entry_error = {}
     249          path_error = {}
     250          def item_ok(self):
     251              return self.name
     252          def path_ok(self):
     253              return self.path
     254  
     255      def test_entry_ok_helpsource(self):
     256          dialog = self.Dummy_HelpSource()
     257          for name, path, result in ((None, None, None),
     258                                     (None, 'doc.txt', None),
     259                                     ('doc', None, None),
     260                                     ('doc', 'doc.txt', ('doc', 'doc.txt'))):
     261              with self.subTest():
     262                  dialog.name, dialog.path = name, path
     263                  self.assertEqual(dialog.entry_ok(), result)
     264  
     265  
     266  # 2 CustomRun test classes each test one method.
     267  
     268  class ESC[4;38;5;81mCustomRunCLIargsokTest(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
     269      "Test cli_ok method of the CustomRun subclass of Query."
     270  
     271      class ESC[4;38;5;81mDummy_CustomRun:
     272          cli_args_ok = query.CustomRun.cli_args_ok
     273          def __init__(self, dummy_entry):
     274              self.entry = Var(value=dummy_entry)
     275              self.entry_error = {'text': ''}
     276          def showerror(self, message):
     277              self.entry_error['text'] = message
     278  
     279      def test_blank_args(self):
     280          dialog = self.Dummy_CustomRun(' ')
     281          self.assertEqual(dialog.cli_args_ok(), [])
     282  
     283      def test_invalid_args(self):
     284          dialog = self.Dummy_CustomRun("'no-closing-quote")
     285          self.assertEqual(dialog.cli_args_ok(), None)
     286          self.assertIn('No closing', dialog.entry_error['text'])
     287  
     288      def test_good_args(self):
     289          args = ['-n', '10', '--verbose', '-p', '/path', '--name']
     290          dialog = self.Dummy_CustomRun(' '.join(args) + ' "my name"')
     291          self.assertEqual(dialog.cli_args_ok(), args + ["my name"])
     292          self.assertEqual(dialog.entry_error['text'], '')
     293  
     294  
     295  class ESC[4;38;5;81mCustomRunEntryokTest(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
     296      "Test entry_ok method of the CustomRun subclass of Query."
     297  
     298      class ESC[4;38;5;81mDummy_CustomRun:
     299          entry_ok = query.CustomRun.entry_ok
     300          entry_error = {}
     301          restartvar = Var()
     302          def cli_args_ok(self):
     303              return self.cli_args
     304  
     305      def test_entry_ok_customrun(self):
     306          dialog = self.Dummy_CustomRun()
     307          for restart in {True, False}:
     308              dialog.restartvar.set(restart)
     309              for cli_args, result in ((None, None),
     310                                       (['my arg'], (['my arg'], restart))):
     311                  with self.subTest(restart=restart, cli_args=cli_args):
     312                      dialog.cli_args = cli_args
     313                      self.assertEqual(dialog.entry_ok(), result)
     314  
     315  
     316  # GUI TESTS
     317  
     318  class ESC[4;38;5;81mQueryGuiTest(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
     319  
     320      @classmethod
     321      def setUpClass(cls):
     322          requires('gui')
     323          cls.root = root = Tk()
     324          cls.root.withdraw()
     325          cls.dialog = query.Query(root, 'TEST', 'test', _utest=True)
     326          cls.dialog.destroy = mock.Mock()
     327  
     328      @classmethod
     329      def tearDownClass(cls):
     330          del cls.dialog.destroy
     331          del cls.dialog
     332          cls.root.destroy()
     333          del cls.root
     334  
     335      def setUp(self):
     336          self.dialog.entry.delete(0, 'end')
     337          self.dialog.result = None
     338          self.dialog.destroy.reset_mock()
     339  
     340      def test_click_ok(self):
     341          dialog = self.dialog
     342          dialog.entry.insert(0, 'abc')
     343          dialog.button_ok.invoke()
     344          self.assertEqual(dialog.result, 'abc')
     345          self.assertTrue(dialog.destroy.called)
     346  
     347      def test_click_blank(self):
     348          dialog = self.dialog
     349          dialog.button_ok.invoke()
     350          self.assertEqual(dialog.result, None)
     351          self.assertFalse(dialog.destroy.called)
     352  
     353      def test_click_cancel(self):
     354          dialog = self.dialog
     355          dialog.entry.insert(0, 'abc')
     356          dialog.button_cancel.invoke()
     357          self.assertEqual(dialog.result, None)
     358          self.assertTrue(dialog.destroy.called)
     359  
     360  
     361  class ESC[4;38;5;81mSectionnameGuiTest(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
     362  
     363      @classmethod
     364      def setUpClass(cls):
     365          requires('gui')
     366  
     367      def test_click_section_name(self):
     368          root = Tk()
     369          root.withdraw()
     370          dialog =  query.SectionName(root, 'T', 't', {'abc'}, _utest=True)
     371          Equal = self.assertEqual
     372          self.assertEqual(dialog.used_names, {'abc'})
     373          dialog.entry.insert(0, 'okay')
     374          dialog.button_ok.invoke()
     375          self.assertEqual(dialog.result, 'okay')
     376          root.destroy()
     377  
     378  
     379  class ESC[4;38;5;81mModulenameGuiTest(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
     380  
     381      @classmethod
     382      def setUpClass(cls):
     383          requires('gui')
     384  
     385      def test_click_module_name(self):
     386          root = Tk()
     387          root.withdraw()
     388          dialog =  query.ModuleName(root, 'T', 't', 'idlelib', _utest=True)
     389          self.assertEqual(dialog.text0, 'idlelib')
     390          self.assertEqual(dialog.entry.get(), 'idlelib')
     391          dialog.button_ok.invoke()
     392          self.assertTrue(dialog.result.endswith('__init__.py'))
     393          root.destroy()
     394  
     395  
     396  class ESC[4;38;5;81mGotoGuiTest(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
     397  
     398      @classmethod
     399      def setUpClass(cls):
     400          requires('gui')
     401  
     402      def test_click_module_name(self):
     403          root = Tk()
     404          root.withdraw()
     405          dialog =  query.Goto(root, 'T', 't', _utest=True)
     406          dialog.entry.insert(0, '22')
     407          dialog.button_ok.invoke()
     408          self.assertEqual(dialog.result, 22)
     409          root.destroy()
     410  
     411  
     412  class ESC[4;38;5;81mHelpsourceGuiTest(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
     413  
     414      @classmethod
     415      def setUpClass(cls):
     416          requires('gui')
     417  
     418      def test_click_help_source(self):
     419          root = Tk()
     420          root.withdraw()
     421          dialog =  query.HelpSource(root, 'T', menuitem='__test__',
     422                                     filepath=__file__, _utest=True)
     423          Equal = self.assertEqual
     424          Equal(dialog.entry.get(), '__test__')
     425          Equal(dialog.path.get(), __file__)
     426          dialog.button_ok.invoke()
     427          prefix = "file://" if sys.platform == 'darwin' else ''
     428          Equal(dialog.result, ('__test__', prefix + __file__))
     429          root.destroy()
     430  
     431  
     432  class ESC[4;38;5;81mCustomRunGuiTest(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
     433  
     434      @classmethod
     435      def setUpClass(cls):
     436          requires('gui')
     437  
     438      def test_click_args(self):
     439          root = Tk()
     440          root.withdraw()
     441          dialog =  query.CustomRun(root, 'Title',
     442                                    cli_args=['a', 'b=1'], _utest=True)
     443          self.assertEqual(dialog.entry.get(), 'a b=1')
     444          dialog.entry.insert(END, ' c')
     445          dialog.button_ok.invoke()
     446          self.assertEqual(dialog.result, (['a', 'b=1', 'c'], True))
     447          root.destroy()
     448  
     449  
     450  if __name__ == '__main__':
     451      unittest.main(verbosity=2, exit=False)