diff options
Diffstat (limited to 'www/wiki/extensions/UploadWizard/tests/api/upload-wizard_tests.py')
-rw-r--r-- | www/wiki/extensions/UploadWizard/tests/api/upload-wizard_tests.py | 253 |
1 files changed, 253 insertions, 0 deletions
diff --git a/www/wiki/extensions/UploadWizard/tests/api/upload-wizard_tests.py b/www/wiki/extensions/UploadWizard/tests/api/upload-wizard_tests.py new file mode 100644 index 00000000..c132ddf2 --- /dev/null +++ b/www/wiki/extensions/UploadWizard/tests/api/upload-wizard_tests.py @@ -0,0 +1,253 @@ +#!/usr/bin/python -u +# Public domain +# +# Set of integration tests that simulate API calls made by the +# UploadWizard frontend. + +import argparse +import sys +import unittest +import urllib2 +import wikitools +from PIL import Image +from PIL import ImageDraw +from PIL import ImageFont +import time +import os + +# This script also depends on poster: https://pypi.python.org/pypi/poster/ +# To install all dependencies in your unix instance use: +# sudo pip install -r requirements.txt + +# Global wiki object to perform API calls. +wiki = None + +# Global verbosity variable used inside the tests. +verbosity = 0 + +# Global generate new image variable used to check the --gen_new_image flag +generate_new_image = False + + +class TestUploadWizardAPICalls(unittest.TestCase): + """Test API calls done by the Upload Wizard""" + + # Tests use same global variables initialized in main(). + global wiki + global generate_new_image + global verbosity + + def createNewImage(self): + """Create a new image with current timestamp as text marker""" + current_timestamp = time.time() + filename = repr(current_timestamp) + ".png" + ImageFont.load_default() + image = Image.new("RGB", (125, 25)) + draw = ImageDraw.Draw(image) + draw.text((10, 10), repr(current_timestamp), (255, 255, 255)) + # TODO(aarcos): Store in /tmp + image.save(filename, "PNG") + return filename + + def uploadImage(self, remote_stash_filename, final_remote_filename, local_filename): + """Uploads image using a workflow very similar to the UploadWizard. First upload + to the stash area, if that's successfull then upload for real. + + remote_stash_filename - Filename used when we upload to stash area + final_remote_filename - Filename when we upload for real + local_filename - Local filename of the image to be uploaded + """ + # Get edit token + params = { + "action": "tokens", + "type": "edit", + } + req = wikitools.api.APIRequest(wiki, params) + data = req.query() + token = data["tokens"]["edittoken"] + + self.assertTrue(len(token) > 0, "Could not get valid token") + + # Upload file to stash area + params = { + "action": "upload", + "token": token, + "stash": "1", + "ignorewarnings": "true", + "filename": remote_stash_filename, + "file": open(local_filename), + } + req = wikitools.api.APIRequest(wiki, params, multipart=True) + data = req.query() + + if verbosity >= 3: + print "Response from stash upload API call:", data + + result = data["upload"]["result"] + self.assertEqual(result, "Success", "Stash upload API call FAILED.") + + filekey = data["upload"]["filekey"] + self.assertTrue(len(filekey) > 0, "Could not get valid filekey") + + if verbosity >= 3: + print "filekey:", filekey + + # Upload file for real using the filekey from previous call + params = { + "action": "upload", + "token": token, + "filekey": filekey, + "ignorewarnings": "true", + "filename": final_remote_filename, + "comment": "Test image uploaded via python script.", + "text": "Image uploaded by WMF QA to monitor upload status. {{pd-ineligible}}[[Category:Test images]]", + } + req = wikitools.api.APIRequest(wiki, params) + data = req.query() + + if verbosity >= 3: + print "Response to upload API call:", data + + result = data["upload"]["result"] + self.assertEqual(result, "Success", "Upload API call FAILED.") + + url = data["upload"]["imageinfo"]["url"] + + # Assert uploaded content same as source file ! + file_content = file(local_filename, "rb").read() + url_content = urllib2.urlopen(url).read() + + self.assertEqual(url_content, file_content, "Uploaded content different than original !") + + if verbosity >= 0: + print "File '%s' uploaded successfully !" % final_remote_filename + + def testUploadImageUsingWizardWorkflow(self): + """Test that basic api calls used by the UploadWizard are working as expected""" + + remote_stash_filename = "55390test-image-rosa-mx-15x15.png" + final_remote_filename = "Test-image-rosa-mx-15x15.png" + local_filename = "test-image-rosa-mx-15x15.png" + + if generate_new_image: + temp_image = self.createNewImage() + remote_stash_filename = temp_image + final_remote_filename = "Test-" + temp_image + local_filename = temp_image + + if verbosity >= 3: + print "Created temp_image:", temp_image + + try: + self.uploadImage(remote_stash_filename, final_remote_filename, local_filename) + finally: + os.remove(temp_image) + else: + self.uploadImage(remote_stash_filename, final_remote_filename, local_filename) + + def testFileInfoAPICall(self): + """Test file info api call used by the UploadWizard""" + + # Try to get file info from a non-existent file + params = { + "action": "query", + "titles": "File:Test-image-non-existant-15x15.png", + "prop": "info|imageinfo", + "inprop": "protection", + "iiprop": "url|mime|size", + "iiurlwidth": "150", + } + req = wikitools.api.APIRequest(wiki, params) + data = req.query() + + if verbosity >= 3: + print "Response to file info API call:", data + + # Assert that no information was found about the file. + result = data["query"]["pages"]["-1"]["missing"] + self.assertEqual(result, "") + + def testTitleBlacklistedAPICall(self): + """Test title blacklisted api call used by the UploadWizard""" + + # Get titleblacklist info + params = { + "action": "titleblacklist", + "tbaction": "create", + "tbtitle": "File:Test-image-rosa-mx-15x15.png", + } + req = wikitools.api.APIRequest(wiki, params) + data = req.query() + + if verbosity >= 3: + print "Response to upload API call:", data + + result = data["titleblacklist"]["result"] + self.assertEqual(result, "ok") + + +def main(): + """Script that tests some API calls and workflows used by the UploadWizard. + Example: + $ python upload-wizard_tests.py --username some_username --password secret_password + """ + + # Global varibles that are going to be used by the tests. + global wiki + global verbosity + global generate_new_image + + # Parse line arguments + parser = argparse.ArgumentParser(description="Upload Wizard API smoke tests.") + parser.add_argument("--api_url", default="https://commons.wikimedia.org/w/api.php", + help="URL of wiki API, such as http://example.org/w/api.php") + parser.add_argument("--username", help="Username for API calls. You can also set MEDIAWIKI_USER") + parser.add_argument("--password", + help="Password for API calls. You can also set MEDIAWIKI_PASSWORD " + + "or MEDIAWIKI_PASSWORD_VARIABLE (points to env var with password value)") + parser.add_argument("-v", "--verbose", type=int, default=0, help="Increase output verbosity") + parser.add_argument("--gen_new_image", action="store_true", help="Create a new image with current timestamp") + args = parser.parse_args() + + username = args.username or os.getenv("MEDIAWIKI_USER") + password = args.password or os.getenv("MEDIAWIKI_PASSWORD") or os.getenv(os.getenv("MEDIAWIKI_PASSWORD_VARIABLE")) + + if username is None or password is None: + sys.stderr.write( + "error: username and password required. Pass these values with the corresponding flags or set " + + "the env variables: MEDIAWIKI_USER and MEDIAWIKI_PASSWORD or " + + "MEDIAWIKI_PASSWORD_VARIABLE (points to env var with password value)\n") + exit(1) + + # Create wikitools object + wiki = wikitools.Wiki(args.api_url) + generate_new_image = args.gen_new_image + verbosity = args.verbose + + # Log in user + wiki.login(username, password) + + if not wiki.isLoggedIn(): + sys.stderr.write("Wrong credentials, please try again.\n") + exit(1) + + # Switch to directory of script + abspath = os.path.abspath(__file__) + dname = os.path.dirname(abspath) + os.chdir(dname) + + # Run tests + suite = unittest.TestLoader().loadTestsFromTestCase(TestUploadWizardAPICalls) + success = unittest.TextTestRunner(verbosity=verbosity).run(suite).wasSuccessful() + + # Log out user + wiki.logout() + + return success + + +if __name__ == "__main__": + if main() is True: + sys.exit(0) + else: + sys.exit(1) |