Skip to content

Commit

Permalink
Merge pull request #428 from UKHomeOffice/bugfix/FAIR-172
Browse files Browse the repository at this point in the history
Bugfix/fair 172
  • Loading branch information
justinhyltonHO authored Feb 20, 2024
2 parents 2963e6f + 40dc9ff commit 8a3fd2a
Show file tree
Hide file tree
Showing 8 changed files with 116 additions and 46 deletions.
46 changes: 40 additions & 6 deletions src/app/garfile/arrival/index.njk
Original file line number Diff line number Diff line change
Expand Up @@ -131,8 +131,18 @@
<div class="govuk-radios govuk-radios--conditional" data-module="radios">
<div class="govuk-radios__item">
<input id="portChoiceCode" name="portChoice" class="govuk-radios__input"
type="radio" value="Yes"{{ ' checked' if cookie.getGarArrivalVoyage().arrivalPort != undefined and cookie.getGarArrivalVoyage().arrivalPort != 'ZZZZ'}}
data-aria-controls="portChoiceCodeContainer" aria-labelledby="portChoiceCode-label">
type="radio"
value="Yes"
{% set IATA_CODE_LENGTH = 3 %}
{% set ICAO_CODE_LENGTH = 4 %}
{{
'checked' if cookie.getGarArrivalVoyage().arrivalPort === ''
or cookie.getGarArrivalVoyage().arrivalPort.length === IATA_CODE_LENGTH
or cookie.getGarArrivalVoyage().arrivalPort.length === ICAO_CODE_LENGTH
}}
data-aria-controls="portChoiceCodeContainer"
aria-labelledby="portChoiceCode-label"
>
<label id="portChoiceCode-label" class="govuk-label govuk-radios__label" for="portChoiceCode">{{__('field_choice_yes')}}</label>
</div>
<div id="portChoiceCodeContainer" class="govuk-radios__conditional govuk-radios__conditional--hidden">
Expand All @@ -154,8 +164,34 @@
</div>
<div class="govuk-radios__item">
<input id="portChoiceCoordinates" name="portChoice" class="govuk-radios__input"
type="radio" value="No"{{ ' checked' if cookie.getGarArrivalVoyage().arrivalPort == 'ZZZZ'}}
data-aria-controls="portChoiceCoordinatesContainer" aria-labelledby="portChoiceCoordinates-label">
type="radio"
value="No"
{#
In some instances when a user submits an empty input field e.g. Latitude: [] [28] [] [],
Not-A-Number (NaN) will be returned because user input is converted to a floating-point number
with parseFloat().
#}

{% set DECIMAL_POINT = '.' %}
{% set NOT_A_NUMBER = 'NaN' %}
{#
If both LAT and LONG values exist. The "No" port choice will be selected if both the LAT and LONG
values contain a decimal point or either the LAT or LONG values are NaN.
#}
{{
'checked' if cookie.getGarArrivalVoyage().arrivalPort != undefined
and (
cookie.getGarArrivalVoyage().arrivalLat.includes(DECIMAL_POINT)
and cookie.getGarArrivalVoyage().arrivalLong.includes(DECIMAL_POINT)
or (
cookie.getGarArrivalVoyage().arrivalLat == NOT_A_NUMBER
or cookie.getGarArrivalVoyage().arrivalLong == NOT_A_NUMBER
)
)
}}
data-aria-controls="portChoiceCoordinatesContainer"
aria-labelledby="portChoiceCoordinates-label"
>
<label id="portChoiceCoordinates-label" class="govuk-label govuk-radios__label" for="portChoiceCoordinates">{{__('field_choice_no')}}</label>
</div>
<div id="portChoiceCoordinatesContainer" class="govuk-radios__conditional govuk-radios__conditional--hidden">
Expand Down Expand Up @@ -200,8 +236,6 @@
<input class="govuk-input govuk-date-input__input govuk-input--width-2" id="arrivalLongDirection"
name="arrivalLongDirection" type="text" maxLength=1 value="{{ cookie.getGarArrivalVoyage().arrivalLongDirection }}" >

<!--<input class="govuk-input govuk-input--width-10" id="arrivalLong" name="arrivalLong" autocomplete="off" type="text"
value="{{ cookie.getGarArrivalVoyage().arrivalLong }}" aria-describedby="arrivalCoordinates-hint arrivalLongitude-hint{{ ' arrivalLong-error' if errors | containsError('arrivalLong') }}"/>-->
</div>
{# End arrival coords #}
</div>
Expand Down
2 changes: 1 addition & 1 deletion src/app/garfile/arrival/post.controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ const buildValidations = (voyage) => {

const validations = [
[new ValidationRule(validator.realDate, 'arrivalDate', arriveDateObj, realDateMsg)],
[new ValidationRule(validator.currentOrFutureDate, 'arrivalDate', arriveDateObj, __('field_arrival_date_too_far_in_future'))],
[new ValidationRule(validator.currentOrPastDate, 'arrivalDate', arriveDateObj, __('field_arrival_date_too_far_in_future'))],
[new ValidationRule(validator.dateNotTooFarInFuture, 'arrivalDate', arriveDateObj, __('field_arrival_date_too_far_in_future'))],
[new ValidationRule(validator.validTime, 'arrivalTime', arrivalTimeObj, timeMsg)],
[new ValidationRule(validator.notEmpty, 'portChoice', voyage.portChoice, portChoiceMsg)],
Expand Down
3 changes: 0 additions & 3 deletions src/app/garfile/departure/get.controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,6 @@ module.exports = (req, res) => {

garApi.get(cookie.getGarId()).then((apiResponse) => {
const parsedResponse = JSON.parse(apiResponse);
if (parsedResponse.departurePort === 'ZZZZ') {
parsedResponse.departurePort = 'YYYY';
}
cookie.setGarDepartureVoyage(parsedResponse);

return res.render('app/garfile/departure/index', { cookie });
Expand Down
48 changes: 40 additions & 8 deletions src/app/garfile/departure/index.njk
Original file line number Diff line number Diff line change
Expand Up @@ -134,8 +134,18 @@
<div class="govuk-radios govuk-radios--conditional" data-module="radios">
<div class="govuk-radios__item">
<input id="portChoiceCode" name="portChoice" class="govuk-radios__input"
type="radio" value="Yes"{{ ' checked' if cookie.getGarDepartureVoyage().departurePort != undefined and cookie.getGarDepartureVoyage().departurePort != 'YYYY'}}
data-aria-controls="portChoiceCodeContainer" aria-labelledby="portChoiceCode-label">
type="radio"
value="Yes"
{% set IATA_CODE_LENGTH = 3 %}
{% set ICAO_CODE_LENGTH = 4 %}
{{
'checked' if cookie.getGarDepartureVoyage().departurePort === ''
or cookie.getGarDepartureVoyage().departurePort.length === IATA_CODE_LENGTH
or cookie.getGarDepartureVoyage().departurePort.length === ICAO_CODE_LENGTH
}}
data-aria-controls="portChoiceCodeContainer"
aria-labelledby="portChoiceCode-label"
>
<label id="portChoiceCode-label" class="govuk-label govuk-radios__label" for="portChoiceCode">{{__('field_choice_yes')}}</label>
</div>
<div id="portChoiceCodeContainer" class="govuk-radios__conditional govuk-radios__conditional--hidden">
Expand All @@ -157,8 +167,34 @@
</div>
<div class="govuk-radios__item">
<input id="portChoiceCoordinates" name="portChoice" class="govuk-radios__input"
type="radio" value="No"{{ ' checked' if cookie.getGarDepartureVoyage().departurePort == 'YYYY'}}
data-aria-controls="portChoiceCoordinatesContainer" aria-labelledby="portChoiceCoordinates-label">
type="radio"
value="No"
{#
In some instances when a user submits an empty input field e.g. Latitude: [] [28] [] [],
Not-A-Number (NaN) will be returned because user input is converted to a floating-point number
with parseFloat().
#}

{% set DECIMAL_POINT = '.' %}
{% set NOT_A_NUMBER = 'NaN' %}
{#
If both LAT and LONG values exist. The "No" port choice will be selected if both the LAT and LONG
values contain a decimal point or either the LAT or LONG values are NaN.
#}
{{
'checked' if cookie.getGarDepartureVoyage().departurePort != undefined
and (
cookie.getGarDepartureVoyage().departureLat.includes(DECIMAL_POINT)
and cookie.getGarDepartureVoyage().departureLong.includes(DECIMAL_POINT)
or (
cookie.getGarDepartureVoyage().departureLat == NOT_A_NUMBER
or cookie.getGarDepartureVoyage().departureLong == NOT_A_NUMBER
)
)
}}
data-aria-controls="portChoiceCoordinatesContainer"
aria-labelledby="portChoiceCoordinates-label"
>
<label id="portChoiceCoordinates-label" class="govuk-label govuk-radios__label" for="portChoiceCoordinates">{{__('field_choice_no')}}</label>
</div>
<div id="portChoiceCoordinatesContainer" class="govuk-radios__conditional govuk-radios__conditional--hidden">
Expand Down Expand Up @@ -187,8 +223,6 @@
<input class="govuk-input govuk-date-input__input govuk-input--width-2" id="departureLatDirection"
name="departureLatDirection" type="text" maxLength=1 value="{{ cookie.getGarDepartureVoyage().departureLatDirection }}" >

<!--<input class="govuk-input govuk-input--width-10" id="departureLat" name="departureLat" autocomplete="off" type="text"
value="{{ cookie.getGarDepartureVoyage().departureLat }}" aria-describedby="departureCoordinates-hint departureLatitude-hint{{ ' departureLat-error' if errors | containsError('departureLat')}}"/>-->
</div>

<div class="govuk-form-group {{ m.form_group_class('departureLong', errors) }}">
Expand All @@ -211,8 +245,6 @@
<input class="govuk-input govuk-date-input__input govuk-input--width-2" id="departureLongDirection"
name="departureLongDirection" type="text" maxLength=1 value="{{ cookie.getGarDepartureVoyage().departureLongDirection }}" >

<!--<input class="govuk-input govuk-input--width-10" id="departureLong" name="departureLong" autocomplete="off" type="text"
value="{{ cookie.getGarDepartureVoyage().departureLong }}" aria-describedby="departureCoordinates-hint departureLongitude-hint{{ ' departureLong-error' if errors | containsError('departureLong') }}"/>-->
</div>
{# End departure coords #}
</div>
Expand Down
5 changes: 2 additions & 3 deletions src/app/garfile/departure/post.controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ const validator = require('../../../common/utils/validator');
const CookieModel = require('../../../common/models/Cookie.class');
const garApi = require('../../../common/services/garApi');
const ValidationRule = require('../../../common/models/ValidationRule.class');
const airportValidation = require('../../../common/utils/airportValidation');
//const airportValidation = require('../../../common/utils/airportValidation');

const createValidationChains = (voyage) => {

Expand Down Expand Up @@ -46,7 +46,7 @@ const createValidationChains = (voyage) => {

const validations = [
[new ValidationRule(validator.realDate, 'departureDate', departDateObj, __('field_departure_real_date_validation'))],
[new ValidationRule(validator.currentOrFutureDate, 'departureDate', departDateObj, __('field_departure_date_too_far_in_future'))],
[new ValidationRule(validator.currentOrPastDate, 'departureDate', departDateObj, __('field_departure_date_too_far_in_future'))],
[new ValidationRule(validator.dateNotTooFarInFuture, 'departureDate', departDateObj, __('field_departure_date_too_far_in_future'))],
[new ValidationRule(validator.validTime, 'departureTime', departureTimeObj, __('field_departure_real_time_validation'))],
[new ValidationRule(validator.notEmpty, 'portChoice', voyage.portChoice, __('field_port_choice_message'))],
Expand Down Expand Up @@ -114,7 +114,6 @@ module.exports = async (req, res) => {
// Define voyage
const voyage = req.body;
delete voyage.buttonClicked;
// TODO: Update this once the intended 'unknown' port code is discovered.
if (voyage.portChoice === 'No') {
logger.debug("Testing departure Lat and Long values...");

Expand Down
32 changes: 20 additions & 12 deletions src/common/utils/validator.js
Original file line number Diff line number Diff line change
Expand Up @@ -196,29 +196,37 @@ function validGender(value) {
return validValues.includes(value);
}

function currentOrFutureDate(dObj) {
/**
* Checks that the supplied date is not a past date
* @param {Object} dObjh Date - can be js Date object or the {d:,m:,y} type object that is used in the UI
* @returns {Boolean} true if not past date, false if past date
*/
function currentOrPastDate(dObj) {
const currDate = new Date();
const currMonth = currDate.getMonth() + 1;

/*
Returns true if all dates fields are empty to avoid duplicate error messages being displayed.
The dateNotTooFarInFuture function will cover this error.
*/
if([dObj.d,dObj.m,dObj.y].includes('')) {
return true;
}

if (dObj.y < currDate.getFullYear()) {
return false;
}
if (dObj.y > currDate.getFullYear()) {
return true;
}
if (dObj.y == currDate.getFullYear()) {
if (dObj.m < currDate.getMonth() + 1) {
if (dObj.m < currMonth) {
return false;
}
if (dObj.m > currDate.getMonth() + 1) {
return true;
}
if (dObj.m == currDate.getMonth() + 1) {
if (dObj.m == currMonth) {
return dObj.d >= currDate.getDate();
}
}
return false;
}

return true;
}

/**
* Check that supplied date is within an acceptable range (currently within 1 month from Date.now())
Expand Down Expand Up @@ -725,7 +733,7 @@ module.exports = {
realDateInFuture,
bornAfter1900,
realDateFromString,
currentOrFutureDate,
currentOrPastDate,
validTime,
validFlag,
validPort,
Expand Down
2 changes: 1 addition & 1 deletion src/test/garfile/arrival/post.controller.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ describe('Arrival Post Controller', () => {
expect(garApi.patch).to.not.have.been.called;
expect(res.render).to.have.been.calledWith('app/garfile/arrival/index', {
cookie,
errors: [new ValidationRule(validator.currentOrFutureDate, 'arrivalDate', { d: "30", m: "5", y: "2010" }, 'Arrival date must be today and cannot be more than 1 month in the future')],
errors: [new ValidationRule(validator.currentOrPastDate, 'arrivalDate', { d: "30", m: "5", y: "2010" }, 'Arrival date must be today and cannot be more than 1 month in the future')],
});
});
});
Expand Down
24 changes: 12 additions & 12 deletions src/test/validators.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -201,22 +201,22 @@ describe('Validator', () => {
const nextMonth = currDate.getMonth() + 1;
const year = currDate.getFullYear();
const nextYear = currDate.getFullYear() + 1;
expect(validator.currentOrFutureDate(genDateObj(day, nextMonth, year))).to.be.true;
expect(validator.currentOrFutureDate(genDateObj(day, nextMonth, nextYear))).to.be.true;
expect(validator.currentOrFutureDate(genDateObj(nextDay, month, nextYear))).to.be.true;
expect(validator.currentOrFutureDate(genDateObj('22', '12', '2055'))).to.be.true;
expect(validator.currentOrFutureDate(genDateObj('01', '01', '2020'))).to.be.true;
expect(validator.currentOrPastDate(genDateObj(day, nextMonth, year))).to.be.true;
expect(validator.currentOrPastDate(genDateObj(day, nextMonth, nextYear))).to.be.true;
expect(validator.currentOrPastDate(genDateObj(nextDay, month, nextYear))).to.be.true;
expect(validator.currentOrPastDate(genDateObj('22', '12', '2055'))).to.be.true;
expect(validator.currentOrPastDate(genDateObj('01', '01', '2020'))).to.be.true;

clock.restore();
});

it('Should return true for a date after, edge cases', () => {
const clock = sinon.useFakeTimers(new Date(2011, 11, 31).getTime());

expect(validator.currentOrFutureDate(genDateObj(1, 1, 2011))).to.be.false;
expect(validator.currentOrFutureDate(genDateObj(31, 1, 2011))).to.be.false;
expect(validator.currentOrFutureDate(genDateObj(1, 1, 2012))).to.be.true;
expect(validator.currentOrFutureDate(genDateObj(31, 12, 2011))).to.be.true;
expect(validator.currentOrPastDate(genDateObj(1, 1, 2011))).to.be.false;
expect(validator.currentOrPastDate(genDateObj(31, 1, 2011))).to.be.false;
expect(validator.currentOrPastDate(genDateObj(1, 1, 2012))).to.be.true;
expect(validator.currentOrPastDate(genDateObj(31, 12, 2011))).to.be.true;

clock.restore();
});
Expand All @@ -229,9 +229,9 @@ describe('Validator', () => {
const month = currDate.getMonth() + 1;
const previousMonth = currDate.getMonth() - 1;
const year = currDate.getFullYear();
expect(validator.currentOrFutureDate(genDateObj(day, month, year))).to.be.false;
expect(validator.currentOrFutureDate(genDateObj(currDate.getDate(), previousMonth, year))).to.be.false;
expect(validator.currentOrFutureDate(genDateObj('22', '12', '1999'))).to.be.false;
expect(validator.currentOrPastDate(genDateObj(day, month, year))).to.be.false;
expect(validator.currentOrPastDate(genDateObj(currDate.getDate(), previousMonth, year))).to.be.false;
expect(validator.currentOrPastDate(genDateObj('22', '12', '1999'))).to.be.false;

clock.restore();
});
Expand Down

0 comments on commit 8a3fd2a

Please sign in to comment.