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()