modinfo in the translate toolkit is now a 2-tuple containing the mtime and
[pootle.git] / test_client.py
blob49f4b60d5280482c262479be42b6bf595813de3d
1 #!/usr/bin/env python
3 """Top-level tests using urllib2 to check interaction with servers
4 This uses test_cmdlineserver / test_service / test_apache (which are for different webservers)
5 ServerTester is mixed in with the different server tests below to generate the required tests"""
7 from Pootle import test_create
8 from Pootle import test_cmdlineserver
9 from Pootle import potree
10 from Pootle import projects
11 from jToolkit.web import postMultipart
12 import zipfile
13 from translate.misc import wStringIO
14 import urllib
15 import urllib2
16 import os
17 import re
19 try:
20 import cookielib
21 except ImportError:
22 # fallback for python before 2.4
23 cookielib = None
24 import ClientCookie
26 class ServerTester:
27 """Tests things directly against the socket of the server. Requires self.baseaddress"""
28 setup_class = test_create.TestCreate.setup_class
30 def setup_cookies(self):
31 """handle cookies etc"""
32 if cookielib:
33 self.cookiejar = cookielib.CookieJar()
34 self.opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(self.cookiejar))
35 self.urlopen = self.opener.open
36 else:
37 self.urlopen = ClientCookie.urlopen
39 def setup_prefs(self, method):
40 """sets up any extra preferences required..."""
41 if hasattr(method, "userprefs"):
42 for key, value in method.userprefs.iteritems():
43 self.prefs.setvalue("Pootle.users.testuser." + key, value)
45 def fetch_page(self, relative_url):
46 """Fetches a page from the webserver installed in the service"""
47 url = "%s/%s" % (self.baseaddress, relative_url)
48 print "fetching", url
49 stream = self.urlopen(url)
50 contents = stream.read()
51 return contents
53 def post_request(self, relative_url, contents, headers):
54 """Posts a request to the webserver installed in the service"""
55 url = "%s/%s" % (self.baseaddress, relative_url)
56 print "posting to", url
57 post_request = urllib2.Request(url, contents, headers)
58 stream = self.urlopen(post_request)
59 response = stream.read()
60 return response
62 def login(self):
63 """calls the login method with username and password"""
64 return self.fetch_page("?islogin=1&username=testuser&password=")
66 def test_login(self):
67 """checks that login works and sets cookies"""
68 contents = self.login()
69 # check login leads us to a normal page
70 assert "Log In" not in contents
71 # check login is retained on next fetch
72 contents = self.fetch_page("")
73 assert "Log In" not in contents
75 def test_non_admin_rights(self):
76 """checks that without admin rights we can't access the admin screen"""
77 contents = self.login()
78 adminlink = '<a href="/admin/">Admin</a>' in contents
79 assert not adminlink
80 contents = self.fetch_page("admin/")
81 denied = "You do not have the rights to administer pootle" in contents
82 assert denied
84 def test_admin_rights(self):
85 """checks that admin rights work properly"""
86 contents = self.login()
87 adminlink = '<a href="/admin/">Admin</a>' in contents
88 assert adminlink
89 contents = self.fetch_page("admin/")
90 admintitle = "<title>Pootle Admin Page</title>" in contents
91 assert admintitle
92 test_admin_rights.userprefs = {"rights.siteadmin": True}
94 def test_add_project(self):
95 """checks that we can add a project successfully"""
96 self.login()
97 projects_list = self.fetch_page("admin/projects.html")
98 testproject_present = '<a href="../projects/testproject/admin.html">testproject</a>' in projects_list
99 assert testproject_present
100 testproject2_present = '<a href="../projects/testproject2/admin.html">testproject2</a>' in projects_list
101 assert not testproject2_present
102 assert projects_list.count(""""selected" value="po""") == 1
103 add_dict = {"newprojectcode": "testproject2", "newprojectname": "Test Project 2",
104 "newprojectdescription": "Test Project Addition","newprojectfiletype": "xliff", "changeprojects": "Save changes"}
105 add_args = "&".join(["%s=%s" % (key, urllib.quote_plus(value)) for key, value in add_dict.items()])
106 add_url = "admin/projects.html?" + add_args
107 add_result = self.fetch_page(add_url)
108 testproject2_present = '<a href="../projects/testproject2/admin.html">testproject2</a>' in add_result
109 assert testproject2_present
110 projects_list = self.fetch_page("admin/projects.html")
111 # The asserts below may fail if output framework changes, html checking does not checking the 'selected' value,
112 # but instead relying on the projected 'value' in the project's name
113 assert """projectfiletype-testproject" value="po">""" in projects_list
114 assert """projectfiletype-testproject2" value="xliff">""" in projects_list
115 test_add_project.userprefs = {"rights.siteadmin": True}
117 def test_add_project_language(self):
118 """tests that we can add a language to a project, then access its page when there are no files"""
119 self.login()
120 language_list = self.fetch_page("projects/testproject/")
121 assert "Test Language" not in language_list
122 assert "Pootle Unit Tests" in language_list
123 project_admin = self.fetch_page("projects/testproject/admin.html")
124 assert '<option value="zxx">Test Language: zxx</option>' in project_admin
125 add_dict = {"newlanguage": "zxx", "doaddlanguage": "Add Language"}
126 add_args = "&".join(["%s=%s" % (key, urllib.quote_plus(value)) for key, value in add_dict.items()])
127 add_language = self.fetch_page("projects/testproject/admin.html?" + add_args)
128 assert "Test Language" in add_language
129 language_page = self.fetch_page("zxx/testproject/")
130 assert "Test Language" in language_page
131 assert "Pootle Unit Tests" in language_page
132 assert "0 files, 0/0 words (0%) translated" in language_page
133 test_add_project_language.userprefs = {"rights.siteadmin": True}
135 def setup_testproject_dir(self, perms=None):
136 """Sets up a blank test project directory"""
137 projectname = "testproject"
138 lang = "zxx"
139 projectdir = os.path.join(self.podir, projectname)
140 os.mkdir(projectdir)
141 podir = os.path.join(projectdir, lang)
142 os.mkdir(podir)
143 if perms:
144 prefsfile = file(os.path.join(projectdir, lang, "pootle-%s-%s.prefs" % (projectname, lang)), 'w')
145 prefsfile.write("# Prefs file for Pootle unit tests\nrights:\n testuser = '%s'\n" % perms)
146 prefsfile.close()
147 language_page = self.fetch_page("%s/%s/" % (lang, projectname))
149 assert "Test Language" in language_page
150 assert "Pootle Unit Tests" in language_page
151 assert "0 files, 0/0 words (0%) translated" in language_page
152 return podir
154 def test_upload_new_file(self):
155 """tests that we can upload a new file into a project"""
156 self.login()
157 podir = self.setup_testproject_dir(perms="view, translate, admin")
158 fields = [("doupload", "Upload File")]
159 pocontents = '#: test.c\nmsgid "test"\nmsgstr "rest"\n'
160 files = [("uploadfile", "test_upload.po", pocontents)]
161 content_type, upload_contents = postMultipart.encode_multipart_formdata(fields, files)
162 headers = {"Content-Type": content_type, "Content-Length": len(upload_contents)}
163 response = self.post_request("zxx/testproject/", upload_contents, headers)
164 assert ' href="test_upload.po?' in response
165 pofile_storename = os.path.join(podir, "test_upload.po")
166 assert os.path.isfile(pofile_storename)
167 assert open(pofile_storename).read() == pocontents
168 pocontents_download = self.fetch_page("zxx/testproject/test_upload.po")
169 assert pocontents_download == pocontents
171 def test_upload_new_xlifffile(self):
172 """tests that we can upload a new xliff file into a project"""
173 self.login()
174 podir = self.setup_testproject_dir(perms="view, translate, admin")
175 fields = [("doupload", "Upload File")]
176 xliffcontents = '''<?xml version="1.0" encoding="utf-8"?>
177 <xliff version="1.1" xmlns="urn:oasis:names:tc:xliff:document:1.1"><file datatype="po" original="test_upload.po" source-language="en-US"><body><trans-unit id="1" xml:space="preserve"><source>test</source><target state="translated">rest</target><context-group name="po-reference" purpose="location"><context context-type="sourcefile">test.c</context></context-group></trans-unit></body></file></xliff>'''
178 pocontents_expected = '#: test.c\nmsgid "test"\nmsgstr "rest"\n'
179 files = [("uploadfile", "test_upload.xlf", xliffcontents)]
180 content_type, upload_contents = postMultipart.encode_multipart_formdata(fields, files)
181 headers = {"Content-Type": content_type, "Content-Length": len(upload_contents)}
182 response = self.post_request("zxx/testproject/", upload_contents, headers)
183 assert ' href="test_upload.po?' in response
184 pofile_storename = os.path.join(podir, "test_upload.po")
185 assert os.path.isfile(pofile_storename)
186 assert open(pofile_storename).read() == xliffcontents
187 # Well, since it is a new file, it actually now is an xliff file...
188 # pocontents_download = self.fetch_page("zxx/testproject/test_upload.po")
189 # assert pocontents_download == pocontents_expected
191 def test_upload_suggestions(self):
192 """tests that we can upload when we only have suggest rights"""
193 self.login()
194 podir = self.setup_testproject_dir(perms="view, suggest")
196 tree = potree.POTree(self.prefs.Pootle)
197 project = projects.TranslationProject("zxx", "testproject", tree)
198 po1contents = '#: test.c\nmsgid "test"\nmsgstr ""\n'
199 open(os.path.join(podir, "test_upload.po"), "w").write(po1contents)
201 fields = [("doupload", "Upload File")]
202 pocontents = '#: test.c\nmsgid "test"\nmsgstr "rest"\n'
203 files = [("uploadfile", "test_upload.po", pocontents)]
204 content_type, upload_contents = postMultipart.encode_multipart_formdata(fields, files)
205 headers = {"Content-Type": content_type, "Content-Length": len(upload_contents)}
206 response = self.post_request("zxx/testproject/", upload_contents, headers)
207 assert ' href="test_upload.po?' in response
208 # Check that the orignal file didn't take the new suggestion.
209 # We test with 'in' since the header is added
210 assert po1contents in self.fetch_page("zxx/testproject/test_upload.po")
211 suggestions_content = open(os.path.join(podir, "test_upload.po.pending"), 'r').read()
212 assert 'msgstr "rest"' in suggestions_content
213 test_upload_suggestions.userprefs = {"rights.siteadmin": False}
215 def test_upload_overwrite(self):
216 """tests that we can overwrite a file in a project"""
217 self.login()
218 podir = self.setup_testproject_dir(perms="view, translate, overwrite")
220 tree = potree.POTree(self.prefs.Pootle)
221 project = projects.TranslationProject("zxx", "testproject", tree)
222 po1contents = '#: test.c\nmsgid "test"\nmsgstr ""\n'
223 open(os.path.join(podir, "test_upload.po"), "w").write(po1contents)
225 fields = [("doupload", "Upload File"),("dooverwrite", "No")]
226 pocontents = '#: test.c\nmsgid "test"\nmsgstr "rest"\n'
227 files = [("uploadfile", "test_upload.po", pocontents)]
228 content_type, upload_contents = postMultipart.encode_multipart_formdata(fields, files)
229 headers = {"Content-Type": content_type, "Content-Length": len(upload_contents)}
230 response = self.post_request("zxx/testproject/", upload_contents, headers)
231 assert ' href="test_upload.po?' in response
232 # Now we only test with 'in' since the header is added
233 assert pocontents in self.fetch_page("zxx/testproject/test_upload.po")
234 firstpofile = self.fetch_page("zxx/testproject/test_upload.po")
236 fields = [("doupload", "Upload File"),("dooverwrite", "Yes")]
237 pocontents = '#: test.c\nmsgid "test"\nmsgstr "rest"\n#: test.c\nmsgid "azoozoo"\nmsgstr ""'
238 files = [("uploadfile", "test_upload.po", pocontents)]
239 content_type, upload_contents = postMultipart.encode_multipart_formdata(fields, files)
240 headers = {"Content-Type": content_type, "Content-Length": len(upload_contents)}
241 response = self.post_request("zxx/testproject/", upload_contents, headers)
242 assert pocontents == self.fetch_page("zxx/testproject/test_upload.po")
244 def test_upload_new_archive(self):
245 """tests that we can upload a new archive of files into a project"""
246 self.login()
247 podir = self.setup_testproject_dir(perms="view, translate, admin")
248 fields = [("doupload", "Upload File")]
249 po1contents = '#: test.c\nmsgid "test"\nmsgstr "rest"\n'
250 po2contents = '#: frog.c\nmsgid "tadpole"\nmsgstr "fish"\n'
251 archivefile = wStringIO.StringIO()
252 archive = zipfile.ZipFile(archivefile, "w", zipfile.ZIP_DEFLATED)
253 archive.writestr("test.po", po1contents)
254 archive.writestr("frog.po", po2contents)
255 archive.close()
256 files = [("uploadfile", "upload.zip", archivefile.getvalue())]
257 content_type, upload_contents = postMultipart.encode_multipart_formdata(fields, files)
258 headers = {"Content-Type": content_type, "Content-Length": len(upload_contents)}
259 response = self.post_request("zxx/testproject/", upload_contents, headers)
260 for filename, contents in [("test.po", po1contents), ("frog.po", po2contents)]:
261 assert (' href="%s?' % filename) in response
262 pofile_storename = os.path.join(podir, filename)
263 assert os.path.isfile(pofile_storename)
264 assert open(pofile_storename).read() == contents
265 pocontents_download = self.fetch_page("zxx/testproject/%s" % filename)
266 assert pocontents_download == contents
268 def test_upload_over_file(self):
269 """tests that we can upload a new version of a file into a project"""
270 self.login()
271 podir = self.setup_testproject_dir(perms="view, translate")
272 tree = potree.POTree(self.prefs.Pootle)
273 project = projects.TranslationProject("zxx", "testproject", tree)
274 po1contents = '#: test.c\nmsgid "test"\nmsgstr "rest"\n\n#: frog.c\nmsgid "tadpole"\nmsgstr "fish"\n'
275 open(os.path.join(podir, "test_existing.po"), "w").write(po1contents)
276 po2contents = '#: test.c\nmsgid "test"\nmsgstr "rested"\n\n#: toad.c\nmsgid "slink"\nmsgstr "stink"\n'
277 fields = [("doupload", "Upload File")]
278 files = [("uploadfile", "test_existing.po", po2contents)]
279 content_type, upload_contents = postMultipart.encode_multipart_formdata(fields, files)
280 headers = {"Content-Type": content_type, "Content-Length": len(upload_contents)}
281 response = self.post_request("zxx/testproject/?editing=1", upload_contents, headers)
282 # NOTE: this is what we do currently, any altered strings become suggestions.
283 # It may be a good idea to change this
284 mergedcontents = '#: test.c\nmsgid "test"\nmsgstr "rest"\n\n#: frog.c\nmsgid "tadpole"\nmsgstr "fish"\n\n#: toad.c\nmsgid "slink"\nmsgstr "stink"\n'
285 suggestedcontents = '#: test.c\nmsgid ""\n"_: suggested by testuser\\n"\n"test"\nmsgstr "rested"\n'
286 assert ' href="test_existing.po?' in response
287 pofile_storename = os.path.join(podir, "test_existing.po")
288 assert os.path.isfile(pofile_storename)
289 assert open(pofile_storename).read().find(mergedcontents) >= 0
290 pendingfile_storename = os.path.join(podir, "test_existing.po.pending")
291 assert os.path.isfile(pendingfile_storename)
292 assert open(pendingfile_storename).read().find(suggestedcontents) >= 0
293 pocontents_download = self.fetch_page("zxx/testproject/test_existing.po")
294 assert pocontents_download.find(mergedcontents) >= 0
295 test_upload_over_file.userprefs = {"rights.siteadmin": True}
297 def test_upload_xliff_over_file(self):
298 """tests that we can upload a new version of a file into a project"""
299 self.login()
300 podir = self.setup_testproject_dir(perms="view, translate")
301 tree = potree.POTree(self.prefs.Pootle)
302 project = projects.TranslationProject("zxx", "testproject", tree)
303 pocontents = '#: test.c\nmsgid "test"\nmsgstr "rest"\n\n#: frog.c\nmsgid "tadpole"\nmsgstr "fish"\n'
304 open(os.path.join(podir, "test_existing.po"), "w").write(pocontents)
305 xlfcontents = '''<?xml version="1.0" encoding="utf-8"?>
306 <xliff version="1.1" xmlns="urn:oasis:names:tc:xliff:document:1.1">
308 <file datatype="po" original="test_existing.po" source-language="en-US"><body>
309 <trans-unit id="1" xml:space="preserve" approved="yes">
310 <source>test</source>
311 <target state="translated">rested</target>
312 <context-group name="po-reference" purpose="location">
313 <context context-type="sourcefile">test.c</context>
314 </context-group>
315 </trans-unit>
316 <trans-unit id="2" xml:space="preserve" approved="yes">
317 <source>slink</source>
318 <target state="translated">stink</target>
319 <context-group name="po-reference" purpose="location">
320 <context context-type="sourcefile">toad.c</context>
321 </context-group>
322 </trans-unit>
323 </body></file></xliff>
325 fields = [("doupload", "Upload File")]
326 files = [("uploadfile", "test_existing.xlf", xlfcontents)]
327 content_type, upload_contents = postMultipart.encode_multipart_formdata(fields, files)
328 headers = {"Content-Type": content_type, "Content-Length": len(upload_contents)}
329 response = self.post_request("zxx/testproject/?editing=1", upload_contents, headers)
330 # NOTE: this is what we do currently, any altered strings become suggestions.
331 # It may be a good idea to change this
332 mergedcontents = '#: test.c\nmsgid "test"\nmsgstr "rest"\n\n#: frog.c\nmsgid "tadpole"\nmsgstr "fish"\n\n#: toad.c\nmsgid "slink"\nmsgstr "stink"\n'
333 suggestedcontents = '#: test.c\nmsgid ""\n"_: suggested by testuser\\n"\n"test"\nmsgstr "rested"\n'
334 assert ' href="test_existing.po?' in response
335 pofile_storename = os.path.join(podir, "test_existing.po")
336 assert os.path.isfile(pofile_storename)
337 assert open(pofile_storename).read().find(mergedcontents) >= 0
338 pendingfile_storename = os.path.join(podir, "test_existing.po.pending")
339 assert os.path.isfile(pendingfile_storename)
340 assert open(pendingfile_storename).read().find(suggestedcontents) >= 0
341 pocontents_download = self.fetch_page("zxx/testproject/test_existing.po")
342 assert pocontents_download.find(mergedcontents) >= 0
343 test_upload_xliff_over_file.userprefs = {"rights.siteadmin": True}
345 def test_submit_translation(self):
346 """tests that we can upload a new file into a project"""
347 self.login()
348 podir = self.setup_testproject_dir(perms="view, translate")
349 pofile_storename = os.path.join(podir, "test_upload.po")
350 pocontents = '#: test.c\nmsgid "test"\nmsgstr "rest"\n'
351 open(pofile_storename, "w").write(pocontents)
352 expected_pocontents = '#: test.c\nmsgid "test"\nmsgstr "restrain"\n'
353 fields = {"orig-pure0.0": "test", "trans0": "restrain", "submit0": "submit", "pofilename": "test_upload.po"}
354 content_type, post_contents = postMultipart.encode_multipart_formdata(fields.items(), [])
355 headers = {"Content-Type": content_type, "Content-Length": len(post_contents)}
356 translatepage = self.post_request("zxx/testproject/test_upload.po?translate=1&editing=1", post_contents, headers)
357 tree = potree.POTree(self.prefs.Pootle)
358 project = projects.TranslationProject("zxx", "testproject", tree)
359 pofile = project.getpofile("test_upload.po")
360 assert str(pofile.units[1]) == expected_pocontents
362 def test_submit_plural_translation(self):
363 """tests that we can submit a translation with plurals"""
364 self.login()
365 podir = self.setup_testproject_dir(perms="view, translate")
366 pofile_storename = os.path.join(podir, "test_upload.po")
367 pocontents = 'msgid "singular"\nmsgid_plural "plural"\nmsgstr[0] "enkelvoud string"\nmsgstr[1] "meervoud boodskap"\n'
368 open(pofile_storename, "w").write(pocontents)
369 expected_pocontents = 'msgid "singular"\nmsgid_plural "plural"\nmsgstr[0] "enkelvoud"\nmsgstr[1] "meervoud"\n'
370 fields = {"orig-pure0.0": "singular", "trans0.0": "enkelvoud", "trans0.1": "meervoud", "submit0": "submit", "pofilename": "test_upload.po"}
371 content_type, post_contents = postMultipart.encode_multipart_formdata(fields.items(), [])
372 headers = {"Content-Type": content_type, "Content-Length": len(post_contents)}
373 translatepage = self.post_request("zxx/testproject/test_upload.po?translate=1&editing=1", post_contents, headers)
374 tree = potree.POTree(self.prefs.Pootle)
375 project = projects.TranslationProject("zxx", "testproject", tree)
376 pofile = project.getpofile("test_upload.po")
377 assert str(pofile.units[1]) == expected_pocontents
379 def test_submit_plural_to_singular_lang(self):
380 """tests that we can submit a translation with plurals to a language without plurals."""
381 self.login()
382 podir = self.setup_testproject_dir(perms="view, translate")
383 pofile_storename = os.path.join(podir, "test_upload.po")
384 pocontents = 'msgid "singular"\nmsgid_plural "plural"\nmsgstr[0] "enkelvoud string"\n'
385 open(pofile_storename, "w").write(pocontents)
386 expected_pocontents = 'msgid "singular"\nmsgid_plural "plural"\nmsgstr[0] "enkelvoud"\n'
387 fields = {"orig-pure0.0": "singular", "trans0.0": "enkelvoud", "submit0": "submit", "pofilename": "test_upload.po"}
388 content_type, post_contents = postMultipart.encode_multipart_formdata(fields.items(), [])
389 headers = {"Content-Type": content_type, "Content-Length": len(post_contents)}
390 translatepage = self.post_request("zxx/testproject/test_upload.po?translate=1&editing=1", post_contents, headers)
391 tree = potree.POTree(self.prefs.Pootle)
392 project = projects.TranslationProject("zxx", "testproject", tree)
393 pofile = project.getpofile("test_upload.po")
394 assert str(pofile.units[1]) == expected_pocontents
397 def test_submit_fuzzy(self):
398 """tests that we can mark a unit as fuzzy"""
399 self.login()
400 podir = self.setup_testproject_dir(perms="view, translate")
401 pofile_storename = os.path.join(podir, "test_fuzzy.po")
402 pocontents = '#: test.c\nmsgid "fuzzy"\nmsgstr "wuzzy"\n'
403 open(pofile_storename, "w").write(pocontents)
404 expected_pocontents = '#: test.c\n#, fuzzy\nmsgid "fuzzy"\nmsgstr "wuzzy"\n'
406 # Fetch the page and check that the fuzzy checkbox is NOT checked.
407 translatepage = self.fetch_page("zxx/testproject/test_fuzzy.po?translate=1&editing=1")
408 assert '<input accesskey="f" type="checkbox" name="fuzzy0" />' in translatepage
410 fields = {"orig-pure0.0": "fuzzy", "trans0": "wuzzy", "submit0": "submit", "fuzzy0": "on", "pofilename": "test_fuzzy.po"}
411 content_type, post_contents = postMultipart.encode_multipart_formdata(fields.items(), [])
412 headers = {"Content-Type": content_type, "Content-Length": len(post_contents)}
413 translatepage = self.post_request("zxx/testproject/test_fuzzy.po?translate=1&editing=1", post_contents, headers)
415 # Fetch the page again and check that the fuzzy checkbox IS checked.
416 translatepage = self.fetch_page("zxx/testproject/test_fuzzy.po?translate=1&editing=1")
417 assert '<input type="checkbox" accesskey="f" checked="checked" name="fuzzy0" />' in translatepage
419 tree = potree.POTree(self.prefs.Pootle)
420 project = projects.TranslationProject("zxx", "testproject", tree)
421 pofile = project.getpofile("test_fuzzy.po")
422 assert str(pofile.units[1]) == expected_pocontents
423 assert pofile.units[1].isfuzzy()
425 # Submit the translation again, without the fuzzy checkbox checked
426 fields = {"orig-pure0.0": "fuzzy", "trans0": "wuzzy", "submit0": "submit", "pofilename": "test_fuzzy.po"}
427 content_type, post_contents = postMultipart.encode_multipart_formdata(fields.items(), [])
428 headers = {"Content-Type": content_type, "Content-Length": len(post_contents)}
429 translatepage = self.post_request("zxx/testproject/test_fuzzy.po?translate=1&editing=1", post_contents, headers)
431 # Fetch the page once more and check that the fuzzy checkbox is NOT checked.
432 translatepage = self.fetch_page("zxx/testproject/test_fuzzy.po?translate=1&editing=1")
433 assert '<input accesskey="f" type="checkbox" name="fuzzy0" />' in translatepage
434 tree = potree.POTree(self.prefs.Pootle)
435 project = projects.TranslationProject("zxx", "testproject", tree)
436 pofile = project.getpofile("test_fuzzy.po")
437 assert not pofile.units[1].isfuzzy()
439 def test_submit_translator_comments(self):
440 """tests that we can edit translator comments"""
441 self.login()
442 podir = self.setup_testproject_dir(perms="view, translate")
443 pofile_storename = os.path.join(podir, "test_upload.po")
444 pocontents = '#: test.c\nmsgid "test"\nmsgstr "rest"\n'
445 open(pofile_storename, "w").write(pocontents)
446 expected_pocontents = '# Some test comment\n# test comment line 2\n#: test.c\nmsgid "test"\nmsgstr "rest"\n'
447 fields = {"orig-pure0.0": "test", "trans0": "rest", "translator_comments0": "Some test comment\ntest comment line 2", "submit0": "submit", "pofilename": "test_upload.po"}
448 content_type, post_contents = postMultipart.encode_multipart_formdata(fields.items(), [])
449 headers = {"Content-Type": content_type, "Content-Length": len(post_contents)}
450 translatepage = self.post_request("zxx/testproject/test_upload.po?translate=1&editing=1", post_contents, headers)
451 tree = potree.POTree(self.prefs.Pootle)
452 project = projects.TranslationProject("zxx", "testproject", tree)
453 pofile = project.getpofile("test_upload.po")
454 assert str(pofile.units[1]) == expected_pocontents
457 def test_navigation_url_parameters(self):
458 """tests that the navigation urls (next/end etc) has the necessary parameters"""
459 self.login()
460 podir = self.setup_testproject_dir(perms="view, translate")
461 pofile_storename = os.path.join(podir, "test_nav_url.po")
462 pocontents = '#: test.c\nmsgid "test1"\nmsgstr "rest"\n'
463 pocontents += '\n#. Second Unit\nmsgid "test2"\nmsgstr "rest2"\n'
464 open(pofile_storename, "w").write(pocontents)
465 self.prefs.setvalue("Pootle.users.testuser.viewrows", 1)
466 translatepage = self.fetch_page("zxx/testproject/test_nav_url.po?translate=1&view=1")
467 patterns = re.findall('<a href=".(.*)".*Next 1.*</a>', translatepage)
468 parameters = patterns[0].split('&amp;')
469 assert 'pofilename=test_nav_url.po' in parameters
470 assert 'item=1' in parameters
472 def MakeServerTester(baseclass):
473 """Makes a new Server Tester class using the base class to setup webserver etc"""
474 class TestServer(baseclass, ServerTester):
475 def setup_method(self, method):
476 ServerTester.setup_prefs(self, method)
477 baseclass.setup_method(self, method)
478 ServerTester.setup_cookies(self)
479 return TestServer
481 TestServerCmdLine = MakeServerTester(test_cmdlineserver.TestCmdlineServer)
482 # TestServerService = MakeServerTester(test_service.TestjLogbookService)
483 # TestServerApache = MakeServerTester(test_apache.TestApachejLogbook)