diff options
Diffstat (limited to 'tests/qc_app')
-rw-r--r-- | tests/qc_app/__init__.py | 0 | ||||
-rw-r--r-- | tests/qc_app/test_entry.py | 43 | ||||
-rw-r--r-- | tests/qc_app/test_expression_data_pages.py | 93 | ||||
-rw-r--r-- | tests/qc_app/test_parse.py | 96 | ||||
-rw-r--r-- | tests/qc_app/test_progress_indication.py | 109 | ||||
-rw-r--r-- | tests/qc_app/test_results_page.py | 68 | ||||
-rw-r--r-- | tests/qc_app/test_uploads_with_zip_files.py | 84 |
7 files changed, 0 insertions, 493 deletions
diff --git a/tests/qc_app/__init__.py b/tests/qc_app/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/tests/qc_app/__init__.py +++ /dev/null diff --git a/tests/qc_app/test_entry.py b/tests/qc_app/test_entry.py deleted file mode 100644 index 0c614a5..0000000 --- a/tests/qc_app/test_entry.py +++ /dev/null @@ -1,43 +0,0 @@ -"""Test the entry module in the web-ui""" -import pytest - -@pytest.mark.parametrize( - "dataitem,lower", - ( - # expression data UI elements - (b'<h2 class="heading">expression data</h2>', True), - (b'<a href="/upload"', False), - (b'upload expression data</a>', False), - - # samples/cases data UI elements - (b'<h2 class="heading">samples/cases</h2>', True), - (b'<a href="/samples/upload/species"', False), - (b'upload samples/cases', True), - - # R/qtl2 data UI elements - (b'<h2 class="heading">r/qtl2 bundles</h2>', True), - (b'<a href="/upload/rqtl2/select-species"', False), - (b'upload r/qtl2 bundle', True) - )) -def test_landing_page_has_sections(client, dataitem, lower): - """ - GIVEN: A flask application testing client - WHEN: the index page is requested - THEN: ensure the page has the expected UI elements - """ - resp = client.get("/") - assert resp.status_code == 200 - assert dataitem in (resp.data.lower() if lower else resp.data) - - -def test_landing_page_fails_with_post(client): - """ - GIVEN: A flask application testing client - WHEN: the index page is requested with the "POST" method - THEN: ensure the system fails - """ - resp = client.post("/") - assert resp.status_code == 405 - assert ( - b'<h1>405: The method is not allowed for the requested URL.</h1>' - in resp.data) diff --git a/tests/qc_app/test_expression_data_pages.py b/tests/qc_app/test_expression_data_pages.py deleted file mode 100644 index 6e073fb..0000000 --- a/tests/qc_app/test_expression_data_pages.py +++ /dev/null @@ -1,93 +0,0 @@ -"""Test expression data path""" -import pytest - -from tests.conftest import uploadable_file_object - -def test_basic_elements_present_in_index_page(client): - """ - GIVEN: A flask application testing client - WHEN: the index page is requested with the "GET" method and no data - THEN: verify that the response contains error notifications - """ - response = client.get("/upload") - assert response.status_code == 200 - ## form present - assert b'<form action="/upload"' in response.data - assert b'method="POST"' in response.data - assert b'enctype="multipart/form-data"' in response.data - assert b'</form>' in response.data - ## filetype elements - assert b'<input type="radio" name="filetype"' in response.data - assert b'id="filetype_standard_error"' in response.data - assert b'id="filetype_average"' in response.data - ## file upload elements - assert b'<label for="file_upload"' in response.data - assert b'select file' in response.data - assert b'<input type="file" name="qc_text_file"' in response.data - assert b'id="file_upload"' in response.data - ## submit button - assert b'<button type="submit"' in response.data - - -def test_post_notifies_errors_if_no_data_is_provided(client): - """ - GIVEN: A flask application testing client - WHEN: the index page is requested with the "POST" method and with no - data provided - THEN: ensure the system responds woit the appropriate error messages - """ - response = client.post("/upload", data={}, follow_redirects=True) - assert len(response.history) == 1 - redirect = response.history[0] - assert redirect.status_code == 302 - assert redirect.location == "/upload" - - - assert response.status_code == 200 - assert b'Invalid file type provided.' in response.data - assert b'No file was uploaded.' in response.data - -def test_post_with_correct_data(client): - """ - GIVEN: A flask application testing client - WHEN: the index page is requested with the "POST" method and with the - appropriate data provided - THEN: ensure the system redirects to the parse endpoint with the filename - and filetype - """ - response = client.post( - "/upload", data={ - "speciesid": 1, - "filetype": "average", - "qc_text_file": uploadable_file_object("no_data_errors.tsv") - }) - - assert response.status_code == 302 - assert b'Redirecting...' in response.data - assert ( - b'/parse/parse?speciesid=1&filename=no_data_errors.tsv&filetype=average' - in response.data) - - -@pytest.mark.parametrize( - "request_data,error_message", - (({"filetype": "invalid_choice", - "qc_text_file": uploadable_file_object("no_data_errors.tsv")}, - b'Invalid file type provided.'), - ({"filetype": "average"}, b'No file was uploaded.'), - ({"filetype": "standard-error"}, b'No file was uploaded.'))) -def test_post_with_missing_or_invalid_data(client, request_data,error_message): - """ - GIVEN: A flask application testing client - WHEN: the index page is requested with the "POST" method and with data - either being missing or invalid - THEN: ensure that the system responds with the appropriate error message - """ - response = client.post("/upload", data=request_data, follow_redirects=True) - assert len(response.history) == 1 - redirect = response.history[0] - assert redirect.status_code == 302 - assert redirect.location == "/upload" - - assert response.status_code == 200 - assert error_message in response.data diff --git a/tests/qc_app/test_parse.py b/tests/qc_app/test_parse.py deleted file mode 100644 index 3915a4d..0000000 --- a/tests/qc_app/test_parse.py +++ /dev/null @@ -1,96 +0,0 @@ -"""Test the 'parse' module in the web-ui""" -import sys - -import redis -import pytest - -from qc_app.jobs import job, jobsnamespace - -from tests.conftest import uploadable_file_object - -def test_parse_with_existing_uploaded_file(#pylint: disable=[too-many-arguments] - client, - db_url, - redis_url, - redis_ttl, - jobs_prefix, - job_id, - monkeypatch): - """ - GIVEN: 1. A flask application testing client - 2. A valid file, and filetype - WHEN: The file is uploaded, and the parsing triggered - THEN: Ensure that: - 1. the system redirects to the job/parse status page - 2. the job is placed on redis for processing - """ - monkeypatch.setattr("qc_app.jobs.uuid4", lambda : job_id) - # Upload a file - speciesid = 1 - filename = "no_data_errors.tsv" - filetype = "average" - client.post( - "/upload", data={ - "speciesid": speciesid, - "filetype": filetype, - "qc_text_file": uploadable_file_object(filename)}) - # Checks - resp = client.get(f"/parse/parse?speciesid={speciesid}&filename={filename}" - f"&filetype={filetype}") - assert resp.status_code == 302 - assert b'Redirecting...' in resp.data - assert b'/parse/status/934c55d8-396e-4959-90e1-2698e9205758' in resp.data - - with redis.Redis.from_url(redis_url, decode_responses=True) as rconn: - the_job = job(rconn, jobsnamespace(), job_id) - - assert the_job["jobid"] == job_id - assert the_job["filename"] == filename - assert the_job["command"] == " ".join([ - sys.executable, "-m", "scripts.validate_file", db_url, redis_url, - jobs_prefix, job_id, "--redisexpiry", str(redis_ttl), str(speciesid), - filetype, f"{client.application.config['UPLOAD_FOLDER']}/{filename}"]) - -@pytest.mark.parametrize( - "filename,uri,error_msgs", - (("non_existent.file", - "/parse/parse?filename=non_existent.file&filename=average", - [b'Selected file does not exist (any longer)']), - ("non_existent.file", - "/parse/parse?filename=non_existent.file&filename=standard-error", - [b'Selected file does not exist (any longer)']), - ("non_existent.file", - "/parse/parse?filename=non_existent.file&filename=percival", - [b'Selected file does not exist (any longer)', - b'Invalid filetype provided']), - ("no_data_errors.tsv", - "/parse/parse?filename=no_data_errors.tsv&filename=percival", - [b'Invalid filetype provided']), - ("no_data_errors.tsv", - "/parse/parse?filename=no_data_errors.tsv", - [b'No filetype provided']), - (None, "/parse/parse", [b'No file provided', b'No filetype provided']))) -def test_parse_with_non_uploaded_file(client, filename, uri, error_msgs): - """ - GIVEN: 1. A flask application testing client - 2. A valid filetype - 3. A filename to a file that has not been uploaded yet - WHEN: The parsing triggered - THEN: Ensure that the appropriate errors are displayed - """ - ## Conditionally upload files - if filename and filename != "non_existent.file": - client.post( - "/upload", data={ - "filetype": "average", - "qc_text_file": uploadable_file_object(filename)}) - # Trigger - resp = client.get(uri,follow_redirects=True) - ## Check that there was exactly one redirect - assert len(resp.history) == 1 and resp.history[0].status_code == 302 - ## Check that redirect is to home page and is successful - assert resp.request.path == "/upload" - assert resp.status_code == 200 - ## Check that error(s) are displayed - for error_msg in error_msgs: - assert error_msg in resp.data diff --git a/tests/qc_app/test_progress_indication.py b/tests/qc_app/test_progress_indication.py deleted file mode 100644 index 14a1050..0000000 --- a/tests/qc_app/test_progress_indication.py +++ /dev/null @@ -1,109 +0,0 @@ -"Test that the progress indication works correctly" - -def test_with_non_existing_job(client, redis_conn_with_fresh_job): # pylint: disable=[unused-argument] - """ - GIVEN: 1. A flask application testing client - 2. A redis instance with a fresh, unstarted job - WHEN: The parsing progress page is loaded for a non existing job - THEN: Ensure that the page: - 1. Has a meta tag to redirect it to the index page after 5 seconds - 2. Has text indicating that the job does not exist - """ - job_id = "non-existent-job-id" - resp = client.get(f"/parse/status/{job_id}") - assert resp.status_code == 400 - assert ( - b"No job, with the id '<em>non-existent-job-id</em>' was found!" - in resp.data) - assert b'<meta http-equiv="refresh" content="5;url=/upload">' in resp.data - -def test_with_unstarted_job(client, job_id, redis_conn_with_fresh_job): # pylint: disable=[unused-argument] - """ - GIVEN: 1. A flask application testing client - 2. A redis instance with a fresh, unstarted job - WHEN: The parsing progress page is loaded - THEN: Ensure that the page: - 1. Has a meta tag to refresh it after 5 seconds - 2. Has a progress indicator with zero progress - """ - resp = client.get(f"/parse/status/{job_id}") - assert b'<meta http-equiv="refresh" content="5">' in resp.data - assert ( - b'<progress id="job_' + (f'{job_id}').encode("utf8") + b'"') in resp.data - assert b'value="0.0"' in resp.data - assert b'0.0</progress>' in resp.data - -def test_with_in_progress_no_error_job( - client, job_id, redis_conn_with_in_progress_job_no_errors): # pylint: disable=[unused-argument] - """ - GIVEN: 1. A flask application testing client - 2. A redis instance with a job in progress, with no errors found in - the file so far - WHEN: The parsing progress page is loaded - THEN: Ensure that the page: - 1. Has a meta tag to refresh it after 5 seconds - 2. Has a progress indicator with the percent of the file processed - indicated - """ - resp = client.get(f"/parse/status/{job_id}") - assert b'<meta http-equiv="refresh" content="5">' in resp.data - assert ( - b'<progress id="job_' + (f'{job_id}').encode("utf8") + b'"') in resp.data - assert b'value="0.32242342"' in resp.data - assert b'32.242342</progress>' in resp.data - assert ( - b'<span >No errors found so far</span>' - in resp.data) - assert b"<table" not in resp.data - -def test_with_in_progress_job_with_errors( - client, job_id, redis_conn_with_in_progress_job_some_errors): # pylint: disable=[unused-argument] - """ - GIVEN: 1. A flask application testing client - 2. A redis instance with a job in progress, with some errors found in - the file so far - WHEN: The parsing progress page is loaded - THEN: Ensure that the page: - 1. Has a meta tag to refresh it after 5 seconds - 2. Has a progress indicator with the percent of the file processed - indicated - 3. Has a table showing the errors found so far - """ - resp = client.get(f"/parse/status/{job_id}") - assert b'<meta http-equiv="refresh" content="5">' in resp.data - assert ( - b'<progress id="job_' + (f'{job_id}').encode("utf8") + b'"') in resp.data - assert b'value="0.4534245"' in resp.data - assert b'45.34245</progress>' in resp.data - assert ( - b'<p class="alert-danger">We have found the following errors so far</p>' - in resp.data) - assert b'table class="table reports-table">' in resp.data - assert b'Duplicate Header' in resp.data - assert b'Invalid Value' in resp.data - -def test_with_completed_job_no_errors( - client, job_id, redis_conn_with_completed_job_no_errors): # pylint: disable=[unused-argument] - """ - GIVEN: 1. A flask application testing client - 2. A redis instance with a completed job, with no errors found in - the file so far - WHEN: The parsing progress page is loaded - THEN: Ensure that the response is a redirection to the results page - """ - resp = client.get(f"/parse/status/{job_id}") - assert resp.status_code == 302 - assert f"/parse/results/{job_id}".encode("utf8") in resp.data - -def test_with_completed_job_some_errors( - client, job_id, redis_conn_with_completed_job_no_errors): # pylint: disable=[unused-argument] - """ - GIVEN: 1. A flask application testing client - 2. A redis instance with a completed job, with some errors found in - the file so far - WHEN: The parsing progress page is loaded - THEN: Ensure that the response is a redirection to the results page - """ - resp = client.get(f"/parse/status/{job_id}") - assert resp.status_code == 302 - assert f"/parse/results/{job_id}".encode("utf8") in resp.data diff --git a/tests/qc_app/test_results_page.py b/tests/qc_app/test_results_page.py deleted file mode 100644 index bb596d7..0000000 --- a/tests/qc_app/test_results_page.py +++ /dev/null @@ -1,68 +0,0 @@ -"Test results page" - -def test_results_with_stderr_output( - client, job_id, stderr_with_output, # pylint: disable=[unused-argument] - redis_conn_with_in_progress_job_no_errors): # pylint: disable=[unused-argument] - """ - GIVEN: 1. A flask application testing client - 2. A file with content to simulate the stderr output - 3. A sample job to prevent the "No such job" error message - WHEN: The parsing progress page is loaded for a non existing job - THEN: Ensure that the page: - 1. Redirects to a job failure display page - 2. The job failure display page: - a) indicates that this is a worker failure - b) provides some debugging information - """ - # Maybe get rid of the use of a stderr file, and check for actual exceptions - resp = client.get(f"/parse/status/{job_id}", follow_redirects=True) - assert len(resp.history) == 1 - assert b'<h1 class="heading">Worker Failure</h1>' in resp.data - assert b'<h4>Debugging Information</h4>' in resp.data - assert ( - f"<li><strong>job id</strong>: {job_id}</li>".encode("utf8") - in resp.data) - -def test_results_with_completed_job_no_errors( - client, job_id, stderr_with_no_output, # pylint: disable=[unused-argument] - redis_conn_with_completed_job_no_errors): # pylint: disable=[unused-argument] - """ - GIVEN: 1. A flask application testing client - 2. A redis instance with a completed job, with no errors found in - the file - 3. A file with no contents to simulate no stderr output - WHEN: The parsing progress page is loaded - THEN: Ensure that: - 1. the system redirects to the results page - 2. the results page indicates that there are no errors in the file - being processed - """ - resp = client.get(f"/parse/status/{job_id}", follow_redirects=True) - assert len(resp.history) == 1 - assert ( - b'<span class="alert-success">No errors found in the file</span>' - in resp.data) - -def test_results_with_completed_job_some_errors( - client, job_id, stderr_with_no_output, # pylint: disable=[unused-argument] - redis_conn_with_completed_job_some_errors): # pylint: disable=[unused-argument] - """ - GIVEN: 1. A flask application testing client - 2. A redis instance with a completed job, with some errors found in - the file - 3. A file with no contents to simulate no stderr output - WHEN: The parsing progress page is loaded - THEN: Ensure that: - 1. the system redirects to the results page - 2. the results page displays the errors found - """ - resp = client.get(f"/parse/status/{job_id}", follow_redirects=True);import sys;print(resp.data, file=sys.stderr) - assert len(resp.history) == 1 - assert ( - b'<p class="alert-danger">We found the following errors</p>' - in resp.data) - assert b'<table class="table reports-table">' in resp.data - assert b'Duplicate Header' in resp.data - assert b'<td>Heading 'DupHead' is repeated</td>' in resp.data - assert b'Invalid Value' in resp.data - assert b'<td>Invalid value 'ohMy'</td>' in resp.data diff --git a/tests/qc_app/test_uploads_with_zip_files.py b/tests/qc_app/test_uploads_with_zip_files.py deleted file mode 100644 index 1506cfa..0000000 --- a/tests/qc_app/test_uploads_with_zip_files.py +++ /dev/null @@ -1,84 +0,0 @@ -"""Test the upload of zip files""" -from tests.conftest import uploadable_file_object - -def test_upload_zipfile_with_zero_files(client): - """ - GIVEN: A flask application testing client - WHEN: A zip file with no files is uploaded - THEN: Ensure that the system responds with the appropriate error message and - status code - """ - resp = client.post("/upload", - data={ - "filetype": "average", - "qc_text_file": uploadable_file_object("empty.zip")}, - follow_redirects=True) - assert len(resp.history) == 1 - redirect = resp.history[0] - assert redirect.status_code == 302 - assert redirect.location == "/upload" - - assert resp.status_code == 200 - assert (b"Expected exactly one (1) member file within the uploaded zip " - b"file. Got 0 member files.") in resp.data - -def test_upload_zipfile_with_multiple_files(client): - """ - GIVEN: A flask application testing client - WHEN: A zip file with more than one file is uploaded - THEN: Ensure that the system responds with the appropriate error message and - status code - """ - resp = client.post( - "/upload", - data={ - "filetype": "average", - "qc_text_file": uploadable_file_object("multiple_files.zip")}, - follow_redirects=True) - assert len(resp.history) == 1 - redirect = resp.history[0] - assert redirect.status_code == 302 - assert redirect.location == "/upload" - - assert resp.status_code == 200 - assert (b"Expected exactly one (1) member file within the uploaded zip " - b"file. Got 3 member files.") in resp.data - -def test_upload_zipfile_with_one_tsv_file(client): - """ - GIVEN: A flask application testing client - WHEN: A zip file with exactly one valid TSV file is uploaded - THEN: Ensure that the system redirects to the correct next URL - """ - resp = client.post("/upload", data={ - "speciesid": 1, - "filetype": "average", - "qc_text_file": uploadable_file_object("average.tsv.zip")}) - assert resp.status_code == 302 - assert b"Redirecting..." in resp.data - assert ( - b"/parse/parse?speciesid=1&filename=average.tsv.zip&filetype=average" - in resp.data) - -def test_upload_zipfile_with_one_non_tsv_file(client): - """ - GIVEN: A flask application testing client - WHEN: A zip file with exactly one file, which is not a valid TSV, is - uploaded - THEN: Ensure that the system responds with the appropriate error message and - status code - """ - resp = client.post( - "/upload", - data={ - "filetype": "average", - "qc_text_file": uploadable_file_object("non_tsv.zip")}, - follow_redirects=True) - assert len(resp.history) == 1 - redirect = resp.history[0] - assert redirect.status_code == 302 - assert redirect.location == "/upload" - - assert resp.status_code == 200 - assert (b"Expected the member text file in the uploaded zip file to " - b"be a tab-separated file.") in resp.data |