Reorganize requests route tests
This commit is contained in:
199
tests/routes/requests/approval.py
Normal file
199
tests/routes/requests/approval.py
Normal file
@@ -0,0 +1,199 @@
|
||||
import os
|
||||
from flask import url_for
|
||||
|
||||
from atst.models.attachment import Attachment
|
||||
from atst.models.request_status_event import RequestStatus
|
||||
from atst.domain.roles import Roles
|
||||
|
||||
from tests.factories import (
|
||||
RequestFactory,
|
||||
TaskOrderFactory,
|
||||
UserFactory,
|
||||
RequestReviewFactory,
|
||||
RequestStatusEventFactory,
|
||||
)
|
||||
|
||||
|
||||
def test_ccpo_can_view_approval(user_session, client):
|
||||
ccpo = Roles.get("ccpo")
|
||||
user = UserFactory.create(atat_role=ccpo)
|
||||
user_session(user)
|
||||
|
||||
request = RequestFactory.create()
|
||||
response = client.get(url_for("requests.approval", request_id=request.id))
|
||||
assert response.status_code == 200
|
||||
|
||||
|
||||
def test_ccpo_prepopulated_as_mission_owner(user_session, client):
|
||||
user = UserFactory.from_atat_role("ccpo")
|
||||
user_session(user)
|
||||
|
||||
request = RequestFactory.create_with_status(RequestStatus.PENDING_CCPO_ACCEPTANCE)
|
||||
response = client.get(url_for("requests.approval", request_id=request.id))
|
||||
|
||||
body = response.data.decode()
|
||||
assert user.first_name in body
|
||||
assert user.last_name in body
|
||||
|
||||
|
||||
def test_non_ccpo_cannot_view_approval(user_session, client):
|
||||
user = UserFactory.create()
|
||||
user_session(user)
|
||||
|
||||
request = RequestFactory.create(creator=user)
|
||||
response = client.get(url_for("requests.approval", request_id=request.id))
|
||||
assert response.status_code == 404
|
||||
|
||||
|
||||
def prepare_request_pending_approval(creator, pdf_attachment=None):
|
||||
task_order = TaskOrderFactory.create(number="abc123", pdf=pdf_attachment)
|
||||
return RequestFactory.create_with_status(
|
||||
status=RequestStatus.PENDING_CCPO_APPROVAL,
|
||||
task_order=task_order,
|
||||
creator=creator,
|
||||
)
|
||||
|
||||
|
||||
def test_ccpo_sees_pdf_link(user_session, client, pdf_upload):
|
||||
ccpo = UserFactory.from_atat_role("ccpo")
|
||||
user_session(ccpo)
|
||||
|
||||
attachment = Attachment.attach(pdf_upload)
|
||||
request = prepare_request_pending_approval(ccpo, pdf_attachment=attachment)
|
||||
|
||||
response = client.get(url_for("requests.approval", request_id=request.id))
|
||||
download_url = url_for("requests.task_order_pdf_download", request_id=request.id)
|
||||
|
||||
body = response.data.decode()
|
||||
assert download_url in body
|
||||
|
||||
|
||||
def test_ccpo_does_not_see_pdf_link_if_no_pdf(user_session, client, pdf_upload):
|
||||
ccpo = UserFactory.from_atat_role("ccpo")
|
||||
user_session(ccpo)
|
||||
|
||||
request = prepare_request_pending_approval(ccpo)
|
||||
|
||||
response = client.get(url_for("requests.approval", request_id=request.id))
|
||||
download_url = url_for("requests.task_order_pdf_download", request_id=request.id)
|
||||
|
||||
body = response.data.decode()
|
||||
assert download_url not in body
|
||||
|
||||
|
||||
def test_task_order_download(app, client, user_session, pdf_upload):
|
||||
user = UserFactory.create()
|
||||
user_session(user)
|
||||
|
||||
attachment = Attachment.attach(pdf_upload)
|
||||
task_order = TaskOrderFactory.create(number="abc123", pdf=attachment)
|
||||
request = RequestFactory.create(task_order=task_order, creator=user)
|
||||
|
||||
# ensure that real data for pdf upload has been flushed to disk
|
||||
pdf_upload.seek(0)
|
||||
pdf_content = pdf_upload.read()
|
||||
pdf_upload.close()
|
||||
full_path = os.path.join(
|
||||
app.config.get("STORAGE_CONTAINER"), attachment.object_name
|
||||
)
|
||||
with open(full_path, "wb") as output_file:
|
||||
output_file.write(pdf_content)
|
||||
output_file.flush()
|
||||
|
||||
response = client.get(
|
||||
url_for("requests.task_order_pdf_download", request_id=request.id)
|
||||
)
|
||||
assert response.data == pdf_content
|
||||
|
||||
|
||||
def test_task_order_download_does_not_exist(client, user_session):
|
||||
user = UserFactory.create()
|
||||
user_session(user)
|
||||
request = RequestFactory.create(creator=user)
|
||||
response = client.get(
|
||||
url_for("requests.task_order_pdf_download", request_id=request.id)
|
||||
)
|
||||
assert response.status_code == 404
|
||||
|
||||
|
||||
def test_can_submit_request_approval(client, user_session):
|
||||
user = UserFactory.from_atat_role("ccpo")
|
||||
user_session(user)
|
||||
request = RequestFactory.create_with_status(
|
||||
status=RequestStatus.PENDING_CCPO_ACCEPTANCE
|
||||
)
|
||||
review_data = RequestReviewFactory.dictionary()
|
||||
review_data["review"] = "approving"
|
||||
response = client.post(
|
||||
url_for("requests.submit_approval", request_id=request.id), data=review_data
|
||||
)
|
||||
assert response.status_code == 302
|
||||
assert request.status == RequestStatus.PENDING_FINANCIAL_VERIFICATION
|
||||
|
||||
|
||||
def test_can_submit_request_denial(client, user_session):
|
||||
user = UserFactory.from_atat_role("ccpo")
|
||||
user_session(user)
|
||||
request = RequestFactory.create_with_status(
|
||||
status=RequestStatus.PENDING_CCPO_ACCEPTANCE
|
||||
)
|
||||
review_data = RequestReviewFactory.dictionary()
|
||||
review_data["review"] = "denying"
|
||||
response = client.post(
|
||||
url_for("requests.submit_approval", request_id=request.id), data=review_data
|
||||
)
|
||||
assert response.status_code == 302
|
||||
assert request.status == RequestStatus.CHANGES_REQUESTED
|
||||
|
||||
|
||||
def test_ccpo_user_can_comment_on_request(client, user_session):
|
||||
user = UserFactory.from_atat_role("ccpo")
|
||||
user_session(user)
|
||||
request = RequestFactory.create_with_status(
|
||||
status=RequestStatus.PENDING_CCPO_ACCEPTANCE
|
||||
)
|
||||
assert len(request.internal_comments) == 0
|
||||
|
||||
comment_text = "This is the greatest request in the history of requests"
|
||||
comment_form_data = {"text": comment_text}
|
||||
response = client.post(
|
||||
url_for("requests.create_internal_comment", request_id=request.id),
|
||||
data=comment_form_data,
|
||||
)
|
||||
assert response.status_code == 302
|
||||
assert len(request.internal_comments) == 1
|
||||
assert request.internal_comments[0].text == comment_text
|
||||
|
||||
|
||||
def test_comment_text_is_required(client, user_session):
|
||||
user = UserFactory.from_atat_role("ccpo")
|
||||
user_session(user)
|
||||
request = RequestFactory.create_with_status(
|
||||
status=RequestStatus.PENDING_CCPO_ACCEPTANCE
|
||||
)
|
||||
assert len(request.internal_comments) == 0
|
||||
|
||||
comment_form_data = {"text": ""}
|
||||
response = client.post(
|
||||
url_for("requests.create_internal_comment", request_id=request.id),
|
||||
data=comment_form_data,
|
||||
)
|
||||
assert response.status_code == 200
|
||||
assert len(request.internal_comments) == 0
|
||||
|
||||
|
||||
def test_other_user_cannot_comment_on_request(client, user_session):
|
||||
user = UserFactory.create()
|
||||
user_session(user)
|
||||
request = RequestFactory.create_with_status(
|
||||
status=RequestStatus.PENDING_CCPO_ACCEPTANCE
|
||||
)
|
||||
|
||||
comment_text = "What is this even"
|
||||
comment_form_data = {"text": comment_text}
|
||||
response = client.post(
|
||||
url_for("requests.create_internal_comment", request_id=request.id),
|
||||
data=comment_form_data,
|
||||
)
|
||||
|
||||
assert response.status_code == 404
|
511
tests/routes/requests/financial_verification.py
Normal file
511
tests/routes/requests/financial_verification.py
Normal file
@@ -0,0 +1,511 @@
|
||||
import pytest
|
||||
from unittest.mock import MagicMock
|
||||
from flask import url_for
|
||||
import datetime
|
||||
|
||||
from atst.eda_client import MockEDAClient
|
||||
from atst.routes.requests.financial_verification import (
|
||||
GetFinancialVerificationForm,
|
||||
UpdateFinancialVerification,
|
||||
SaveFinancialVerificationDraft,
|
||||
)
|
||||
|
||||
from tests.mocks import MOCK_VALID_PE_ID
|
||||
from tests.factories import RequestFactory, UserFactory
|
||||
from atst.forms.exceptions import FormValidationError
|
||||
from atst.domain.requests.financial_verification import (
|
||||
PENumberValidator,
|
||||
TaskOrderNumberValidator,
|
||||
)
|
||||
from atst.models.request_status_event import RequestStatus
|
||||
from atst.domain.requests.query import RequestsQuery
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def fv_data():
|
||||
return {
|
||||
"request-pe_id": "123",
|
||||
"task_order-number": MockEDAClient.MOCK_CONTRACT_NUMBER,
|
||||
"request-fname_co": "Contracting",
|
||||
"request-lname_co": "Officer",
|
||||
"request-email_co": "jane@mail.mil",
|
||||
"request-office_co": "WHS",
|
||||
"request-fname_cor": "Officer",
|
||||
"request-lname_cor": "Representative",
|
||||
"request-email_cor": "jane@mail.mil",
|
||||
"request-office_cor": "WHS",
|
||||
"request-uii_ids": "1234",
|
||||
"request-treasury_code": "00123456",
|
||||
"request-ba_code": "02A",
|
||||
}
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def e_fv_data(pdf_upload):
|
||||
return {
|
||||
"task_order-funding_type": "RDTE",
|
||||
"task_order-funding_type_other": "other",
|
||||
"task_order-expiration_date": "1/1/{}".format(datetime.date.today().year + 1),
|
||||
"task_order-clin_0001": "50000",
|
||||
"task_order-clin_0003": "13000",
|
||||
"task_order-clin_1001": "30000",
|
||||
"task_order-clin_1003": "7000",
|
||||
"task_order-clin_2001": "30000",
|
||||
"task_order-clin_2003": "7000",
|
||||
"task_order-pdf": pdf_upload,
|
||||
}
|
||||
|
||||
|
||||
MANUAL_TO_NUMBER = "DCA10096D0051"
|
||||
|
||||
|
||||
TrueValidator = MagicMock()
|
||||
TrueValidator.validate = MagicMock(return_value=True)
|
||||
|
||||
FalseValidator = MagicMock()
|
||||
FalseValidator.validate = MagicMock(return_value=False)
|
||||
|
||||
|
||||
def test_update_fv(fv_data):
|
||||
request = RequestFactory.create()
|
||||
user = UserFactory.create()
|
||||
data = {**fv_data, "pe_id": MOCK_VALID_PE_ID}
|
||||
|
||||
updated_request = UpdateFinancialVerification(
|
||||
TrueValidator, TrueValidator, user, request, data, is_extended=False
|
||||
).execute()
|
||||
|
||||
assert updated_request.is_pending_ccpo_approval
|
||||
|
||||
|
||||
def test_update_fv_re_enter_pe_number(fv_data):
|
||||
request = RequestFactory.create()
|
||||
user = UserFactory.create()
|
||||
data = {**fv_data, "pe_id": "0101228M"}
|
||||
update_fv = UpdateFinancialVerification(
|
||||
PENumberValidator(), TrueValidator, user, request, data, is_extended=False
|
||||
)
|
||||
|
||||
with pytest.raises(FormValidationError):
|
||||
update_fv.execute()
|
||||
updated_request = update_fv.execute()
|
||||
|
||||
assert updated_request.is_pending_ccpo_approval
|
||||
|
||||
|
||||
def test_update_fv_invalid_task_order_number(fv_data):
|
||||
request = RequestFactory.create()
|
||||
user = UserFactory.create()
|
||||
data = {**fv_data, "task_order-number": MANUAL_TO_NUMBER}
|
||||
update_fv = UpdateFinancialVerification(
|
||||
TrueValidator,
|
||||
TaskOrderNumberValidator(),
|
||||
user,
|
||||
request,
|
||||
data,
|
||||
is_extended=False,
|
||||
)
|
||||
|
||||
with pytest.raises(FormValidationError):
|
||||
update_fv.execute()
|
||||
|
||||
|
||||
def test_draft_without_pe_id(fv_data):
|
||||
request = RequestFactory.create()
|
||||
user = UserFactory.create()
|
||||
data = {"request-uii_ids": "1234"}
|
||||
assert SaveFinancialVerificationDraft(
|
||||
PENumberValidator(),
|
||||
TaskOrderNumberValidator(),
|
||||
user,
|
||||
request,
|
||||
data,
|
||||
is_extended=False,
|
||||
).execute()
|
||||
|
||||
|
||||
def test_update_fv_extended(fv_data, e_fv_data):
|
||||
request = RequestFactory.create()
|
||||
user = UserFactory.create()
|
||||
data = {**fv_data, **e_fv_data}
|
||||
update_fv = UpdateFinancialVerification(
|
||||
TrueValidator, TaskOrderNumberValidator(), user, request, data, is_extended=True
|
||||
)
|
||||
|
||||
assert update_fv.execute()
|
||||
|
||||
|
||||
def test_update_fv_extended_does_not_validate_task_order(fv_data, e_fv_data):
|
||||
request = RequestFactory.create()
|
||||
user = UserFactory.create()
|
||||
data = {**fv_data, **e_fv_data, "task_order-number": "abc123"}
|
||||
update_fv = UpdateFinancialVerification(
|
||||
TrueValidator, TaskOrderNumberValidator(), user, request, data, is_extended=True
|
||||
)
|
||||
|
||||
assert update_fv.execute()
|
||||
|
||||
|
||||
def test_update_fv_missing_extended_data(fv_data):
|
||||
request = RequestFactory.create()
|
||||
user = UserFactory.create()
|
||||
update_fv = UpdateFinancialVerification(
|
||||
TrueValidator,
|
||||
TaskOrderNumberValidator(),
|
||||
user,
|
||||
request,
|
||||
fv_data,
|
||||
is_extended=True,
|
||||
)
|
||||
|
||||
with pytest.raises(FormValidationError):
|
||||
update_fv.execute()
|
||||
|
||||
|
||||
def test_update_fv_submission(fv_data):
|
||||
request = RequestFactory.create()
|
||||
user = UserFactory.create()
|
||||
updated_request = UpdateFinancialVerification(
|
||||
TrueValidator, TrueValidator, user, request, fv_data
|
||||
).execute()
|
||||
assert updated_request
|
||||
|
||||
|
||||
def test_save_empty_draft():
|
||||
request = RequestFactory.create()
|
||||
user = UserFactory.create()
|
||||
save_draft = SaveFinancialVerificationDraft(
|
||||
TrueValidator, TrueValidator, user, request, {}, is_extended=False
|
||||
)
|
||||
|
||||
assert save_draft.execute()
|
||||
|
||||
|
||||
def test_save_draft_with_ba_code():
|
||||
request = RequestFactory.create()
|
||||
user = UserFactory.create()
|
||||
data = {"ba_code": "02A"}
|
||||
save_draft = SaveFinancialVerificationDraft(
|
||||
TrueValidator, TrueValidator, user, request, data, is_extended=False
|
||||
)
|
||||
|
||||
assert save_draft.execute()
|
||||
|
||||
|
||||
def test_save_draft_allows_invalid_data():
|
||||
request = RequestFactory.create()
|
||||
user = UserFactory.create()
|
||||
data = {
|
||||
"task_order-number": MANUAL_TO_NUMBER,
|
||||
"request-pe_id": "123",
|
||||
"request-ba_code": "a",
|
||||
}
|
||||
|
||||
assert SaveFinancialVerificationDraft(
|
||||
PENumberValidator(),
|
||||
TaskOrderNumberValidator(),
|
||||
user,
|
||||
request,
|
||||
data,
|
||||
is_extended=True,
|
||||
).execute()
|
||||
|
||||
|
||||
def test_save_draft_and_then_submit():
|
||||
request = RequestFactory.create()
|
||||
user = UserFactory.create()
|
||||
data = {"ba_code": "02A"}
|
||||
updated_request = SaveFinancialVerificationDraft(
|
||||
TrueValidator, TrueValidator, user, request, data, is_extended=False
|
||||
).execute()
|
||||
|
||||
with pytest.raises(FormValidationError):
|
||||
UpdateFinancialVerification(
|
||||
TrueValidator, TrueValidator, user, updated_request, data
|
||||
).execute()
|
||||
|
||||
|
||||
def test_updated_request_has_pdf(fv_data, e_fv_data):
|
||||
request = RequestFactory.create()
|
||||
user = UserFactory.create()
|
||||
data = {**fv_data, **e_fv_data, "task_order-number": MANUAL_TO_NUMBER}
|
||||
updated_request = UpdateFinancialVerification(
|
||||
TrueValidator, TrueValidator, user, request, data, is_extended=True
|
||||
).execute()
|
||||
assert updated_request.task_order.pdf
|
||||
|
||||
|
||||
def test_can_save_draft_with_just_pdf(e_fv_data):
|
||||
request = RequestFactory.create()
|
||||
user = UserFactory.create()
|
||||
data = {"task_order-pdf": e_fv_data["task_order-pdf"]}
|
||||
SaveFinancialVerificationDraft(
|
||||
TrueValidator, TrueValidator, user, request, data, is_extended=True
|
||||
).execute()
|
||||
|
||||
form = GetFinancialVerificationForm(user, request, is_extended=True).execute()
|
||||
assert form.task_order.pdf
|
||||
|
||||
|
||||
def test_task_order_info_present_in_extended_form(fv_data, e_fv_data):
|
||||
request = RequestFactory.create()
|
||||
user = UserFactory.create()
|
||||
data = {
|
||||
"task_order-clin_0001": "1",
|
||||
"task_order-number": fv_data["task_order-number"],
|
||||
}
|
||||
SaveFinancialVerificationDraft(
|
||||
TrueValidator, TrueValidator, user, request, data, is_extended=True
|
||||
).execute()
|
||||
|
||||
form = GetFinancialVerificationForm(user, request, is_extended=True).execute()
|
||||
assert form.task_order.clin_0001.data
|
||||
|
||||
|
||||
def test_update_ignores_empty_values(fv_data, e_fv_data):
|
||||
request = RequestFactory.create()
|
||||
user = UserFactory.create()
|
||||
data = {**fv_data, **e_fv_data, "task_order-funding_type": ""}
|
||||
SaveFinancialVerificationDraft(
|
||||
TrueValidator, TrueValidator, user, request, data, is_extended=True
|
||||
).execute()
|
||||
|
||||
|
||||
def test_can_save_draft_with_funding_type(fv_data, e_fv_data):
|
||||
request = RequestFactory.create()
|
||||
user = UserFactory.create()
|
||||
data = {
|
||||
"task_order-number": fv_data["task_order-number"],
|
||||
"task_order-funding_type": e_fv_data["task_order-funding_type"],
|
||||
}
|
||||
updated_request = SaveFinancialVerificationDraft(
|
||||
TrueValidator, TrueValidator, user, request, data, is_extended=False
|
||||
).execute()
|
||||
|
||||
assert updated_request.task_order.funding_type
|
||||
|
||||
|
||||
def test_update_fv_route(client, user_session, fv_data):
|
||||
user = UserFactory.create()
|
||||
request = RequestFactory.create(creator=user)
|
||||
user_session(user)
|
||||
response = client.post(
|
||||
url_for("requests.financial_verification", request_id=request.id),
|
||||
data=fv_data,
|
||||
follow_redirects=False,
|
||||
)
|
||||
|
||||
assert response.status_code == 200
|
||||
|
||||
|
||||
def test_save_fv_draft_route(client, user_session, fv_data):
|
||||
user = UserFactory.create()
|
||||
request = RequestFactory.create(creator=user)
|
||||
user_session(user)
|
||||
response = client.post(
|
||||
url_for("requests.save_financial_verification_draft", request_id=request.id),
|
||||
data=fv_data,
|
||||
follow_redirects=True,
|
||||
)
|
||||
|
||||
assert response.status_code == 200
|
||||
|
||||
|
||||
def test_get_fv_form_route(client, user_session, fv_data):
|
||||
user = UserFactory.create()
|
||||
request = RequestFactory.create(creator=user)
|
||||
user_session(user)
|
||||
response = client.get(
|
||||
url_for("requests.financial_verification", request_id=request.id),
|
||||
data=fv_data,
|
||||
follow_redirects=False,
|
||||
)
|
||||
|
||||
assert response.status_code == 200
|
||||
|
||||
|
||||
def test_manual_task_order_triggers_extended_form(
|
||||
client, user_session, fv_data, e_fv_data
|
||||
):
|
||||
user = UserFactory.create()
|
||||
request = RequestFactory.create(creator=user)
|
||||
|
||||
data = {**fv_data, **e_fv_data, "task_order-number": MANUAL_TO_NUMBER}
|
||||
|
||||
UpdateFinancialVerification(
|
||||
TrueValidator, TrueValidator, user, request, data, is_extended=True
|
||||
).execute()
|
||||
|
||||
user_session(user)
|
||||
response = client.get(
|
||||
url_for("requests.financial_verification", request_id=request.id),
|
||||
data=fv_data,
|
||||
follow_redirects=False,
|
||||
)
|
||||
assert "extended" in response.headers["Location"]
|
||||
|
||||
|
||||
def test_manual_to_does_not_trigger_approval(client, user_session, fv_data, e_fv_data):
|
||||
user = UserFactory.create()
|
||||
request = RequestFactory.create(creator=user)
|
||||
data = {
|
||||
**fv_data,
|
||||
**e_fv_data,
|
||||
"task_order-number": MANUAL_TO_NUMBER,
|
||||
"request-pe_id": "0101228N",
|
||||
}
|
||||
user_session(user)
|
||||
client.post(
|
||||
url_for(
|
||||
"requests.financial_verification", request_id=request.id, extended=True
|
||||
),
|
||||
data=data,
|
||||
follow_redirects=True,
|
||||
)
|
||||
|
||||
updated_request = RequestsQuery.get(request.id)
|
||||
assert updated_request.status != RequestStatus.APPROVED
|
||||
|
||||
|
||||
def test_eda_task_order_does_trigger_approval(client, user_session, fv_data, e_fv_data):
|
||||
user = UserFactory.create()
|
||||
request = RequestFactory.create(creator=user)
|
||||
data = {
|
||||
**fv_data,
|
||||
**e_fv_data,
|
||||
"task_order-number": MockEDAClient.MOCK_CONTRACT_NUMBER,
|
||||
"request-pe_id": "0101228N",
|
||||
}
|
||||
user_session(user)
|
||||
client.post(
|
||||
url_for(
|
||||
"requests.financial_verification", request_id=request.id, extended=True
|
||||
),
|
||||
data=data,
|
||||
follow_redirects=True,
|
||||
)
|
||||
|
||||
updated_request = RequestsQuery.get(request.id)
|
||||
assert updated_request.status == RequestStatus.APPROVED
|
||||
|
||||
|
||||
def test_attachment_on_non_extended_form(client, user_session, fv_data, e_fv_data):
|
||||
user = UserFactory.create()
|
||||
request = RequestFactory.create(creator=user)
|
||||
data = {
|
||||
**fv_data,
|
||||
**e_fv_data,
|
||||
"task_order-number": MockEDAClient.MOCK_CONTRACT_NUMBER,
|
||||
"request-pe_id": "0101228N",
|
||||
}
|
||||
user_session(user)
|
||||
client.post(
|
||||
url_for(
|
||||
"requests.financial_verification", request_id=request.id, extended=True
|
||||
),
|
||||
data=data,
|
||||
follow_redirects=True,
|
||||
)
|
||||
|
||||
response = client.get(
|
||||
url_for("requests.financial_verification", request_id=request.id)
|
||||
)
|
||||
|
||||
assert response.status_code == 200
|
||||
|
||||
|
||||
def test_task_order_number_persists_in_form(fv_data, e_fv_data):
|
||||
user = UserFactory.create()
|
||||
request = RequestFactory.create(creator=user)
|
||||
data = {
|
||||
**fv_data,
|
||||
"task_order-number": MANUAL_TO_NUMBER,
|
||||
"request-pe_id": "0101228N",
|
||||
}
|
||||
|
||||
try:
|
||||
UpdateFinancialVerification(
|
||||
TrueValidator, FalseValidator, user, request, data, is_extended=False
|
||||
).execute()
|
||||
except FormValidationError:
|
||||
pass
|
||||
|
||||
form = GetFinancialVerificationForm(user, request, is_extended=True).execute()
|
||||
assert form.task_order.number.data == MANUAL_TO_NUMBER
|
||||
|
||||
|
||||
def test_can_submit_once_to_details_are_entered(fv_data, e_fv_data):
|
||||
user = UserFactory.create()
|
||||
request = RequestFactory.create(creator=user)
|
||||
data = {
|
||||
**fv_data,
|
||||
"task_order-number": MANUAL_TO_NUMBER,
|
||||
"request-pe_id": "0101228N",
|
||||
}
|
||||
|
||||
try:
|
||||
UpdateFinancialVerification(
|
||||
TrueValidator, FalseValidator, user, request, data, is_extended=False
|
||||
).execute()
|
||||
except FormValidationError:
|
||||
pass
|
||||
|
||||
data = {
|
||||
**fv_data,
|
||||
**e_fv_data,
|
||||
"task_order-number": MANUAL_TO_NUMBER,
|
||||
"request-pe_id": "0101228N",
|
||||
}
|
||||
assert UpdateFinancialVerification(
|
||||
TrueValidator, TrueValidator, user, request, data, is_extended=True
|
||||
).execute()
|
||||
|
||||
|
||||
def test_existing_task_order_with_pdf(fv_data, e_fv_data, client, user_session):
|
||||
# Use finver route to create initial TO #1, complete with PDF
|
||||
user = UserFactory.create()
|
||||
request = RequestFactory.create(creator=user)
|
||||
data = {**fv_data, **e_fv_data, "task_order-number": MANUAL_TO_NUMBER}
|
||||
UpdateFinancialVerification(
|
||||
TrueValidator, TaskOrderNumberValidator(), user, request, data, is_extended=True
|
||||
).execute()
|
||||
|
||||
# Save draft on a new finver form, but with same number as TO #1
|
||||
user = UserFactory.create()
|
||||
request = RequestFactory.create(creator=user)
|
||||
data = {"task_order-number": MANUAL_TO_NUMBER}
|
||||
SaveFinancialVerificationDraft(
|
||||
TrueValidator,
|
||||
TaskOrderNumberValidator(),
|
||||
user,
|
||||
request,
|
||||
data,
|
||||
is_extended=False,
|
||||
).execute()
|
||||
|
||||
# Get finver form
|
||||
user_session(user)
|
||||
response = client.get(
|
||||
url_for("requests.financial_verification", request_id=request.id),
|
||||
follow_redirects=True,
|
||||
)
|
||||
|
||||
assert response.status_code == 200
|
||||
|
||||
|
||||
def test_pdf_clearing(fv_data, e_fv_data, pdf_upload, pdf_upload2):
|
||||
user = UserFactory.create()
|
||||
request = RequestFactory.create(creator=user)
|
||||
data = {**fv_data, **e_fv_data, "task_order-pdf": pdf_upload}
|
||||
|
||||
SaveFinancialVerificationDraft(
|
||||
TrueValidator, TrueValidator, user, request, data, is_extended=True
|
||||
).execute()
|
||||
|
||||
data = {**data, "task_order-pdf": pdf_upload2}
|
||||
UpdateFinancialVerification(
|
||||
TrueValidator, TrueValidator, user, request, data, is_extended=True
|
||||
).execute()
|
||||
|
||||
form = GetFinancialVerificationForm(user, request, is_extended=True).execute()
|
||||
assert form.task_order.pdf.data == pdf_upload2.filename
|
28
tests/routes/requests/index.py
Normal file
28
tests/routes/requests/index.py
Normal file
@@ -0,0 +1,28 @@
|
||||
from flask import url_for
|
||||
|
||||
from atst.routes.requests.index import RequestsIndex
|
||||
from tests.factories import RequestFactory, UserFactory
|
||||
from atst.domain.requests import Requests
|
||||
|
||||
|
||||
def test_action_required_mission_owner():
|
||||
creator = UserFactory.create()
|
||||
requests = RequestFactory.create_batch(5, creator=creator)
|
||||
Requests.submit(requests[0])
|
||||
Requests.approve_and_create_workspace(requests[1])
|
||||
|
||||
context = RequestsIndex(creator).execute()
|
||||
|
||||
assert context["requests"][0]["action_required"] == False
|
||||
|
||||
|
||||
def test_action_required_ccpo():
|
||||
creator = UserFactory.create()
|
||||
requests = RequestFactory.create_batch(5, creator=creator)
|
||||
Requests.submit(requests[0])
|
||||
Requests.approve_and_create_workspace(requests[1])
|
||||
|
||||
ccpo = UserFactory.from_atat_role("ccpo")
|
||||
context = RequestsIndex(ccpo).execute()
|
||||
|
||||
assert context["num_action_required"] == 1
|
37
tests/routes/requests/requests_form/details.py
Normal file
37
tests/routes/requests/requests_form/details.py
Normal file
@@ -0,0 +1,37 @@
|
||||
import re
|
||||
from flask import url_for
|
||||
|
||||
from atst.models.request_status_event import RequestStatus
|
||||
|
||||
from tests.factories import RequestFactory, TaskOrderFactory, UserFactory
|
||||
|
||||
|
||||
def test_can_show_financial_data(client, user_session):
|
||||
user = UserFactory.create()
|
||||
user_session(user)
|
||||
|
||||
task_order = TaskOrderFactory.create()
|
||||
request = RequestFactory.create_with_status(
|
||||
status=RequestStatus.PENDING_CCPO_APPROVAL, task_order=task_order, creator=user
|
||||
)
|
||||
response = client.get(
|
||||
url_for("requests.view_request_details", request_id=request.id)
|
||||
)
|
||||
|
||||
body = response.data.decode()
|
||||
assert re.search(r">\s+Financial Verification\s+<", body)
|
||||
|
||||
|
||||
def test_can_not_show_financial_data(client, user_session):
|
||||
user = UserFactory.create()
|
||||
user_session(user)
|
||||
|
||||
request = RequestFactory.create_with_status(
|
||||
status=RequestStatus.PENDING_CCPO_ACCEPTANCE, creator=user
|
||||
)
|
||||
response = client.get(
|
||||
url_for("requests.view_request_details", request_id=request.id)
|
||||
)
|
||||
|
||||
body = response.data.decode()
|
||||
assert not re.search(r">\s+Financial Verification\s+<", body)
|
52
tests/routes/requests/requests_form/edit.py
Normal file
52
tests/routes/requests/requests_form/edit.py
Normal file
@@ -0,0 +1,52 @@
|
||||
from tests.factories import UserFactory, RequestFactory
|
||||
from atst.models.request_status_event import RequestStatus
|
||||
|
||||
|
||||
def test_creator_pending_finver(client, user_session):
|
||||
request = RequestFactory.create_with_status(
|
||||
RequestStatus.PENDING_FINANCIAL_VERIFICATION
|
||||
)
|
||||
user_session(request.creator)
|
||||
response = client.get(
|
||||
"/requests/edit/{}".format(request.id), follow_redirects=False
|
||||
)
|
||||
assert "verify" in response.location
|
||||
|
||||
|
||||
def test_creator_pending_finver_changes(client, user_session):
|
||||
request = RequestFactory.create_with_status(
|
||||
RequestStatus.CHANGES_REQUESTED_TO_FINVER
|
||||
)
|
||||
user_session(request.creator)
|
||||
response = client.get(
|
||||
"/requests/edit/{}".format(request.id), follow_redirects=False
|
||||
)
|
||||
assert "verify" in response.location
|
||||
|
||||
|
||||
def test_creator_approved(client, user_session):
|
||||
request = RequestFactory.create_with_status(RequestStatus.APPROVED)
|
||||
user_session(request.creator)
|
||||
response = client.get(
|
||||
"/requests/edit/{}".format(request.id), follow_redirects=False
|
||||
)
|
||||
assert "details" in response.location
|
||||
|
||||
|
||||
def test_creator_approved(client, user_session):
|
||||
request = RequestFactory.create_with_status(RequestStatus.STARTED)
|
||||
user_session(request.creator)
|
||||
response = client.get(
|
||||
"/requests/edit/{}".format(request.id), follow_redirects=False
|
||||
)
|
||||
assert "new" in response.location
|
||||
|
||||
|
||||
def test_ccpo(client, user_session):
|
||||
ccpo = UserFactory.from_atat_role("ccpo")
|
||||
request = RequestFactory.create_with_status(RequestStatus.STARTED)
|
||||
user_session(ccpo)
|
||||
response = client.get(
|
||||
"/requests/edit/{}".format(request.id), follow_redirects=False
|
||||
)
|
||||
assert "approval" in response.location
|
247
tests/routes/requests/requests_form/new.py
Normal file
247
tests/routes/requests/requests_form/new.py
Normal file
@@ -0,0 +1,247 @@
|
||||
import datetime
|
||||
import re
|
||||
from tests.factories import (
|
||||
RequestFactory,
|
||||
UserFactory,
|
||||
RequestRevisionFactory,
|
||||
RequestStatusEventFactory,
|
||||
RequestReviewFactory,
|
||||
)
|
||||
from atst.models.request_status_event import RequestStatus
|
||||
from atst.domain.roles import Roles
|
||||
from atst.domain.requests import Requests
|
||||
from urllib.parse import urlencode
|
||||
|
||||
from tests.assert_util import dict_contains
|
||||
|
||||
ERROR_CLASS = "alert--error"
|
||||
|
||||
|
||||
def test_submit_invalid_request_form(monkeypatch, client, user_session):
|
||||
user_session()
|
||||
response = client.post(
|
||||
"/requests/new/1",
|
||||
headers={"Content-Type": "application/x-www-form-urlencoded"},
|
||||
data="total_ram=5",
|
||||
)
|
||||
assert re.search(ERROR_CLASS, response.data.decode())
|
||||
|
||||
|
||||
def test_submit_valid_request_form(monkeypatch, client, user_session):
|
||||
user_session()
|
||||
monkeypatch.setattr(
|
||||
"atst.forms.new_request.DetailsOfUseForm.validate", lambda s: True
|
||||
)
|
||||
|
||||
response = client.post(
|
||||
"/requests/new/1",
|
||||
headers={"Content-Type": "application/x-www-form-urlencoded"},
|
||||
data="meaning=42",
|
||||
)
|
||||
assert "/requests/new/2" in response.headers.get("Location")
|
||||
|
||||
|
||||
def test_owner_can_view_request(client, user_session):
|
||||
user = UserFactory.create()
|
||||
user_session(user)
|
||||
request = RequestFactory.create(creator=user)
|
||||
|
||||
response = client.get(
|
||||
"/requests/new/1/{}".format(request.id), follow_redirects=True
|
||||
)
|
||||
|
||||
assert response.status_code == 200
|
||||
|
||||
|
||||
def test_non_owner_cannot_view_request(client, user_session):
|
||||
user = UserFactory.create()
|
||||
user_session(user)
|
||||
request = RequestFactory.create()
|
||||
|
||||
response = client.get(
|
||||
"/requests/new/1/{}".format(request.id), follow_redirects=True
|
||||
)
|
||||
|
||||
assert response.status_code == 404
|
||||
|
||||
|
||||
def test_ccpo_can_view_request(client, user_session):
|
||||
ccpo = Roles.get("ccpo")
|
||||
user = UserFactory.create(atat_role=ccpo)
|
||||
user_session(user)
|
||||
request = RequestFactory.create()
|
||||
|
||||
response = client.get(
|
||||
"/requests/new/1/{}".format(request.id), follow_redirects=True
|
||||
)
|
||||
|
||||
assert response.status_code == 200
|
||||
|
||||
|
||||
def test_nonexistent_request(client, user_session):
|
||||
user_session()
|
||||
response = client.get("/requests/new/1/foo", follow_redirects=True)
|
||||
|
||||
assert response.status_code == 404
|
||||
|
||||
|
||||
def test_creator_info_is_autopopulated_for_existing_request(
|
||||
monkeypatch, client, user_session
|
||||
):
|
||||
user = UserFactory.create()
|
||||
user_session(user)
|
||||
request = RequestFactory.create(creator=user, initial_revision={})
|
||||
|
||||
response = client.get("/requests/new/2/{}".format(request.id))
|
||||
body = response.data.decode()
|
||||
prepopulated_values = [
|
||||
"first_name",
|
||||
"last_name",
|
||||
"email",
|
||||
"phone_number",
|
||||
"date_latest_training",
|
||||
]
|
||||
for attr in prepopulated_values:
|
||||
value = getattr(user, attr)
|
||||
if isinstance(value, datetime.date):
|
||||
value = value.strftime("%m/%d/%Y")
|
||||
assert "initial-value='{}'".format(value) in body
|
||||
|
||||
|
||||
def test_creator_info_is_autopopulated_for_new_request(
|
||||
monkeypatch, client, user_session
|
||||
):
|
||||
user = UserFactory.create()
|
||||
user_session(user)
|
||||
|
||||
response = client.get("/requests/new/2")
|
||||
body = response.data.decode()
|
||||
assert "initial-value='{}'".format(user.first_name) in body
|
||||
assert "initial-value='{}'".format(user.last_name) in body
|
||||
assert "initial-value='{}'".format(user.email) in body
|
||||
|
||||
|
||||
def test_non_creator_info_is_not_autopopulated(monkeypatch, client, user_session):
|
||||
user = UserFactory.create()
|
||||
creator = UserFactory.create()
|
||||
user_session(user)
|
||||
request = RequestFactory.create(creator=creator, initial_revision={})
|
||||
|
||||
response = client.get("/requests/new/2/{}".format(request.id))
|
||||
body = response.data.decode()
|
||||
assert not user.first_name in body
|
||||
assert not user.last_name in body
|
||||
assert not user.email in body
|
||||
|
||||
|
||||
def test_am_poc_causes_poc_to_be_autopopulated(client, user_session):
|
||||
creator = UserFactory.create()
|
||||
user_session(creator)
|
||||
request = RequestFactory.create(creator=creator, initial_revision={})
|
||||
client.post(
|
||||
"/requests/new/3/{}".format(request.id),
|
||||
headers={"Content-Type": "application/x-www-form-urlencoded"},
|
||||
data="am_poc=yes",
|
||||
)
|
||||
request = Requests.get(creator, request.id)
|
||||
assert request.body["primary_poc"]["dodid_poc"] == creator.dod_id
|
||||
|
||||
|
||||
def test_not_am_poc_requires_poc_info_to_be_completed(client, user_session):
|
||||
creator = UserFactory.create()
|
||||
user_session(creator)
|
||||
request = RequestFactory.create(creator=creator, initial_revision={})
|
||||
response = client.post(
|
||||
"/requests/new/3/{}".format(request.id),
|
||||
headers={"Content-Type": "application/x-www-form-urlencoded"},
|
||||
data="am_poc=no",
|
||||
follow_redirects=True,
|
||||
)
|
||||
assert ERROR_CLASS in response.data.decode()
|
||||
|
||||
|
||||
def test_not_am_poc_allows_user_to_fill_in_poc_info(client, user_session):
|
||||
creator = UserFactory.create()
|
||||
user_session(creator)
|
||||
request = RequestFactory.create(creator=creator, initial_revision={})
|
||||
poc_input = {
|
||||
"am_poc": "no",
|
||||
"fname_poc": "test",
|
||||
"lname_poc": "user",
|
||||
"email_poc": "test.user@mail.com",
|
||||
"dodid_poc": "1234567890",
|
||||
}
|
||||
response = client.post(
|
||||
"/requests/new/3/{}".format(request.id),
|
||||
headers={"Content-Type": "application/x-www-form-urlencoded"},
|
||||
data=urlencode(poc_input),
|
||||
)
|
||||
assert ERROR_CLASS not in response.data.decode()
|
||||
|
||||
|
||||
def test_poc_details_can_be_autopopulated_on_new_request(client, user_session):
|
||||
creator = UserFactory.create()
|
||||
user_session(creator)
|
||||
response = client.post(
|
||||
"/requests/new/3",
|
||||
headers={"Content-Type": "application/x-www-form-urlencoded"},
|
||||
data="am_poc=yes",
|
||||
)
|
||||
request_id = response.headers["Location"].split("/")[-1]
|
||||
request = Requests.get(creator, request_id)
|
||||
|
||||
assert request.body["primary_poc"]["dodid_poc"] == creator.dod_id
|
||||
|
||||
|
||||
def test_poc_autofill_checks_information_about_you_form_first(client, user_session):
|
||||
creator = UserFactory.create()
|
||||
user_session(creator)
|
||||
request = RequestFactory.create(
|
||||
creator=creator,
|
||||
initial_revision=dict(
|
||||
fname_request="Alice",
|
||||
lname_request="Adams",
|
||||
email_request="alice.adams@mail.mil",
|
||||
),
|
||||
)
|
||||
poc_input = {"am_poc": "yes"}
|
||||
client.post(
|
||||
"/requests/new/3/{}".format(request.id),
|
||||
headers={"Content-Type": "application/x-www-form-urlencoded"},
|
||||
data=urlencode(poc_input),
|
||||
)
|
||||
request = Requests.get(creator, request.id)
|
||||
assert dict_contains(
|
||||
request.body["primary_poc"],
|
||||
{
|
||||
"fname_poc": "Alice",
|
||||
"lname_poc": "Adams",
|
||||
"email_poc": "alice.adams@mail.mil",
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
def test_can_review_data(user_session, client):
|
||||
creator = UserFactory.create()
|
||||
user_session(creator)
|
||||
request = RequestFactory.create(creator=creator)
|
||||
response = client.get("/requests/new/4/{}".format(request.id))
|
||||
body = response.data.decode()
|
||||
# assert a sampling of the request data is on the review page
|
||||
assert request.body["primary_poc"]["fname_poc"] in body
|
||||
assert request.body["information_about_you"]["email_request"] in body
|
||||
|
||||
|
||||
def test_displays_ccpo_review_comment(user_session, client):
|
||||
creator = UserFactory.create()
|
||||
ccpo = UserFactory.from_atat_role("ccpo")
|
||||
user_session(creator)
|
||||
request = RequestFactory.create(creator=creator)
|
||||
request = Requests.set_status(request, RequestStatus.CHANGES_REQUESTED)
|
||||
review_comment = "add all of the correct info, instead of the incorrect info"
|
||||
RequestReviewFactory.create(
|
||||
reviewer=ccpo, comment=review_comment, status=request.status_events[-1]
|
||||
)
|
||||
response = client.get("/requests/new/1/{}".format(request.id))
|
||||
body = response.data.decode()
|
||||
assert review_comment in body
|
43
tests/routes/requests/requests_form/submit.py
Normal file
43
tests/routes/requests/requests_form/submit.py
Normal file
@@ -0,0 +1,43 @@
|
||||
import pytest
|
||||
from tests.mocks import MOCK_USER
|
||||
from tests.factories import RequestFactory
|
||||
from atst.models.request_status_event import RequestStatus
|
||||
|
||||
|
||||
def _mock_func(*args, **kwargs):
|
||||
return RequestFactory.create()
|
||||
|
||||
|
||||
def test_submit_reviewed_request(monkeypatch, client, user_session):
|
||||
user_session()
|
||||
monkeypatch.setattr("atst.domain.requests.Requests.get", _mock_func)
|
||||
monkeypatch.setattr("atst.domain.requests.Requests.submit", _mock_func)
|
||||
monkeypatch.setattr("atst.models.request.Request.status", "pending")
|
||||
# this just needs to send a known invalid form value
|
||||
response = client.post(
|
||||
"/requests/submit/1",
|
||||
headers={"Content-Type": "application/x-www-form-urlencoded"},
|
||||
data="",
|
||||
follow_redirects=False,
|
||||
)
|
||||
assert "/requests" in response.headers["Location"]
|
||||
assert "modal=pendingCCPOAcceptance" in response.headers["Location"]
|
||||
|
||||
|
||||
def test_submit_autoapproved_reviewed_request(monkeypatch, client, user_session):
|
||||
user_session()
|
||||
monkeypatch.setattr("atst.domain.requests.Requests.get", _mock_func)
|
||||
monkeypatch.setattr("atst.domain.requests.Requests.submit", _mock_func)
|
||||
monkeypatch.setattr(
|
||||
"atst.models.request.Request.status",
|
||||
RequestStatus.PENDING_FINANCIAL_VERIFICATION,
|
||||
)
|
||||
response = client.post(
|
||||
"/requests/submit/1",
|
||||
headers={"Content-Type": "application/x-www-form-urlencoded"},
|
||||
data="",
|
||||
follow_redirects=False,
|
||||
)
|
||||
assert (
|
||||
"/requests?modal=pendingFinancialVerification" in response.headers["Location"]
|
||||
)
|
Reference in New Issue
Block a user