Verify correct land use group parameters

This commit is contained in:
Maciej Ziarkowski 2020-03-22 19:18:07 +00:00
parent aebf7c7135
commit d6beb03065
4 changed files with 79 additions and 14 deletions

View File

@ -36,3 +36,14 @@ export async function getLandUseOrderFromGroup(groups: string[]): Promise<string
return 'Mixed Use'; return 'Mixed Use';
} else return null; } else return null;
} }
export async function isLandUseGroupAllowed(group: string): Promise<boolean> {
let groupResult = await db.oneOrNone(`
SELECT landuse_id
FROM reference_tables.buildings_landuse_group
WHERE description = $1
`, [group]
);
return (groupResult != undefined);
}

View File

@ -1,5 +1,6 @@
import * as _ from 'lodash'; import * as _ from 'lodash';
import { ArgumentError } from '../../../errors/general';
import { LandUseState, updateLandUse } from '../../domainLogic/landUse'; import { LandUseState, updateLandUse } from '../../domainLogic/landUse';
const testGroupToOrder = { const testGroupToOrder = {
@ -9,6 +10,8 @@ const testGroupToOrder = {
'Offices': 'Industry And Business' 'Offices': 'Industry And Business'
}; };
const testAllowedGroups = Object.keys(testGroupToOrder);
jest.mock('../../../dataAccess/landUse', () => ({ jest.mock('../../../dataAccess/landUse', () => ({
getLandUseOrderFromGroup: jest.fn((groups: string[]) => { getLandUseOrderFromGroup: jest.fn((groups: string[]) => {
const orders = _.chain(groups).map(g => testGroupToOrder[g]).uniq().value(); const orders = _.chain(groups).map(g => testGroupToOrder[g]).uniq().value();
@ -19,6 +22,9 @@ jest.mock('../../../dataAccess/landUse', () => ({
else result = 'Mixed Use'; else result = 'Mixed Use';
return Promise.resolve(result); return Promise.resolve(result);
}),
isLandUseGroupAllowed: jest.fn((group: string) => {
return testAllowedGroups.includes(group);
}) })
})); }));
@ -94,4 +100,27 @@ describe('updateLandUse()', () => {
} }
); );
it.each([
[['Blah'], "'Blah' is not a valid Land Use Group"],
[['Agriculture', 'Zonk'], "'Zonk' is not a valid Land Use Group"],
[['Zonk', 'Blah'], "'Zonk' is not a valid Land Use Group"]
])('Should throw ArgumentError when invalid land use group supplied', async (groups: string[], message: string) => {
const resultPromise = updateLandUse({landUseGroup: [], landUseOrder: null}, { landUseGroup: groups});
await expect(resultPromise).rejects.toBeInstanceOf(ArgumentError);
await expect(resultPromise).rejects.toHaveProperty('argumentName', 'landUseUpdate');
await expect(resultPromise).rejects.toHaveProperty('message', message);
});
it('Should throw ArgumentError when duplicate land use groups supplied', async () => {
const resultPromise = updateLandUse(
{landUseGroup: [], landUseOrder: null},
{ landUseGroup: ['Agriculture', 'Agriculture']}
);
await expect(resultPromise).rejects.toBeInstanceOf(ArgumentError);
await expect(resultPromise).rejects.toHaveProperty('argumentName', 'landUseUpdate');
await expect(resultPromise).rejects.toHaveProperty('message', 'Cannot supply duplicate Land Use Groups');
});
}); });

View File

@ -1,6 +1,7 @@
import _ from 'lodash'; import _ from 'lodash';
import { getLandUseOrderFromGroup } from '../../dataAccess/landUse'; import * as landUseDataAccess from '../../dataAccess/landUse';
import { ArgumentError } from '../../errors/general';
export interface LandUseState { export interface LandUseState {
landUseGroup: string[]; landUseGroup: string[];
@ -9,10 +10,26 @@ export interface LandUseState {
export async function updateLandUse(landUse: LandUseState, landUseUpdate: Partial<LandUseState>): Promise<LandUseState> { export async function updateLandUse(landUse: LandUseState, landUseUpdate: Partial<LandUseState>): Promise<LandUseState> {
const landUseGroupUpdate = landUseUpdate.landUseGroup; const landUseGroupUpdate = landUseUpdate.landUseGroup;
const landUseOrderUpdate = await getLandUseOrderFromGroup(landUseGroupUpdate);
for(let group of landUseGroupUpdate) {
const isGroupValid = await landUseDataAccess.isLandUseGroupAllowed(group);
if(!isGroupValid) {
throw new ArgumentError(`'${group}' is not a valid Land Use Group`, 'landUseUpdate');
}
}
if(hasDuplicates(landUseGroupUpdate)) {
throw new ArgumentError('Cannot supply duplicate Land Use Groups', 'landUseUpdate');
}
const landUseOrderUpdate = await landUseDataAccess.getLandUseOrderFromGroup(landUseGroupUpdate);
return { return {
landUseGroup: landUseGroupUpdate, landUseGroup: landUseGroupUpdate,
landUseOrder: landUseOrderUpdate landUseOrder: landUseOrderUpdate
}; };
} }
function hasDuplicates(array: any[]) {
return (new Set(array).size !== array.length);
}

View File

@ -1,6 +1,7 @@
import * as _ from 'lodash'; import * as _ from 'lodash';
import { hasAnyOwnProperty } from '../../../helpers'; import { hasAnyOwnProperty } from '../../../helpers';
import { ArgumentError } from '../../errors/general';
import { getCurrentBuildingDataById } from '../building'; import { getCurrentBuildingDataById } from '../building';
import { updateLandUse } from './landUse'; import { updateLandUse } from './landUse';
@ -16,6 +17,7 @@ export async function processBuildingUpdate(buildingId: number, buildingUpdate:
async function processCurrentLandUseClassifications(buildingId: number, buildingUpdate: any): Promise<any> { async function processCurrentLandUseClassifications(buildingId: number, buildingUpdate: any): Promise<any> {
const currentBuildingData = await getCurrentBuildingDataById(buildingId); const currentBuildingData = await getCurrentBuildingDataById(buildingId);
try {
const currentLandUseUpdate = await updateLandUse( const currentLandUseUpdate = await updateLandUse(
{ {
landUseGroup: currentBuildingData.current_landuse_group, landUseGroup: currentBuildingData.current_landuse_group,
@ -29,4 +31,10 @@ async function processCurrentLandUseClassifications(buildingId: number, building
current_landuse_group: currentLandUseUpdate.landUseGroup, current_landuse_group: currentLandUseUpdate.landUseGroup,
current_landuse_order: currentLandUseUpdate.landUseOrder, current_landuse_order: currentLandUseUpdate.landUseOrder,
}); });
} catch (error) {
if(error instanceof ArgumentError && error.argumentName === 'landUseUpdate') {
error.argumentName = 'buildingUpdate';
}
throw error;
}
} }