From d47d77bb5e89c6ff675fb2ddbf6da16105226d40 Mon Sep 17 00:00:00 2001 From: Mike Gerwitz Date: Wed, 28 Jun 2017 14:51:34 -0400 Subject: [PATCH] Add server.meta.DapiMetaSource Encapsulates the nasty. * src/server/meta/DapiMetaSource.js: Add class. * test/server/meta/DapiMetaSourceTest.js: Add test case. --- src/server/meta/DapiMetaSource.js | 109 ++++++++++++++++++ test/server/meta/DapiMetaSourceTest.js | 149 +++++++++++++++++++++++++ 2 files changed, 258 insertions(+) create mode 100644 src/server/meta/DapiMetaSource.js create mode 100644 test/server/meta/DapiMetaSourceTest.js diff --git a/src/server/meta/DapiMetaSource.js b/src/server/meta/DapiMetaSource.js new file mode 100644 index 0000000..fecfe2d --- /dev/null +++ b/src/server/meta/DapiMetaSource.js @@ -0,0 +1,109 @@ +/** + * Data-API-based metadata population + * + * Copyright (C) 2017 R-T Specialty, LLC. + * + * This file is part of the Liza Data Collection Framework. + * + * liza is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +"use strict"; + +const { Class } = require( 'easejs' ); + + +/** + * Retrieve data for meta field using Data API + * + * TODO: The reason this class exists at all is to encapsulate the horrid + * API. Once refactored, perhaps this class will no longer be necessary. + */ +module.exports = Class( 'DapiMetaSource', +{ + /** + * Metabucket constructor + * @type {function()} + */ + 'private _bucketf': null, + + + /** + * Initialize with metabucket constructor + * @type {function()} + */ + constructor( bucketf ) + { + this._bucketf = bucketf; + }, + + + /** + * Retrieve field data + * + * @param {string} field field name + * @param {number} index field index + * @param {DataApiManager} dapi_manager manager for dapi calls + * @param {Object} dapi dapi descriptor + * @param {Object} data dapi input data + * + * @return {Promise} object containing `field`, `index`, and return data + */ + 'public getFieldData'( field, index, dapi_manager, dapi, data ) + { + const metabucket = this._bucketf(); + + return new Promise( ( resolve, reject ) => + { + dapi_manager.getApiData( + dapi.name, + data, + ( err, api_data ) => + { + dapi_manager.setFieldData( + dapi.name, + index, + api_data, + dapi.value, + '', + false + ); + + dapi_manager.expandFieldData( + dapi.name, + index, + metabucket, + dapi.mapdest, + true, + { + [dapi.name]: { + [index]: api_data[ 0 ][ dapi.value ], + }, + } + ); + + resolve( { + field: field, + index: index, + data: metabucket.getData(), + } ); + }, + field, + index, + {}, + reject + ); + } ); + }, +} ); diff --git a/test/server/meta/DapiMetaSourceTest.js b/test/server/meta/DapiMetaSourceTest.js new file mode 100644 index 0000000..87ff860 --- /dev/null +++ b/test/server/meta/DapiMetaSourceTest.js @@ -0,0 +1,149 @@ +/** + * Tests Data-API-based metadata population + * + * Copyright (C) 2017 R-T Specialty, LLC. + * + * This file is part of the Liza Data Collection Framework. + * + * liza is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +"use strict"; + +const expect = require( 'chai' ).expect; +const Sut = require( '../../../' ).server.meta.DapiMetaSource; + +describe( "DapiMetaSource", () => +{ + it( "populates field with dapi response", () => + { + const dapim = createStubDapiManager(); + const field_name = 'field_foo'; + const index = 1; + + const dapi = { + name: 'dapi_name', + value: 'foo', + mapdest: { map: 'dest' }, + }; + + // input data to dapi + const given_data = {}; + + // dapi output data (response) + const ret_data = [ {} ]; + + const bucket_result = { + [dapi.name]: { + [index]: ret_data[ 0 ][ dapi.value ], + }, + }; + + const metabucket = getStubBucket(); + + // g prefix = "given" + // all these show why we want to encapsulate this garbage + dapim.getApiData = ( gapi, gdata, gcallback, gname, gindex ) => + { + expect( gapi ).to.equal( dapi.name ); + expect( gdata ).to.equal( given_data ); + expect( gname ).to.equal( field_name ); + expect( gindex ).to.equal( index ); + + // make sure we handle async + process.nextTick( () => gcallback( null, ret_data ) ); + }; + + dapim.setFieldData = + ( gname, gindex, gdata, gvalue, glabel, gunchanged ) => + { + expect( gname ).to.equal( dapi.name ); + expect( gindex ).to.equal( index ); + expect( gdata ).to.equal( ret_data ); + expect( gvalue ).to.equal( dapi.value ); + expect( glabel ).to.equal( '' ); // unused + expect( gunchanged ).to.equal( false ); + }; + + dapim.expandFieldData = + ( gname, gindex, gbucket, gmap, gpredictive, gdiff ) => + { + expect( gname ).to.equal( dapi.name ); + expect( gindex ).to.equal( index ); + expect( gbucket ).to.equal( metabucket ); + expect( gmap ).to.equal( dapi.mapdest ); + expect( gpredictive ).to.equal( true ); + expect( gdiff ).to.deep.equal( bucket_result ); + + metabucket.getData = () => bucket_result; + }; + + return Sut( () => metabucket ) + .getFieldData( field_name, index, dapim, dapi, given_data ) + .then( result => + { + expect( result.field ).to.equal( field_name ); + expect( result.index ).to.equal( index ); + expect( result.data ).to.equal( bucket_result ); + } ); + } ); + + + it( "rejects promise on error", () => + { + const e = Error( "Test error" ); + const dapim = createStubDapiManager(); + + dapim.getApiData = ( _, __, ___, ____, _____, ______, failc ) => + { + failc( e ); + }; + + return Sut( () => getStubBucket() ) + .getFieldData( 'name', 0, dapim, {}, {} ) + .catch( given_e => + { + expect( given_e ).to.equal( e ); + + return true; + } ); + } ); +} ); + + +function createStubDapiManager() +{ + return { + getApiData() {}, + setFieldData() {}, + expandFieldData() {}, + }; +} + + +function getStubBucket() +{ + return { + setValues() {}, + getData() {}, + }; +} + + +function createStubDb() +{ + return { + saveQuoteMeta() {}, + }; +}