test/guitest.py (6471B) - raw
1 #!/usr/bin/env python 2 3 import sys 4 import os 5 import time 6 import struct 7 import tempfile 8 import subprocess 9 import Xlib.display 10 import dogtail.tree 11 import unittest 12 13 def extract_xmp(path): 14 popen = subprocess.Popen([ 15 os.path.join('target', 'printxmp'), path], 16 stdout=subprocess.PIPE) 17 stdout, stderr = popen.communicate() 18 assert popen.returncode == 0 19 return stdout.decode('utf8') 20 21 class XmpeditTestCase(unittest.TestCase): 22 23 def start(self, image_filename): 24 self.tempfile = tempfile.NamedTemporaryFile() 25 self.tempfile.write(open(os.path.join('testdata', image_filename)).read()) 26 self.tempfile.flush() 27 self.tempfile.seek(0) 28 self.popen = subprocess.Popen( 29 [os.path.join('target', 'xmpedit'), self.tempfile.name], 30 env=dict(os.environ.items() + [ 31 ('G_DEBUG', 'fatal_criticals'), 32 ('G_SLICE', 'debug-blocks'), 33 ('GNOME_DISABLE_CRASH_DIALOG', '1') 34 ])) 35 36 def stop(self): 37 if self.popen.returncode is None: 38 print 'Terminating process under test' 39 self.popen.terminate() 40 self.popen.wait() 41 42 def assert_stopped(self): 43 for _ in range(3): 44 if self.popen.poll() is not None: 45 assert self.popen.returncode == 0 46 return 47 time.sleep(1) 48 assert False, 'Process did not end' 49 50 def assert_image_unmodified(self, image_filename): 51 self.tempfile.seek(0) 52 assert self.tempfile.read() == open(os.path.join('testdata', image_filename)).read(), 'Image should be unmodified' 53 54 def get_window(self): 55 root = Xlib.display.Display().screen().root # XXX multiple screens? 56 for child in root.query_tree().children: 57 if child.get_wm_class() is not None and 'xmpedit' in child.get_wm_class(): 58 return child 59 60 def close_window(self): 61 window = self.get_window() 62 assert window is not None, "Where'd the window go?" 63 WM_PROTOCOLS = window.display.get_atom('WM_PROTOCOLS') 64 WM_DELETE_WINDOW = window.display.get_atom('WM_DELETE_WINDOW') 65 assert WM_DELETE_WINDOW in window.get_wm_protocols() 66 event = Xlib.protocol.event.ClientMessage(window=window, client_type=WM_PROTOCOLS, 67 data=(32, struct.pack('=lllll', WM_DELETE_WINDOW, 0, 0, 0, 0))) 68 window.send_event(event) 69 window.display.flush() 70 71 class Test(XmpeditTestCase): 72 73 def setUp(self): 74 self.start('24-06-06_1449.jpg') 75 76 def tearDown(self): 77 self.stop() 78 79 def test_do_nothing(self): 80 xmpedit = dogtail.tree.Root().application('xmpedit') 81 window = xmpedit.child(roleName='frame') 82 self.close_window() 83 self.assert_stopped() 84 self.assert_image_unmodified('24-06-06_1449.jpg') 85 86 def test_close_without_saving(self): 87 xmpedit = dogtail.tree.Root().application('xmpedit') 88 window = xmpedit.child(roleName='frame') 89 pe, = [child for child in window.child('Image properties').children 90 if child.name.splitlines()[0] == 'Description'] # ugh 91 pe.select() 92 entry = window.child(roleName='ROLE_TEXT', label='Description') 93 entry.grabFocus() 94 entry.text = 'new description' 95 lang = window.child(roleName='ROLE_TEXT', label='Language:') 96 lang.text = 'en' 97 self.close_window() 98 alert = xmpedit.child(roleName='alert') 99 self.assertEquals(alert.child(roleName='label').name, 100 'Your changes to image "%s" have not been saved.\n\nSave changes before closing?' 101 % os.path.basename(self.tempfile.name)) 102 alert.button('Close without saving').doAction('click') 103 self.assert_stopped() 104 self.assert_image_unmodified('24-06-06_1449.jpg') 105 106 def test_edit_then_revert(self): 107 xmpedit = dogtail.tree.Root().application('xmpedit') 108 window = xmpedit.child(roleName='frame') 109 pe, = [child for child in window.child('Image properties').children 110 if child.name.splitlines()[0] == 'Description'] # ugh 111 pe.select() 112 entry = window.child(roleName='ROLE_TEXT', label='Description') 113 entry.grabFocus() 114 entry.text = 'new description' 115 lang = window.child(roleName='ROLE_TEXT', label='Language:') 116 lang.text = 'en' 117 assert window.button('Revert').sensitive 118 window.button('Revert').doAction('click') 119 entry = window.child(roleName='ROLE_TEXT', label='Description') 120 self.assertEquals(entry.text, 'Edward Scissorhands stencil graffiti ' 121 'on the wall of John Hines building.') 122 lang = window.child(roleName='ROLE_TEXT', label='Language:') 123 self.assertEquals(lang.text, 'x-default') 124 self.close_window() 125 self.assert_stopped() 126 self.assert_image_unmodified('24-06-06_1449.jpg') 127 128 def test_update_description(self): 129 xmpedit = dogtail.tree.Root().application('xmpedit') 130 window = xmpedit.child(roleName='frame') 131 pe, = [child for child in window.child('Image properties').children 132 if child.name.splitlines()[0] == 'Description'] # ugh 133 pe.select() 134 entry = window.child(roleName='ROLE_TEXT', label='Description') 135 entry.grabFocus() 136 entry.text = 'new description' 137 lang = window.child(roleName='ROLE_TEXT', label='Language:') 138 lang.text = 'en' 139 assert window.button('Save').sensitive 140 window.button('Save').doAction('click') 141 self.close_window() 142 self.assert_stopped() 143 xmp = extract_xmp(self.tempfile.name) 144 self.assertEquals(len(xmp), 2675) 145 self.assertEquals(extract_xmp(self.tempfile.name), 146 u'''<?xpacket begin="\ufeff" id="W5M0MpCehiHzreSzNTczkc9d"?><x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="xmpedit 0.0-dev"><rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"><rdf:Description rdf:about=""><Iptc4xmlCore:Location xmlns:Iptc4xmlCore="http://iptc.org/std/Iptc4xmpCore/1.0/xmlns/">UQ St Lucia</Iptc4xmlCore:Location><dc:description xmlns:dc="http://purl.org/dc/elements/1.1/"><rdf:Alt><rdf:li xml:lang="en">new description</rdf:li></rdf:Alt></dc:description></rdf:Description></rdf:RDF></x:xmpmeta>''' + ' ' * 2143 + '''<?xpacket end="w"?>''') 147 148 if __name__ == '__main__': 149 unittest.main()