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")
+