Merge pull request #238 from dod-ccpo/request-schema-#159719829
Request schema #159719829
This commit is contained in:
@@ -1,20 +0,0 @@
|
||||
import pytest
|
||||
import pendulum
|
||||
|
||||
from atst.domain.date import parse_date
|
||||
|
||||
|
||||
def test_date_with_slashes():
|
||||
date_str = "1/2/2020"
|
||||
assert parse_date(date_str) == pendulum.date(2020, 1, 2)
|
||||
|
||||
|
||||
def test_date_with_dashes():
|
||||
date_str = "2020-1-2"
|
||||
assert parse_date(date_str) == pendulum.date(2020, 1, 2)
|
||||
|
||||
|
||||
def test_invalid_date():
|
||||
date_str = "This is not a valid data"
|
||||
with pytest.raises(ValueError):
|
||||
parse_date(date_str)
|
@@ -12,6 +12,7 @@ from tests.factories import (
|
||||
UserFactory,
|
||||
RequestStatusEventFactory,
|
||||
TaskOrderFactory,
|
||||
RequestRevisionFactory,
|
||||
)
|
||||
|
||||
|
||||
@@ -20,10 +21,11 @@ def new_request(session):
|
||||
return RequestFactory.create()
|
||||
|
||||
|
||||
def test_can_get_request(new_request):
|
||||
request = Requests.get(new_request.creator, new_request.id)
|
||||
def test_can_get_request():
|
||||
factory_req = RequestFactory.create()
|
||||
request = Requests.get(factory_req.creator, factory_req.id)
|
||||
|
||||
assert request.id == new_request.id
|
||||
assert request.id == factory_req.id
|
||||
|
||||
|
||||
def test_nonexistent_request_raises():
|
||||
@@ -37,36 +39,41 @@ def test_new_request_has_started_status():
|
||||
assert request.status == RequestStatus.STARTED
|
||||
|
||||
|
||||
def test_auto_approve_less_than_1m(new_request):
|
||||
new_request.body = {"details_of_use": {"dollar_value": 999999}}
|
||||
def test_auto_approve_less_than_1m():
|
||||
new_request = RequestFactory.create(initial_revision={"dollar_value": 999999})
|
||||
request = Requests.submit(new_request)
|
||||
|
||||
assert request.status == RequestStatus.PENDING_FINANCIAL_VERIFICATION
|
||||
|
||||
|
||||
def test_dont_auto_approve_if_dollar_value_is_1m_or_above(new_request):
|
||||
new_request.body = {"details_of_use": {"dollar_value": 1000000}}
|
||||
def test_dont_auto_approve_if_dollar_value_is_1m_or_above():
|
||||
new_request = RequestFactory.create(initial_revision={"dollar_value": 1000000})
|
||||
request = Requests.submit(new_request)
|
||||
|
||||
assert request.status == RequestStatus.PENDING_CCPO_APPROVAL
|
||||
|
||||
|
||||
def test_dont_auto_approve_if_no_dollar_value_specified(new_request):
|
||||
new_request.body = {"details_of_use": {}}
|
||||
def test_dont_auto_approve_if_no_dollar_value_specified():
|
||||
new_request = RequestFactory.create(initial_revision={})
|
||||
request = Requests.submit(new_request)
|
||||
|
||||
assert request.status == RequestStatus.PENDING_CCPO_APPROVAL
|
||||
|
||||
|
||||
def test_should_allow_submission(new_request):
|
||||
def test_should_allow_submission():
|
||||
new_request = RequestFactory.create()
|
||||
|
||||
assert Requests.should_allow_submission(new_request)
|
||||
|
||||
RequestStatusEventFactory.create(
|
||||
request=new_request, new_status=RequestStatus.CHANGES_REQUESTED
|
||||
request=new_request,
|
||||
new_status=RequestStatus.CHANGES_REQUESTED,
|
||||
revision=new_request.latest_revision,
|
||||
)
|
||||
assert Requests.should_allow_submission(new_request)
|
||||
|
||||
del new_request.body["details_of_use"]
|
||||
# new, blank revision
|
||||
RequestRevisionFactory.create(request=new_request)
|
||||
assert not Requests.should_allow_submission(new_request)
|
||||
|
||||
|
||||
@@ -96,6 +103,7 @@ def test_status_count(session):
|
||||
RequestStatusEventFactory.create(
|
||||
sequence=2,
|
||||
request_id=request2.id,
|
||||
revision=request2.latest_revision,
|
||||
new_status=RequestStatus.PENDING_FINANCIAL_VERIFICATION,
|
||||
)
|
||||
|
||||
@@ -164,3 +172,9 @@ def test_update_financial_verification_with_invalid_task_order():
|
||||
request.body["financial_verification"]["task_order_number"]
|
||||
== request_financial_data["task_order_number"]
|
||||
)
|
||||
|
||||
|
||||
def test_set_status_sets_revision():
|
||||
request = RequestFactory.create()
|
||||
Requests.set_status(request, RequestStatus.APPROVED)
|
||||
assert request.latest_revision == request.status_events[-1].revision
|
||||
|
@@ -2,9 +2,11 @@ import random
|
||||
import string
|
||||
import factory
|
||||
from uuid import uuid4
|
||||
import datetime
|
||||
|
||||
from atst.forms.data import SERVICE_BRANCHES
|
||||
from atst.models.request import Request
|
||||
from atst.models.request_revision import RequestRevision
|
||||
from atst.models.request_status_event import RequestStatusEvent, RequestStatus
|
||||
from atst.models.pe_number import PENumber
|
||||
from atst.models.task_order import TaskOrder
|
||||
@@ -46,57 +48,83 @@ class RequestStatusEventFactory(factory.alchemy.SQLAlchemyModelFactory):
|
||||
sequence = 1
|
||||
|
||||
|
||||
class RequestRevisionFactory(factory.alchemy.SQLAlchemyModelFactory):
|
||||
class Meta:
|
||||
model = RequestRevision
|
||||
|
||||
id = factory.Sequence(lambda x: uuid4())
|
||||
|
||||
|
||||
class RequestFactory(factory.alchemy.SQLAlchemyModelFactory):
|
||||
class Meta:
|
||||
model = Request
|
||||
|
||||
id = factory.Sequence(lambda x: uuid4())
|
||||
status_events = factory.RelatedFactory(
|
||||
RequestStatusEventFactory, "request", new_status=RequestStatus.STARTED
|
||||
)
|
||||
creator = factory.SubFactory(UserFactory)
|
||||
body = factory.LazyAttribute(lambda r: RequestFactory.build_request_body(r.creator))
|
||||
revisions = factory.LazyAttribute(
|
||||
lambda r: [RequestFactory.create_initial_revision(r)]
|
||||
)
|
||||
status_events = factory.RelatedFactory(
|
||||
RequestStatusEventFactory,
|
||||
"request",
|
||||
new_status=RequestStatus.STARTED,
|
||||
revision=factory.LazyAttribute(lambda se: se.factory_parent.revisions[-1]),
|
||||
)
|
||||
|
||||
class Params:
|
||||
initial_revision = None
|
||||
|
||||
@classmethod
|
||||
def build_request_body(cls, user, dollar_value=1000000):
|
||||
return {
|
||||
"primary_poc": {
|
||||
"am_poc": False,
|
||||
"dodid_poc": user.dod_id,
|
||||
"email_poc": user.email,
|
||||
"fname_poc": user.first_name,
|
||||
"lname_poc": user.last_name,
|
||||
},
|
||||
"details_of_use": {
|
||||
"jedi_usage": "adf",
|
||||
"start_date": "2018-08-08",
|
||||
"cloud_native": "yes",
|
||||
"dollar_value": dollar_value,
|
||||
"dod_component": SERVICE_BRANCHES[2][1],
|
||||
"data_transfers": "Less than 100GB",
|
||||
"expected_completion_date": "Less than 1 month",
|
||||
"jedi_migration": "yes",
|
||||
"num_software_systems": 1,
|
||||
"number_user_sessions": 2,
|
||||
"average_daily_traffic": 1,
|
||||
"engineering_assessment": "yes",
|
||||
"technical_support_team": "yes",
|
||||
"estimated_monthly_spend": 100,
|
||||
"average_daily_traffic_gb": 4,
|
||||
"rationalization_software_systems": "yes",
|
||||
"organization_providing_assistance": "In-house staff",
|
||||
},
|
||||
"information_about_you": {
|
||||
"citizenship": "United States",
|
||||
"designation": "military",
|
||||
"phone_number": "1234567890",
|
||||
"email_request": user.email,
|
||||
"fname_request": user.first_name,
|
||||
"lname_request": user.last_name,
|
||||
"service_branch": SERVICE_BRANCHES[1][1],
|
||||
"date_latest_training": "2018-08-06",
|
||||
},
|
||||
}
|
||||
def create_initial_status_event(cls, request):
|
||||
return RequestStatusEventFactory(
|
||||
request=request,
|
||||
new_status=RequestStatus.STARTED,
|
||||
revision=request.revisions,
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def create_initial_revision(cls, request, dollar_value=1000000):
|
||||
user = request.creator
|
||||
default_data = dict(
|
||||
am_poc=False,
|
||||
dodid_poc=user.dod_id,
|
||||
email_poc=user.email,
|
||||
fname_poc=user.first_name,
|
||||
lname_poc=user.last_name,
|
||||
jedi_usage="adf",
|
||||
start_date=datetime.date(2018, 8, 8),
|
||||
cloud_native="yes",
|
||||
dollar_value=dollar_value,
|
||||
dod_component=SERVICE_BRANCHES[2][1],
|
||||
data_transfers="Less than 100GB",
|
||||
expected_completion_date="Less than 1 month",
|
||||
jedi_migration="yes",
|
||||
num_software_systems=1,
|
||||
number_user_sessions=2,
|
||||
average_daily_traffic=1,
|
||||
engineering_assessment="yes",
|
||||
technical_support_team="yes",
|
||||
estimated_monthly_spend=100,
|
||||
average_daily_traffic_gb=4,
|
||||
rationalization_software_systems="yes",
|
||||
organization_providing_assistance="In-house staff",
|
||||
citizenship="United States",
|
||||
designation="military",
|
||||
phone_number="1234567890",
|
||||
email_request=user.email,
|
||||
fname_request=user.first_name,
|
||||
lname_request=user.last_name,
|
||||
service_branch=SERVICE_BRANCHES[1][1],
|
||||
date_latest_training=datetime.date(2018, 8, 6),
|
||||
)
|
||||
|
||||
data = (
|
||||
request.initial_revision
|
||||
if request.initial_revision is not None
|
||||
else default_data
|
||||
)
|
||||
|
||||
return RequestRevisionFactory.build(**data)
|
||||
|
||||
|
||||
class PENumberFactory(factory.alchemy.SQLAlchemyModelFactory):
|
||||
|
@@ -3,33 +3,13 @@ from wtforms import Form
|
||||
import pendulum
|
||||
from werkzeug.datastructures import ImmutableMultiDict
|
||||
|
||||
from atst.forms.fields import DateField, NewlineListField
|
||||
|
||||
|
||||
class DateForm(Form):
|
||||
date = DateField()
|
||||
from atst.forms.fields import NewlineListField
|
||||
|
||||
|
||||
class NewlineListForm(Form):
|
||||
newline_list = NewlineListField()
|
||||
|
||||
|
||||
def test_date_ie_format():
|
||||
form = DateForm(data={"date": "12/24/2018"})
|
||||
assert form.date._value() == pendulum.date(2018, 12, 24)
|
||||
|
||||
|
||||
def test_date_sane_format():
|
||||
form = DateForm(data={"date": "2018-12-24"})
|
||||
assert form.date._value() == pendulum.date(2018, 12, 24)
|
||||
|
||||
|
||||
def test_date_insane_format():
|
||||
form = DateForm(data={"date": "hello"})
|
||||
with pytest.raises(ValueError):
|
||||
form.date._value()
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"input_,expected",
|
||||
[
|
||||
|
@@ -2,9 +2,7 @@ from tests.factories import RequestFactory, UserFactory
|
||||
|
||||
|
||||
MOCK_USER = UserFactory.build()
|
||||
MOCK_REQUEST = RequestFactory.build(
|
||||
creator=MOCK_USER.id, body={"financial_verification": {"pe_id": "0203752A"}}
|
||||
)
|
||||
MOCK_REQUEST = RequestFactory.build(creator=MOCK_USER)
|
||||
DOD_SDN_INFO = {"first_name": "ART", "last_name": "GARFUNKEL", "dod_id": "5892460358"}
|
||||
DOD_SDN = f"CN={DOD_SDN_INFO['last_name']}.{DOD_SDN_INFO['first_name']}.G.{DOD_SDN_INFO['dod_id']},OU=OTHER,OU=PKI,OU=DoD,O=U.S. Government,C=US"
|
||||
|
||||
|
@@ -35,7 +35,7 @@ class TestPENumberInForm:
|
||||
return user
|
||||
|
||||
def submit_data(self, client, user, data, extended=False):
|
||||
request = RequestFactory.create(creator=user, body=MOCK_REQUEST.body)
|
||||
request = RequestFactory.create(creator=user)
|
||||
url_kwargs = {"request_id": request.id}
|
||||
if extended:
|
||||
url_kwargs["extended"] = True
|
||||
@@ -58,7 +58,7 @@ class TestPENumberInForm:
|
||||
user = self._set_monkeypatches(monkeypatch)
|
||||
|
||||
data = dict(self.required_data)
|
||||
data["pe_id"] = MOCK_REQUEST.body["financial_verification"]["pe_id"]
|
||||
data["pe_id"] = "0101110F"
|
||||
|
||||
response = self.submit_data(client, user, data)
|
||||
|
||||
@@ -95,7 +95,7 @@ class TestPENumberInForm:
|
||||
user_session(user)
|
||||
|
||||
data = dict(self.required_data)
|
||||
data["pe_id"] = MOCK_REQUEST.body["financial_verification"]["pe_id"]
|
||||
data["pe_id"] = "0101110F"
|
||||
data["task_order_number"] = "1234"
|
||||
|
||||
response = self.submit_data(client, user, data)
|
||||
@@ -112,7 +112,7 @@ class TestPENumberInForm:
|
||||
user_session(user)
|
||||
|
||||
data = dict(self.required_data)
|
||||
data["pe_id"] = MOCK_REQUEST.body["financial_verification"]["pe_id"]
|
||||
data["pe_id"] = "0101110F"
|
||||
data["task_order_number"] = MockEDAClient.MOCK_CONTRACT_NUMBER
|
||||
|
||||
response = self.submit_data(client, user, data)
|
||||
|
@@ -1,5 +1,5 @@
|
||||
import re
|
||||
from tests.factories import RequestFactory, UserFactory
|
||||
from tests.factories import RequestFactory, UserFactory, RequestRevisionFactory
|
||||
from atst.domain.roles import Roles
|
||||
from atst.domain.requests import Requests
|
||||
from urllib.parse import urlencode
|
||||
@@ -75,10 +75,12 @@ def test_nonexistent_request(client, user_session):
|
||||
assert response.status_code == 404
|
||||
|
||||
|
||||
def test_creator_info_is_autopopulated(monkeypatch, client, user_session):
|
||||
def test_creator_info_is_autopopulated_for_existing_request(
|
||||
monkeypatch, client, user_session
|
||||
):
|
||||
user = UserFactory.create()
|
||||
user_session(user)
|
||||
request = RequestFactory.create(creator=user, body={"information_about_you": {}})
|
||||
request = RequestFactory.create(creator=user, initial_revision={})
|
||||
|
||||
response = client.get("/requests/new/2/{}".format(request.id))
|
||||
body = response.data.decode()
|
||||
@@ -104,7 +106,7 @@ 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, body={"information_about_you": {}})
|
||||
request = RequestFactory.create(creator=creator, initial_revision={})
|
||||
|
||||
response = client.get("/requests/new/2/{}".format(request.id))
|
||||
body = response.data.decode()
|
||||
@@ -116,7 +118,7 @@ def test_non_creator_info_is_not_autopopulated(monkeypatch, client, user_session
|
||||
def test_am_poc_causes_poc_to_be_autopopulated(client, user_session):
|
||||
creator = UserFactory.create()
|
||||
user_session(creator)
|
||||
request = RequestFactory.create(creator=creator, body={})
|
||||
request = RequestFactory.create(creator=creator, initial_revision={})
|
||||
client.post(
|
||||
"/requests/new/3/{}".format(request.id),
|
||||
headers={"Content-Type": "application/x-www-form-urlencoded"},
|
||||
@@ -129,7 +131,7 @@ def test_am_poc_causes_poc_to_be_autopopulated(client, user_session):
|
||||
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, body={})
|
||||
request = RequestFactory.create(creator=creator, initial_revision={})
|
||||
response = client.post(
|
||||
"/requests/new/3/{}".format(request.id),
|
||||
headers={"Content-Type": "application/x-www-form-urlencoded"},
|
||||
@@ -142,7 +144,7 @@ def test_not_am_poc_requires_poc_info_to_be_completed(client, user_session):
|
||||
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, body={})
|
||||
request = RequestFactory.create(creator=creator, initial_revision={})
|
||||
poc_input = {
|
||||
"am_poc": "no",
|
||||
"fname_poc": "test",
|
||||
@@ -177,13 +179,11 @@ def test_poc_autofill_checks_information_about_you_form_first(client, user_sessi
|
||||
user_session(creator)
|
||||
request = RequestFactory.create(
|
||||
creator=creator,
|
||||
body={
|
||||
"information_about_you": {
|
||||
"fname_request": "Alice",
|
||||
"lname_request": "Adams",
|
||||
"email_request": "alice.adams@mail.mil",
|
||||
}
|
||||
},
|
||||
initial_revision=dict(
|
||||
fname_request="Alice",
|
||||
lname_request="Adams",
|
||||
email_request="alice.adams@mail.mil",
|
||||
),
|
||||
)
|
||||
poc_input = {"am_poc": "yes"}
|
||||
client.post(
|
||||
|
@@ -12,10 +12,25 @@ def screens(app):
|
||||
return JEDIRequestFlow(3).screens
|
||||
|
||||
|
||||
def serialize_dates(data):
|
||||
if not data:
|
||||
return data
|
||||
|
||||
dates = {
|
||||
k: v.strftime("%m/%d/%Y") for k, v in data.items() if hasattr(v, "strftime")
|
||||
}
|
||||
|
||||
new_data = data.copy()
|
||||
new_data.update(dates)
|
||||
|
||||
return new_data
|
||||
|
||||
|
||||
def test_stepthrough_request_form(user_session, screens, client):
|
||||
user = UserFactory.create()
|
||||
user_session(user)
|
||||
mock_request = RequestFactory.stub()
|
||||
mock_request = RequestFactory.create()
|
||||
mock_body = mock_request.body
|
||||
|
||||
def post_form(url, redirects=False, data=""):
|
||||
return client.post(
|
||||
@@ -33,6 +48,7 @@ def test_stepthrough_request_form(user_session, screens, client):
|
||||
# destination url
|
||||
prelim_resp = post_form(req_url, data=data)
|
||||
response = post_form(req_url, True, data=data)
|
||||
assert prelim_resp.status_code == 302
|
||||
return (prelim_resp.headers.get("Location"), response)
|
||||
|
||||
# GET the initial form
|
||||
@@ -44,7 +60,8 @@ def test_stepthrough_request_form(user_session, screens, client):
|
||||
for i in range(1, len(screens)):
|
||||
# get appropriate form data to POST for this section
|
||||
section = screens[i - 1]["section"]
|
||||
post_data = urlencode(mock_request.body[section])
|
||||
massaged = serialize_dates(mock_body[section])
|
||||
post_data = urlencode(massaged)
|
||||
|
||||
effective_url, resp = take_a_step(i, req=req_id, data=post_data)
|
||||
req_id = effective_url.split("/")[-1]
|
||||
@@ -55,7 +72,7 @@ def test_stepthrough_request_form(user_session, screens, client):
|
||||
|
||||
# at this point, the real request we made and the mock_request bodies
|
||||
# should be equivalent
|
||||
assert Requests.get(user, req_id).body == mock_request.body
|
||||
assert Requests.get(user, req_id).body == mock_body
|
||||
|
||||
# finish the review and submit step
|
||||
client.post(
|
||||
|
Reference in New Issue
Block a user