IEEE.org     |     IEEE Xplore Digital Library     |     IEEE Standards     |     IEEE Spectrum     |     More Sites

Unverified Commit 99138493 authored by tilley14's avatar tilley14 Committed by GitHub
Browse files

Asset Donor Search Backend (#95)

parent 7a115383
......@@ -28,14 +28,22 @@ describe('assets.controller.find', () => {
it('accesses DB and sends JSON response when no project_id is provided', async () => {
await find(req, res, next);
expect(assetsDb.find).toHaveBeenCalledWith(undefined, undefined, undefined);
expect(assetsDb.find).toHaveBeenCalledWith(undefined, undefined, undefined, undefined);
expect(res.json).toHaveBeenCalledWith(EXPECTED_ASSETS);
});
it('accesses DB and sends JSON response when project_id is provided', async () => {
req.valid['project_id'] = 2;
await find(req, res, next);
expect(assetsDb.find).toHaveBeenCalledWith(undefined, 2, undefined);
expect(assetsDb.find).toHaveBeenCalledWith(undefined, 2, undefined, undefined);
expect(res.json).toHaveBeenCalledWith(EXPECTED_ASSETS);
});
it('accesses DB and sends JSON response when project_id is provided', async () => {
const valid_donor_codes = ['abc123', 'cc1211'];
req.valid['donor_code'] = valid_donor_codes;
await find(req, res, next);
expect(assetsDb.find).toHaveBeenCalledWith(undefined, undefined, undefined, valid_donor_codes);
expect(res.json).toHaveBeenCalledWith(EXPECTED_ASSETS);
});
......@@ -53,4 +61,4 @@ describe('assets.controller.find', () => {
expect(next).toHaveBeenCalledWith(DB_ERROR);
expect(res.json).not.toHaveBeenCalled();
});
});
\ No newline at end of file
});
......@@ -4,9 +4,10 @@ const find = async (req, res, next) => {
const sponsorId = req.valid.sponsor_id;
const projectId = req.valid.project_id;
const assetId = req.valid.asset_type_id;
const donorCodes = req.valid.donor_code;
try {
const assets = await assetsDb.find(sponsorId, projectId, assetId);
const assets = await assetsDb.find(sponsorId, projectId, assetId, donorCodes);
res.json(assets);
} catch (error) {
next(error);
......
......@@ -29,6 +29,15 @@ describe('assets.db.find', () => {
expect(query.mock.calls[0][1]).toEqual([54]);
});
it('executes correct DB query when donor_code is specified', async () => {
const valid_donor_codes = ['abc123', 'xyz987'];
await find(undefined, undefined, undefined, valid_donor_codes);
expect(query).toHaveBeenCalledTimes(1);
expect(query.mock.calls[0][0]).toEqual(expect.stringContaining('AND donor_code = ANY'));
expect(query.mock.calls[0][1]).toEqual(expect.arrayContaining([valid_donor_codes]));
});
it('returns an array of asset rows', async () => {
rows = [
{ id: 1, project_id: 1, latitude: 2, longitude: 3 },
......@@ -46,4 +55,4 @@ describe('assets.db.find', () => {
await expect(find()).rejects.toThrow();
});
});
\ No newline at end of file
});
......@@ -8,7 +8,8 @@ const QUERY_FIND = `
asset_type.name AS asset_type,
asset_type.description AS asset_description,
ST_Y(asset.location) AS latitude,
ST_X(asset.location) AS longitude
ST_X(asset.location) AS longitude,
asset.donor_code AS donor_code
FROM
asset
JOIN project ON asset.project_id = project.id
......@@ -22,25 +23,37 @@ const QUERY_FIND = `
*
* Returns all assets across all projects unless projectId is given.
*
* @param {number} sponsorId - The ID of the sponsor
* @param {number} [projectId] - (assumes isValidDbInteger(projectId)): optional: filter assets by this Project ID
* @param {number} assetType - the ID of the asset type
* @param {Array} donorCodes - a list of donor codes that the asset could have
* @returns {object[]|undefined} array of assets with fields (id, project_id, latitude, and longitude), or undefined if projectId is invalid.
* @throws error if the DB query failed to execute
*/
const find = async (sponsorId, projectId, assetType) => {
const find = async (sponsorId, projectId, assetType, donorCodes = undefined) => {
let query = QUERY_FIND;
let values = [];
if ((typeof sponsorId !== 'undefined') & (sponsorId > 0)) {
if ((typeof sponsorId !== 'undefined') && (sponsorId > 0)) {
values.push(sponsorId);
query = query + `AND sponsor_id = $${values.length}` + ' ';
}
if ((typeof projectId !== 'undefined') & (projectId > 0)) {
if ((typeof projectId !== 'undefined') && (projectId > 0)) {
values.push(projectId);
query = query + `AND project_id = $${values.length}` + ' ';
}
if ((typeof assetType !== 'undefined') & (assetType > 0)) {
if ((typeof assetType !== 'undefined') && (assetType > 0)) {
values.push(assetType);
query = query + `AND asset_type_id = $${values.length}` + ' ';
}
if ((typeof donorCodes !== 'undefined') && (donorCodes.length > 0)) {
values.push(donorCodes);
query = query + `AND donor_code = ANY ($${values.length})` + ' ';
}
const result = await global.dbPool.query(query, values);
return result.rows;
};
......
......@@ -685,3 +685,29 @@ describe('validate.param.params', () => {
expect(result).toBe(undefined);
});
});
describe('validate.type.donorCode', () => {
it('parses a single donor code and returns an array', () => {
const donor_code = 'FF00ABC';
const result = type.donorCode(donor_code);
expect(result.isSuccess()).toBeTruthy();
expect(result.value).toEqual(expect.arrayContaining([donor_code]));
});
it('parses an array of donor codes', () => {
const donor_code = ['FF00ABC', 'AABB1122'];
const result = type.donorCode(donor_code);
expect(result.isSuccess()).toBeTruthy();
expect(result.value).toEqual(expect.arrayContaining(donor_code));
});
it('returns a ParseResult.failure() if the donor code is Undefined', () => {
const result = type.donorCode(undefined);
expect(result.isFailure()).toBeTruthy();
});
it('returns a ParseResult.failure() if the donor code is an empty array', () => {
const result = type.donorCode([]);
expect(result.isFailure()).toBeTruthy();
});
});
......@@ -53,6 +53,16 @@ router.post(
temporal.temporalSearch
);
// donor code search
router.post(
'/assets/donor',
validate(param.body, 'sponsor_id', type.id),
validate(param.body, 'project_id', type.id),
validate(param.body, 'asset_type_id', type.id),
validate(param.body, 'donor_code', type.donorCode),
assets.find
);
// Assets
router.get(
'/assets',
......
......@@ -509,6 +509,31 @@ const parseProject = (project) => {
return ParseResult.success(project);
};
/**
* Validates a donor code or a list of donor codes
*
* @param {*} donor_codes - the donor code string or an array of donor codes
* @returns {ParseResult} a successful ParseResult if its a valid donor code
*/
const parseDonorCode = (donor_codes) => {
if (parseString(donor_codes)) {
return ParseResult.success([donor_codes]);
} else if (Array.isArray(donor_codes) && donor_codes.length != 0) {
var allStrings = true;
for (const code in donor_codes) {
if (!parseString(code)) {
allStrings = false;
break;
}
}
if (allStrings) {
return ParseResult.success(donor_codes);
}
}
return ParseResult.failure('donor_code must be a string or an array of strings.');
};
module.exports = {
validate,
......@@ -524,6 +549,7 @@ module.exports = {
assetTypeName: parseAssetTypeName,
coordinates: parseCoordinates,
date: parseDate,
donorCode: parseDonorCode,
geometry: parseGeometry,
latitude: parseLatitude,
longitude: parseLongitude,
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment