From 85215361b561d332cab954ea68438a2d442c96d8 Mon Sep 17 00:00:00 2001 From: Frederick Muriuki Muriithi Date: Thu, 17 Oct 2024 10:26:15 -0500 Subject: Rename test module. --- tests/uploader/__init__.py | 0 tests/uploader/test_entry.py | 43 ++++++++++ tests/uploader/test_expression_data_pages.py | 92 ++++++++++++++++++++++ tests/uploader/test_parse.py | 96 +++++++++++++++++++++++ tests/uploader/test_progress_indication.py | 109 ++++++++++++++++++++++++++ tests/uploader/test_results_page.py | 68 ++++++++++++++++ tests/uploader/test_uploads_with_zip_files.py | 84 ++++++++++++++++++++ 7 files changed, 492 insertions(+) create mode 100644 tests/uploader/__init__.py create mode 100644 tests/uploader/test_entry.py create mode 100644 tests/uploader/test_expression_data_pages.py create mode 100644 tests/uploader/test_parse.py create mode 100644 tests/uploader/test_progress_indication.py create mode 100644 tests/uploader/test_results_page.py create mode 100644 tests/uploader/test_uploads_with_zip_files.py (limited to 'tests/uploader') diff --git a/tests/uploader/__init__.py b/tests/uploader/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/uploader/test_entry.py b/tests/uploader/test_entry.py new file mode 100644 index 0000000..0c614a5 --- /dev/null +++ b/tests/uploader/test_entry.py @@ -0,0 +1,43 @@ +"""Test the entry module in the web-ui""" +import pytest + +@pytest.mark.parametrize( + "dataitem,lower", + ( + # expression data UI elements + (b'

expression data

', True), + (b'', False), + + # samples/cases data UI elements + (b'

samples/cases

', True), + (b'
r/qtl2 bundles', True), + (b'405: The method is not allowed for the requested URL.' + in resp.data) diff --git a/tests/uploader/test_expression_data_pages.py b/tests/uploader/test_expression_data_pages.py new file mode 100644 index 0000000..c2f7de1 --- /dev/null +++ b/tests/uploader/test_expression_data_pages.py @@ -0,0 +1,92 @@ +"""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'
' in response.data + ## filetype elements + assert b'non-existent-job-id' was found!" + in resp.data) + assert b'' 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'' in resp.data + assert ( + b'' 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'' in resp.data + assert ( + b'' in resp.data + assert ( + b'No errors found so far' + in resp.data) + assert b"' in resp.data + assert ( + b'' in resp.data + assert ( + b'

We have found the following errors so far

' + 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/uploader/test_results_page.py b/tests/uploader/test_results_page.py new file mode 100644 index 0000000..8c8379f --- /dev/null +++ b/tests/uploader/test_results_page.py @@ -0,0 +1,68 @@ +"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'

Worker Failure

' in resp.data + assert b'

Debugging Information

' in resp.data + assert ( + f"
  • job id: {job_id}
  • ".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'No errors found in the file' + 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) + assert len(resp.history) == 1 + assert ( + b'

    We found the following errors

    ' + in resp.data) + assert b'' in resp.data + assert b'Duplicate Header' in resp.data + assert b'' in resp.data + assert b'Invalid Value' in resp.data + assert b'' in resp.data diff --git a/tests/uploader/test_uploads_with_zip_files.py b/tests/uploader/test_uploads_with_zip_files.py new file mode 100644 index 0000000..1506cfa --- /dev/null +++ b/tests/uploader/test_uploads_with_zip_files.py @@ -0,0 +1,84 @@ +"""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 -- cgit v1.2.3
    Heading 'DupHead' is repeatedInvalid value 'ohMy'