diff -r 2c124e30a324 Lib/idlelib/idle_test/idletestcase.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Lib/idlelib/idle_test/idletestcase.py Tue Aug 11 13:33:56 2015 -0700 @@ -0,0 +1,20 @@ +"""Define some IDLE-specific support routines on top of the more generic + TkTestCase. +""" +from idlelib.idle_test.tktestcase import TkTestCase, requires_mac +from idlelib.EditorWindow import EditorWindow +import idlelib.uifactory + + +class IdleTestCase(TkTestCase): + + def open_editwindow(self): + idlelib.uifactory.initialize(self.root) + self.root.wm_withdraw() + self.ed = EditorWindow(root=self.root) + self.text = self.getWidget('text') + self.waitForExists('toplevel', title='Untitled', viewable=1) + self.topwin = self.getWidget('toplevel', title='Untitled') + + def close_editwindow(self): + self.ed._close() diff -r 2c124e30a324 Lib/idlelib/idle_test/test_about.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Lib/idlelib/idle_test/test_about.py Tue Aug 11 13:33:56 2015 -0700 @@ -0,0 +1,48 @@ +"Functional tests for about dialog" + + +from idlelib.idle_test.idletestcase import IdleTestCase + + +class AboutTest(IdleTestCase): + + def setUp(self): + self.open_editwindow() + + def tearDown(self): + self.close_editwindow() + + def test_basics(self): + self.text.event_generate('<>') + self.waitForExists('toplevel', title='About IDLE') + self.assertExists('label', text='More...', viewable=1) + abt = self.getWidget('toplevel', title='About IDLE') + self.assertEqual(self.root.tk.eval('wm stackorder ' + str(abt) + + ' isabove '+str(self.topwin)), '1') + self.assertNotExists('menubutton') + self.getWidget('label', text='More...').event_generate('<1>') + self.waitForExists('label', text='More...', viewable=0) + self.assertExists('menubutton', text='IDLE Readme') + txt = self.getWidget('text', toplevel='About IDLE') + self.assertRegex(txt.get('1.0','end'), "IDLE is Python's") + mb = self.getWidget('menubutton', toplevel='About IDLE') + mb['menu'].invoke(4) + self.assertEqual(mb['text'], 'Python Copyright') + self.assertNotRegex(txt.get('1.0','end'), "IDLE is Python's") + self.assertRegex(txt.get('1.0','end'), + "Corporation for National Research Initiatives") + abt.close() + + def test_not_modal(self): + self.text.event_generate('<>') + self.waitForExists('toplevel', title='About IDLE', viewable=1) + abt = self.getWidget('toplevel', title='About IDLE') + self.assertEqual(self.root.tk.eval('wm stackorder ' + str(abt) + + ' isabove '+str(self.topwin)), '1') + self.text.event_generate('<1>') + self.assertEqual(self.root.tk.eval('wm stackorder ' + str(abt) + + ' isbelow '+str(self.topwin)), '1') + abt.close() + +if __name__ == '__main__': + IdleTestCase.main(verbosity=2) diff -r 2c124e30a324 Lib/idlelib/idle_test/test_editorwindow.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Lib/idlelib/idle_test/test_editorwindow.py Tue Aug 11 13:33:56 2015 -0700 @@ -0,0 +1,29 @@ +"Functional tests for main editor window" + + +from idlelib.idle_test.idletestcase import IdleTestCase + + +class EditorWindowTest(IdleTestCase): + + def setUp(self): + self.open_editwindow() + + def tearDown(self): + self.close_editwindow() + + def test_mainwindow_appearance(self): # Issue 24750 + self.assertExists('toplevel', title='Untitled') + self.assertExists('text', highlightthickness=0) + self.assertNotExists('label', text='Col: 0', relief='sunken') + self.assertExists('separator') + # TODO - status bar not same color as text widget + # TODO - scrollbar + + def test_no_tearoff(self): # Issue 13884 + self.assertExists('menu', tearoff=0) + self.assertNotExists('menu', tearoff=1) + + +if __name__ == '__main__': + IdleTestCase.main(verbosity=2) diff -r 2c124e30a324 Lib/idlelib/idle_test/test_finddialogs.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Lib/idlelib/idle_test/test_finddialogs.py Tue Aug 11 13:33:56 2015 -0700 @@ -0,0 +1,32 @@ +"Functional tests for find dialogs" + +from idlelib.idle_test.idletestcase import IdleTestCase + + +class FindDialogsTest(IdleTestCase): + + def setUp(self): + self.open_editwindow() + + def tearDown(self): + self.close_editwindow() + + def test_find(self): + self.text.insert('1.0', 'once upon a time\nthere was a nice\nstory.') + self.text.event_generate('<>', when='tail') + self.waitForExists('toplevel', title='Search Dialog', viewable=1) + self.assertExists('button', text='close') # TODO - should be Close + self.assertExists('button', text='Find Next') + entry = self.getWidget('entry') + self.assertEqual(entry.get(), '') + entry.insert(0, 'c') + entry.event_generate('') + start, end = self.text.tag_ranges('sel') + self.assertEqual(str(start), '1.2') + self.assertEqual(str(end), '1.3') + entry.event_generate('') + self.waitForExists('toplevel', title='Search Dialog', viewable=0) + + +if __name__ == '__main__': + IdleTestCase.main(verbosity=2) diff -r 2c124e30a324 Lib/idlelib/idle_test/tktestcase.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Lib/idlelib/idle_test/tktestcase.py Tue Aug 11 13:33:56 2015 -0700 @@ -0,0 +1,131 @@ +import unittest +from test.support import requires, ResourceDenied +from tkinter import Tk +from idlelib.macosxSupport import _initializeTkVariantTests +import re +import sys + + +class TkTestCase(unittest.TestCase): + """ + Helpers for functional testing of Tkinter applications + """ + @classmethod + def setUpClass(cls): + requires('gui') + cls.root = Tk() + _initializeTkVariantTests(cls.root) + + @classmethod + def tearDownClass(cls): + cls.root.destroy() + del cls.root + + @classmethod + def main(cls, **kwargs): + unittest.main(**kwargs) + + def allwidgets(self): + return self._allwidgets(self.root) + + def _allwidgets(self, parent): + wlist = [parent] + for w in parent.winfo_children(): + wlist += self._allwidgets(w) + return wlist + + def _widgetMatches(self, w, widgetclass, matchopts): + wtype = self._widgetType(w) + if (wtype != '*' and wtype != widgetclass): + return False + for k, val in matchopts.items(): + if (wtype == "toplevel" and k == "title"): + actual = w.wm_title() + elif k == 'viewable': + actual = w.winfo_viewable() + elif k == 'toplevel': + actual = w.winfo_toplevel().wm_title() + else: + actual = w.cget(k) + if (actual != val): + return False + return True + + def getWidget(self, widgetclass, **kwargs): + for w in self.allwidgets(): + if (self._widgetMatches(w, widgetclass, kwargs)): + return w + return None + + def assertExists(self, widgetclass, **kwargs): + if self.getWidget(widgetclass, **kwargs): + return + raise AssertionError("widget not found") + + def assertNotExists(self, widgetclass, **kwargs): + if self.getWidget(widgetclass, **kwargs): + raise AssertionError("widget found") + return + + def assertVisible(self, widgetclass, **kwargs): + kwargs['viewable'] = 1 + self.assertExists(widgetclass, **kwargs) + + def countMatches(self, widgetclass, **kwargs): + count = 0 + for w in self.allwidgets(): + if (self._widgetMatches(w, widgetclass, kwargs)): + count += 1 + return count + + def waitForExists(self, widgetclass, **kwargs): + for i in range(2000): # TODO change to use elapsed time + self.root.update() + self.root.update_idletasks() + try: + self.assertExists(widgetclass, **kwargs) + return + except AssertionError: + pass + raise Timeout("wait condition never satisfied") + + def waitForNotExists(self, widgetclass, **kwargs): + for i in range(2000): # TODO change to use elapsed time + self.root.update() + self.root.update_idletasks() + try: + self.assertNotExists(widgetclass, **kwargs) + return + except AssertionError: + pass + raise Timeout("wait condition never satisfied") + + def runModalTest(self, modal_cmd, modal_testcmd): + exc = None + def runmodal(): + try: + modal_testcmd() + except Exception as e: + exc = e + self.root.after_idle(runmodal) + modal_cmd() + if exc is not None: + raise exc + + def _widgetType(self, w): + cls = w.winfo_class() + if re.match("^T[A-Z]", cls): + cls = cls[1:] + return cls.lower() + +class Timeout(Exception): + pass + +def requires_mac(): + if sys.platform != 'darwin': + raise ResourceDenied("Not on Mac OS X") + +def requires_windows(): + if sys.platform[:3] != 'win': + raise ResourceDenied("Not on Windows") +