From c83a3cd22e00fda023819ed888d7d1135fc6aff2 Mon Sep 17 00:00:00 2001 From: Joseph Nuthalapati Date: Tue, 2 Oct 2018 20:21:18 -0700 Subject: [PATCH] coquelicot: Implement functional tests with uploading file Reviewed-by: James Valleroy --- functional_tests/features/coquelicot.feature | 10 ++++++ .../step_definitions/interface.py | 6 ++++ functional_tests/step_definitions/site.py | 24 ++++++++++++- functional_tests/support/interface.py | 34 +++++++++++++++++++ functional_tests/support/site.py | 15 ++++++-- 5 files changed, 85 insertions(+), 4 deletions(-) diff --git a/functional_tests/features/coquelicot.feature b/functional_tests/features/coquelicot.feature index 34f4f4dd9..d129dbe26 100644 --- a/functional_tests/features/coquelicot.feature +++ b/functional_tests/features/coquelicot.feature @@ -48,15 +48,25 @@ Scenario: Modify maximum upload size in disabled case When I modify the maximum file size of coquelicot to 123 Then the coquelicot service should not be running +Scenario: Upload a file to coquelicot + Given a sample local file + When I modify the coquelicot upload password to whatever123 + And I upload the sample local file to coquelicot with password whatever123 + And I download the uploaded file from coquelicot + Then contents of downloaded sample file should be same as sample local file + Scenario: Backup and restore coquelicot Given the coquelicot application is enabled When I modify the coquelicot upload password to beforebackup123 And I modify the maximum file size of coquelicot to 128 + And I upload the sample local file to coquelicot with password beforebackup123 And I create a backup of the coquelicot app data And I export the coquelicot app data backup And I modify the coquelicot upload password to afterbackup123 And I modify the maximum file size of coquelicot to 64 And I restore the coquelicot app data backup + And I download the uploaded file from coquelicot Then the coquelicot service should be running And I should be able to login to coquelicot with password beforebackup123 And the maximum file size of coquelicot should be 128 + And contents of downloaded sample file should be same as sample local file diff --git a/functional_tests/step_definitions/interface.py b/functional_tests/step_definitions/interface.py index d3b42f160..e414be22a 100644 --- a/functional_tests/step_definitions/interface.py +++ b/functional_tests/step_definitions/interface.py @@ -77,3 +77,9 @@ def new_user_is_listed(browser, name): @then(parsers.parse('{name:w} should not be listed as a user')) def new_user_is_not_listed(browser, name): assert not interface.is_user(browser, name) + + +@given('a sample local file') +def sample_local_file(): + file_path, contents = interface.create_sample_local_file() + return dict(file_path=file_path, contents=contents) diff --git a/functional_tests/step_definitions/site.py b/functional_tests/step_definitions/site.py index 5cbc25cad..ab1ff9eae 100644 --- a/functional_tests/step_definitions/site.py +++ b/functional_tests/step_definitions/site.py @@ -17,7 +17,7 @@ from pytest_bdd import given, parsers, then, when -from support import site +from support import interface, site @then(parsers.parse('the {site_name:w} site should be available')) @@ -56,6 +56,28 @@ def verify_upload_password(browser, password): site.verify_coquelicot_upload_password(browser, password) +@when( + parsers.parse( + 'I upload the sample local file to coquelicot with password {password:w}' + )) +def coquelicot_upload_file(browser, sample_local_file, password): + url = site.upload_file_to_coquelicot( + browser, sample_local_file['file_path'], password) + sample_local_file['upload_url'] = url + + +@when('I download the uploaded file from coquelicot') +def coquelicot_download_file(sample_local_file): + file_path = interface.download_file(sample_local_file['upload_url']) + sample_local_file['download_path'] = file_path + + +@then('contents of downloaded sample file should be same as sample local file') +def coquelicot_compare_upload_download_files(sample_local_file): + interface.compare_files(sample_local_file['file_path'], + sample_local_file['download_path']) + + @then(parsers.parse('the mediawiki site should allow creating accounts')) def mediawiki_allows_creating_accounts(browser): site.verify_mediawiki_create_account_link(browser) diff --git a/functional_tests/support/interface.py b/functional_tests/support/interface.py index 61d3ddc9c..6eea6eed4 100644 --- a/functional_tests/support/interface.py +++ b/functional_tests/support/interface.py @@ -15,6 +15,12 @@ # along with this program. If not, see . # +import logging +import random +import tempfile + +import requests + from support import config from .service import wait_for_page_update @@ -115,3 +121,31 @@ def submit(browser, element=None, form_class=None): '.{} input[type=submit]'.format(form_class)).click() else: browser.find_by_css('input[type=submit]').click() + + +def create_sample_local_file(): + """Create a sample file for upload using browser.""" + contents = bytearray(random.getrandbits(8) for _ in range(64)) + with tempfile.NamedTemporaryFile(delete=False) as temp_file: + temp_file.write(contents) + + return temp_file.name, contents + + +def download_file(url): + """Download a file to disk given a URL.""" + with tempfile.NamedTemporaryFile(delete=False) as temp_file: + logging.captureWarnings(True) + request = requests.get(url, verify=False) + logging.captureWarnings(False) + temp_file.write(request.content) + + return temp_file.name + + +def compare_files(file1, file2): + """Assert that the contents of two files are the same.""" + file1_contents = open(file1, 'rb').read() + file2_contents = open(file2, 'rb').read() + + assert file1_contents == file2_contents diff --git a/functional_tests/support/site.py b/functional_tests/support/site.py index b17f15122..29f0596a6 100644 --- a/functional_tests/support/site.py +++ b/functional_tests/support/site.py @@ -24,7 +24,6 @@ from selenium.webdriver.common.keys import Keys from support import application, config, interface, system from support.service import eventually, wait_for_page_update - # unlisted sites just use '/' + site_name as url site_url = { 'wiki': '/ikiwiki', @@ -63,6 +62,17 @@ def verify_coquelicot_upload_password(browser, password): args=['div[style*="display: none;"]']) +def upload_file_to_coquelicot(browser, file_path, password): + """Upload a local file from disk to coquelicot.""" + verify_coquelicot_upload_password(browser, password) + browser.attach_file('file', file_path) + interface.submit(browser) + assert eventually(browser.is_element_present_by_css, + args=['#content .url']) + url_textarea = browser.find_by_css('#content .url textarea').first + return url_textarea.value + + def verify_mediawiki_create_account_link(browser): browser.visit(config['DEFAULT']['url'] + '/mediawiki') assert eventually(browser.is_element_present_by_id, @@ -111,8 +121,7 @@ def upload_image_mediawiki(browser, username, password, image): # Upload file browser.visit(config['DEFAULT']['url'] + '/mediawiki/Special:Upload') - file_path = os.path.realpath( - '../static/themes/default/img/' + image) + file_path = os.path.realpath('../static/themes/default/img/' + image) browser.attach_file('wpUploadFile', file_path) interface.submit(browser, element=browser.find_by_name('wpUpload')[0])