use regular WTForms DateField for requests dates
This commit is contained in:
parent
b20d91c784
commit
59fdad8554
@ -1,12 +0,0 @@
|
|||||||
import pendulum
|
|
||||||
|
|
||||||
|
|
||||||
def parse_date(data):
|
|
||||||
date_formats = ["YYYY-MM-DD", "MM/DD/YYYY"]
|
|
||||||
for _format in date_formats:
|
|
||||||
try:
|
|
||||||
return pendulum.from_format(data, _format).date()
|
|
||||||
except (ValueError, pendulum.parsing.exceptions.ParserError):
|
|
||||||
pass
|
|
||||||
|
|
||||||
raise ValueError("Unable to parse string {}".format(data))
|
|
@ -1,23 +1,6 @@
|
|||||||
from wtforms.fields.html5 import DateField
|
|
||||||
from wtforms.fields import Field, SelectField as SelectField_
|
from wtforms.fields import Field, SelectField as SelectField_
|
||||||
from wtforms.widgets import TextArea
|
from wtforms.widgets import TextArea
|
||||||
|
|
||||||
from atst.domain.date import parse_date
|
|
||||||
|
|
||||||
|
|
||||||
class DateField(DateField):
|
|
||||||
def _value(self):
|
|
||||||
if self.data:
|
|
||||||
return parse_date(self.data)
|
|
||||||
else:
|
|
||||||
return None
|
|
||||||
|
|
||||||
def process_formdata(self, values):
|
|
||||||
if values:
|
|
||||||
self.data = values[0]
|
|
||||||
else:
|
|
||||||
self.data = None
|
|
||||||
|
|
||||||
|
|
||||||
class NewlineListField(Field):
|
class NewlineListField(Field):
|
||||||
widget = TextArea()
|
widget = TextArea()
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
from wtforms.fields.html5 import EmailField, TelField
|
from wtforms.fields.html5 import DateField, EmailField, TelField
|
||||||
from wtforms.fields import RadioField, StringField
|
from wtforms.fields import RadioField, StringField
|
||||||
from wtforms.validators import Required, Email
|
from wtforms.validators import Required, Email
|
||||||
import pendulum
|
import pendulum
|
||||||
|
|
||||||
from .fields import DateField, SelectField
|
from .fields import SelectField
|
||||||
from .forms import ValidatedForm
|
from .forms import ValidatedForm
|
||||||
from .validators import DateRange, PhoneNumber, Alphabet
|
from .validators import DateRange, PhoneNumber, Alphabet
|
||||||
from .data import SERVICE_BRANCHES
|
from .data import SERVICE_BRANCHES
|
||||||
@ -60,4 +60,5 @@ class OrgForm(ValidatedForm):
|
|||||||
message="Must be a date within the last year.",
|
message="Must be a date within the last year.",
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
format="%m/%d/%Y",
|
||||||
)
|
)
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
from wtforms.fields.html5 import IntegerField
|
from wtforms.fields.html5 import DateField, IntegerField
|
||||||
from wtforms.fields import RadioField, TextAreaField
|
from wtforms.fields import RadioField, TextAreaField
|
||||||
from wtforms.validators import Optional, Required
|
from wtforms.validators import Optional, Required
|
||||||
|
|
||||||
from .fields import DateField, SelectField
|
from .fields import SelectField
|
||||||
from .forms import ValidatedForm
|
from .forms import ValidatedForm
|
||||||
from .data import (
|
from .data import (
|
||||||
SERVICE_BRANCHES,
|
SERVICE_BRANCHES,
|
||||||
@ -135,4 +135,5 @@ class RequestForm(ValidatedForm):
|
|||||||
start_date = DateField(
|
start_date = DateField(
|
||||||
description="When do you expect to start using the JEDI Cloud (not for billing purposes)?",
|
description="When do you expect to start using the JEDI Cloud (not for billing purposes)?",
|
||||||
validators=[Required()],
|
validators=[Required()],
|
||||||
|
format="%m/%d/%Y",
|
||||||
)
|
)
|
||||||
|
@ -2,13 +2,11 @@ import re
|
|||||||
from wtforms.validators import ValidationError
|
from wtforms.validators import ValidationError
|
||||||
import pendulum
|
import pendulum
|
||||||
|
|
||||||
from atst.domain.date import parse_date
|
|
||||||
|
|
||||||
|
|
||||||
def DateRange(lower_bound=None, upper_bound=None, message=None):
|
def DateRange(lower_bound=None, upper_bound=None, message=None):
|
||||||
def _date_range(form, field):
|
def _date_range(form, field):
|
||||||
now = pendulum.now().date()
|
now = pendulum.now().date()
|
||||||
date = parse_date(field.data)
|
date = field.data
|
||||||
|
|
||||||
if lower_bound is not None:
|
if lower_bound is not None:
|
||||||
if (now - lower_bound) > date:
|
if (now - lower_bound) > date:
|
||||||
|
10
templates/components/date_input.html
Normal file
10
templates/components/date_input.html
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
{% from "components/text_input.html" import TextInput %}
|
||||||
|
|
||||||
|
{% macro DateInput(field, tooltip='', placeholder='', validation='anything', paragraph=False) -%}
|
||||||
|
{% if field.data %}
|
||||||
|
{% set input_value=field.data.strftime("%m/%d/%Y") %}
|
||||||
|
{% else %}
|
||||||
|
{% set input_value=None %}
|
||||||
|
{% endif %}
|
||||||
|
{{ TextInput(field, initial_value=input_value, tooltip=tooltip, placeholder=placeholder, validation=validation, paragraph=paragraph) }}
|
||||||
|
{% endmacro %}
|
@ -1,12 +1,12 @@
|
|||||||
{% from "components/icon.html" import Icon %}
|
{% from "components/icon.html" import Icon %}
|
||||||
{% from "components/tooltip.html" import Tooltip %}
|
{% from "components/tooltip.html" import Tooltip %}
|
||||||
|
|
||||||
{% macro TextInput(field, tooltip='', placeholder='', validation='anything', paragraph=False) -%}
|
{% macro TextInput(field, tooltip='', placeholder='', validation='anything', paragraph=False, initial_value='') -%}
|
||||||
<textinput
|
<textinput
|
||||||
name='{{ field.name }}'
|
name='{{ field.name }}'
|
||||||
validation='{{ validation }}'
|
validation='{{ validation }}'
|
||||||
{% if paragraph %}paragraph='true'{% endif %}
|
{% if paragraph %}paragraph='true'{% endif %}
|
||||||
{% if field.data %}initial-value='{{ field.data }}'{% endif %}
|
{% if initial_value or field.data %}initial-value='{{ initial_value or field.data }}'{% endif %}
|
||||||
{% if field.errors %}v-bind:initial-errors='{{ field.errors }}'{% endif %}
|
{% if field.errors %}v-bind:initial-errors='{{ field.errors }}'{% endif %}
|
||||||
key='{{ field.name }}'
|
key='{{ field.name }}'
|
||||||
inline-template>
|
inline-template>
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
{% from "components/alert.html" import Alert %}
|
{% from "components/alert.html" import Alert %}
|
||||||
{% from "components/text_input.html" import TextInput %}
|
{% from "components/text_input.html" import TextInput %}
|
||||||
{% from "components/options_input.html" import OptionsInput %}
|
{% from "components/options_input.html" import OptionsInput %}
|
||||||
|
{% from "components/date_input.html" import DateInput %}
|
||||||
|
|
||||||
{% block subtitle %}
|
{% block subtitle %}
|
||||||
<h2>Details of Use</h2>
|
<h2>Details of Use</h2>
|
||||||
@ -76,7 +77,7 @@
|
|||||||
</transition>
|
</transition>
|
||||||
|
|
||||||
{{ TextInput(f.dollar_value, validation='dollars', placeholder='$0') }}
|
{{ TextInput(f.dollar_value, validation='dollars', placeholder='$0') }}
|
||||||
{{ TextInput(f.start_date, placeholder='MM / DD / YYYY', validation='date') }}
|
{{ DateInput(f.start_date, placeholder='MM / DD / YYYY', validation='date') }}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</details-of-use>
|
</details-of-use>
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
{% from "components/alert.html" import Alert %}
|
{% from "components/alert.html" import Alert %}
|
||||||
{% from "components/text_input.html" import TextInput %}
|
{% from "components/text_input.html" import TextInput %}
|
||||||
{% from "components/options_input.html" import OptionsInput %}
|
{% from "components/options_input.html" import OptionsInput %}
|
||||||
|
{% from "components/date_input.html" import DateInput %}
|
||||||
|
|
||||||
{% block subtitle %}
|
{% block subtitle %}
|
||||||
<h2>Information About You</h2>
|
<h2>Information About You</h2>
|
||||||
@ -29,5 +30,5 @@
|
|||||||
{{ OptionsInput(f.service_branch) }}
|
{{ OptionsInput(f.service_branch) }}
|
||||||
{{ OptionsInput(f.citizenship) }}
|
{{ OptionsInput(f.citizenship) }}
|
||||||
{{ OptionsInput(f.designation) }}
|
{{ OptionsInput(f.designation) }}
|
||||||
{{ TextInput(f.date_latest_training,tooltip="When was the last time you completed the IA training? <br> Information Assurance (IA) training is an important step in cyber awareness.",placeholder="MM / DD / YYYY", validation="date") }}
|
{{ DateInput(f.date_latest_training,tooltip="When was the last time you completed the IA training? <br> Information Assurance (IA) training is an important step in cyber awareness.",placeholder="MM / DD / YYYY", validation="date") }}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
@ -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)
|
|
@ -3,33 +3,13 @@ from wtforms import Form
|
|||||||
import pendulum
|
import pendulum
|
||||||
from werkzeug.datastructures import ImmutableMultiDict
|
from werkzeug.datastructures import ImmutableMultiDict
|
||||||
|
|
||||||
from atst.forms.fields import DateField, NewlineListField
|
from atst.forms.fields import NewlineListField
|
||||||
|
|
||||||
|
|
||||||
class DateForm(Form):
|
|
||||||
date = DateField()
|
|
||||||
|
|
||||||
|
|
||||||
class NewlineListForm(Form):
|
class NewlineListForm(Form):
|
||||||
newline_list = NewlineListField()
|
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(
|
@pytest.mark.parametrize(
|
||||||
"input_,expected",
|
"input_,expected",
|
||||||
[
|
[
|
||||||
|
@ -12,6 +12,20 @@ def screens(app):
|
|||||||
return JEDIRequestFlow(3).screens
|
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):
|
def test_stepthrough_request_form(user_session, screens, client):
|
||||||
user = UserFactory.create()
|
user = UserFactory.create()
|
||||||
user_session(user)
|
user_session(user)
|
||||||
@ -46,7 +60,8 @@ def test_stepthrough_request_form(user_session, screens, client):
|
|||||||
for i in range(1, len(screens)):
|
for i in range(1, len(screens)):
|
||||||
# get appropriate form data to POST for this section
|
# get appropriate form data to POST for this section
|
||||||
section = screens[i - 1]["section"]
|
section = screens[i - 1]["section"]
|
||||||
post_data = urlencode(mock_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)
|
effective_url, resp = take_a_step(i, req=req_id, data=post_data)
|
||||||
req_id = effective_url.split("/")[-1]
|
req_id = effective_url.split("/")[-1]
|
||||||
|
Loading…
x
Reference in New Issue
Block a user