Notification support given no rating results
commit
f38d0bf96c
|
@ -49,7 +49,8 @@
|
|||
"remote": {
|
||||
"host": "localhost",
|
||||
"domain": ""
|
||||
}
|
||||
},
|
||||
"noResultsUrl": ""
|
||||
},
|
||||
"c1export": {
|
||||
"host": "localhost",
|
||||
|
|
|
@ -61,7 +61,7 @@ module.exports = Class( 'QuoteDataApi' )
|
|||
if ( !( Class.isA( DataApi, dapi ) ) )
|
||||
{
|
||||
throw TypeError(
|
||||
'Expected object of type DataApi; given: ' + data_api
|
||||
'Expected object of type DataApi; given: ' + dapi
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -139,14 +139,33 @@ module.exports = Class( 'HttpDataApi' )
|
|||
|
||||
this._validateDataType( data );
|
||||
|
||||
this._impl.requestData(
|
||||
this._url,
|
||||
this._method,
|
||||
this.requestData( this._url, this._method, data, callback );
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Request data from underlying HttpImpl
|
||||
*
|
||||
* Subtypes may override this method to alter any aspect of the request
|
||||
* before sending.
|
||||
*
|
||||
* @param {string} url destination URL
|
||||
* @param {string} method RFC-2616-compliant HTTP method
|
||||
* @param {Object|string} data request params
|
||||
* @param {function(?Error, ?string)} callback server response callback
|
||||
*
|
||||
* @return {HttpDataApi} self
|
||||
*/
|
||||
'virtual protected requestData'( url, method, data, callback )
|
||||
{
|
||||
return this._impl.requestData(
|
||||
url,
|
||||
method,
|
||||
this.encodeData( data ),
|
||||
callback
|
||||
);
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,127 @@
|
|||
/**
|
||||
* Provide data as part of URL
|
||||
*
|
||||
* Copyright (C) 2018 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 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const { Trait } = require( 'easejs' );
|
||||
const HttpDataApi = require( './HttpDataApi' );
|
||||
|
||||
|
||||
/**
|
||||
* Place fields from given data in the URL
|
||||
*
|
||||
* All remaining fields are passed to the underlying supertype.
|
||||
*/
|
||||
module.exports = Trait( 'HttpDataApiUrlData' )
|
||||
.extend( HttpDataApi,
|
||||
{
|
||||
/**
|
||||
* Fields to take from data and place in URL
|
||||
* @type {string}
|
||||
*/
|
||||
'private _fields': [],
|
||||
|
||||
|
||||
/**
|
||||
* Initialize with URL field list
|
||||
*
|
||||
* @param {Array<string>} fields list of fields to include in URL
|
||||
*/
|
||||
__mixin( fields )
|
||||
{
|
||||
this._fields = fields;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Concatenate chosen fields with URL
|
||||
*
|
||||
* The previously specified fields will have their values delimited by '/'
|
||||
* and will be concatenated with the URL. All used fields in DATA will be
|
||||
* removed before being passed to the supertype. METHOD and CALLBACK are
|
||||
* proxied as-is.
|
||||
*
|
||||
* @param {string} url destination URL
|
||||
* @param {string} method RFC-2616-compliant HTTP method
|
||||
* @param {Object|string} data request params
|
||||
* @param {function(Error, Object)} callback server response callback
|
||||
*
|
||||
* @return {HttpImpl} self
|
||||
*/
|
||||
'override public requestData'( url, method, data, callback )
|
||||
{
|
||||
const [ values, filtered_data ] = this._getFieldValues( data );
|
||||
|
||||
const params = values.map( ( [ , value ] ) => value );
|
||||
const missing = values.filter( ( [ , value ] ) => value === undefined );
|
||||
|
||||
if ( missing.length > 0 )
|
||||
{
|
||||
callback(
|
||||
Error(
|
||||
"Missing URL parameters: " +
|
||||
missing.map( ( [ field ] ) => field ).join( ", " )
|
||||
),
|
||||
null
|
||||
);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
const built_url = ( params.length > 0 )
|
||||
? url + '/' + params.join( '/' )
|
||||
: url;
|
||||
|
||||
return this.__super( built_url, method, filtered_data, callback );
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Associate fields with their respective values from DATA
|
||||
*
|
||||
* The returned values are of the form `[ [ field, value ], ... ]`.
|
||||
* The returned data object is a copy of the original and is stripped
|
||||
* of the respective fields.
|
||||
*
|
||||
* @param {Object} data source data
|
||||
*
|
||||
* @return {Array} values and copy of data stripped of those fields
|
||||
*/
|
||||
'private _getFieldValues'( data )
|
||||
{
|
||||
const fieldset = new Set( this._fields );
|
||||
const values = this._fields.map( field => [ field, data[ field ] ] );
|
||||
|
||||
// copy of data with fields stripped
|
||||
const new_data = Object.keys( data ).reduce( ( dest, key ) =>
|
||||
{
|
||||
if ( fieldset.has( key ) )
|
||||
{
|
||||
return dest;
|
||||
}
|
||||
|
||||
dest[ key ] = data[ key ];
|
||||
return dest;
|
||||
}, {} );
|
||||
|
||||
return [ values, new_data ];
|
||||
},
|
||||
} );
|
|
@ -87,7 +87,7 @@ module.exports = Class( 'NodeHttpImpl' )
|
|||
*
|
||||
* @return {HttpImpl} self
|
||||
*/
|
||||
'public requestData'( url, method, data, callback )
|
||||
'virtual public requestData'( url, method, data, callback )
|
||||
{
|
||||
const options = this._parseUrl( url );
|
||||
const protocol = options.protocol.replace( /:$/, '' );
|
||||
|
|
|
@ -37,7 +37,7 @@ module.exports = Trait( 'SpoofedNodeHttpImpl' )
|
|||
{
|
||||
/**
|
||||
* Session to spoof
|
||||
* @type {UserSession}
|
||||
* @type {UserRequest}
|
||||
*/
|
||||
'private _request': null,
|
||||
|
||||
|
@ -45,11 +45,11 @@ module.exports = Trait( 'SpoofedNodeHttpImpl' )
|
|||
/**
|
||||
* Use session for spoofing requests
|
||||
*
|
||||
* @param {UserSession} session session to spoof
|
||||
* @param {UserRequest} request session to spoof
|
||||
*/
|
||||
__mixin( session )
|
||||
__mixin( request )
|
||||
{
|
||||
this._request = session;
|
||||
this._request = request;
|
||||
},
|
||||
|
||||
|
||||
|
|
|
@ -71,7 +71,7 @@ module.exports = Class( 'XhrHttpImpl' )
|
|||
*
|
||||
* @return {HttpImpl} self
|
||||
*/
|
||||
'public requestData': function( url, method, data, callback )
|
||||
'virtual public requestData': function( url, method, data, callback )
|
||||
{
|
||||
if ( typeof data !== 'string' )
|
||||
{
|
||||
|
|
|
@ -113,7 +113,8 @@ module.exports = AbstractClass( 'Daemon',
|
|||
this._createDebugLog(),
|
||||
this._createAccessLog(),
|
||||
this._conf.get( 'skey' ),
|
||||
] ).then( ([ debug_log, access_log, skey ]) =>
|
||||
this._conf.get( 'services.rating.noResultsUrl' ),
|
||||
] ).then( ([ debug_log, access_log, skey, no_results_url ]) =>
|
||||
{
|
||||
this._debugLog = debug_log;
|
||||
this._accessLog = access_log;
|
||||
|
@ -122,7 +123,7 @@ module.exports = AbstractClass( 'Daemon',
|
|||
this._rater = liza.server.rater.ProcessManager();
|
||||
this._encService = this.getEncryptionService();
|
||||
this._memcache = this.getMemcacheClient();
|
||||
this._routers = this.getRouters( skey );
|
||||
this._routers = this.getRouters( skey, no_results_url );
|
||||
} )
|
||||
.then( () => this._startDaemon() );
|
||||
},
|
||||
|
@ -182,14 +183,16 @@ module.exports = AbstractClass( 'Daemon',
|
|||
},
|
||||
|
||||
|
||||
'protected getProgramController': function( skey )
|
||||
'protected getProgramController': function( skey, no_results_url )
|
||||
{
|
||||
var controller = require( './controller' );
|
||||
controller.rater = this._rater;
|
||||
|
||||
controller.rater = this._rater;
|
||||
controller.no_results_url = no_results_url || "";
|
||||
|
||||
if ( skey )
|
||||
{
|
||||
controller.skey = skey;
|
||||
controller.skey = skey;
|
||||
}
|
||||
|
||||
return controller;
|
||||
|
@ -276,10 +279,10 @@ module.exports = AbstractClass( 'Daemon',
|
|||
'abstract protected getEncryptionService': [],
|
||||
|
||||
|
||||
'protected getRouters': function( skey )
|
||||
'protected getRouters': function( skey, no_results_url )
|
||||
{
|
||||
return [
|
||||
this.getProgramController( skey ),
|
||||
this.getProgramController( skey, no_results_url ),
|
||||
this.getScriptsController(),
|
||||
this.getClientErrorController(),
|
||||
];
|
||||
|
|
|
@ -43,6 +43,12 @@ const {
|
|||
},
|
||||
|
||||
dapi: {
|
||||
http: {
|
||||
HttpDataApi,
|
||||
HttpDataApiUrlData,
|
||||
NodeHttpImpl,
|
||||
SpoofedNodeHttpImpl,
|
||||
},
|
||||
DataApiFactory,
|
||||
DataApiManager,
|
||||
},
|
||||
|
@ -69,6 +75,7 @@ const {
|
|||
},
|
||||
|
||||
RatingService,
|
||||
RatingServiceSubmitNotify,
|
||||
TokenedService,
|
||||
TokenDao,
|
||||
},
|
||||
|
@ -93,8 +100,9 @@ var sflag = {};
|
|||
|
||||
|
||||
// TODO: kluge to get liza somewhat decoupled from lovullo (rating module)
|
||||
exports.rater = {};
|
||||
exports.skey = "";
|
||||
exports.rater = {};
|
||||
exports.skey = "";
|
||||
exports.no_results_url = "";
|
||||
|
||||
|
||||
exports.init = function( logger, enc_service, conf )
|
||||
|
@ -118,7 +126,31 @@ exports.init = function( logger, enc_service, conf )
|
|||
server_cache = _createCache( server );
|
||||
server.init( server_cache, exports.rater );
|
||||
|
||||
rating_service = RatingService( logger, dao, server, exports.rater );
|
||||
// TODO: do none of this if no_results_url is provided
|
||||
const createSubmitDapi = request => HttpDataApi
|
||||
.use( HttpDataApiUrlData( [ 'quote_id' ] ) )
|
||||
(
|
||||
exports.no_results_url,
|
||||
'PUT',
|
||||
|
||||
NodeHttpImpl
|
||||
.use( SpoofedNodeHttpImpl( request ) )
|
||||
(
|
||||
{
|
||||
http: require( 'http' ),
|
||||
https: require( 'https' ),
|
||||
},
|
||||
require( 'url' ),
|
||||
this._origin
|
||||
),
|
||||
''
|
||||
);
|
||||
|
||||
rating_service = RatingService
|
||||
.use( RatingServiceSubmitNotify( createSubmitDapi, dao ) )
|
||||
(
|
||||
logger, dao, server, exports.rater
|
||||
);
|
||||
|
||||
// TODO: exports.init needs to support callbacks; this will work, but
|
||||
// only because it's unlikely that we'll get a request within
|
||||
|
|
|
@ -783,5 +783,70 @@ module.exports = Class( 'MongoServerDao' )
|
|||
}
|
||||
);
|
||||
},
|
||||
} );
|
||||
|
||||
|
||||
/**
|
||||
* Set arbitrary data on a document
|
||||
*
|
||||
* @param {number} qid quote/document id
|
||||
* @param {string} key field key
|
||||
* @param {*} value field value
|
||||
* @param {function(?Error)} callback completion callback
|
||||
*
|
||||
* @return {undefined}
|
||||
*/
|
||||
'public setDocumentField'( qid, key, value, callback )
|
||||
{
|
||||
this._collection.update(
|
||||
{ id: qid },
|
||||
{ '$set': { [key]: value } },
|
||||
|
||||
// create record if it does not yet exist
|
||||
{ upsert: true },
|
||||
|
||||
// on complete
|
||||
function( err )
|
||||
{
|
||||
callback && callback( err );
|
||||
return;
|
||||
}
|
||||
);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Retrieve arbitrary data on a document
|
||||
*
|
||||
* @param {number} qid quote/document id
|
||||
* @param {string} key field key
|
||||
* @param {function(?Error)} callback completion callback
|
||||
*
|
||||
* @return {undefined}
|
||||
*/
|
||||
'public getDocumentField'( qid, key, callback )
|
||||
{
|
||||
this._collection.find(
|
||||
{ id: qid },
|
||||
{ limit: 1 },
|
||||
function( err, cursor )
|
||||
{
|
||||
if ( err !== null )
|
||||
{
|
||||
callback( err, null );
|
||||
return;
|
||||
}
|
||||
|
||||
cursor.toArray( function( err, data )
|
||||
{
|
||||
if ( err !== null )
|
||||
{
|
||||
callback( err, null );
|
||||
return;
|
||||
}
|
||||
|
||||
callback( null, data[ key ] );
|
||||
} );
|
||||
}
|
||||
);
|
||||
},
|
||||
} );
|
||||
|
|
|
@ -154,8 +154,8 @@ module.exports = Class( 'RatingService',
|
|||
{
|
||||
actions = actions || [];
|
||||
|
||||
_self._postProcessRaterData(
|
||||
rate_data, actions, program, quote
|
||||
_self.postProcessRaterData(
|
||||
request, rate_data, actions, program, quote
|
||||
);
|
||||
|
||||
const class_dest = {};
|
||||
|
@ -244,14 +244,17 @@ module.exports = Class( 'RatingService',
|
|||
/**
|
||||
* Process rater data returned from a rater
|
||||
*
|
||||
* @param {Object} data rating data returned
|
||||
* @param {Array} actions actions to send to client
|
||||
* @param {Program} program program used to perform rating
|
||||
* @param {Quote} quote quote used for rating
|
||||
* @param {UserRequest} request user request to satisfy
|
||||
* @param {Object} data rating data returned
|
||||
* @param {Array} actions actions to send to client
|
||||
* @param {Program} program program used to perform rating
|
||||
* @param {Quote} quote quote used for rating
|
||||
*
|
||||
* @return {undefined}
|
||||
*/
|
||||
_postProcessRaterData: function( data, actions, program, quote )
|
||||
'virtual protected postProcessRaterData': function(
|
||||
request, data, actions, program, quote
|
||||
)
|
||||
{
|
||||
var meta = data._cmpdata || {};
|
||||
|
||||
|
|
|
@ -0,0 +1,140 @@
|
|||
/**
|
||||
* Notification on all submit
|
||||
*
|
||||
* Copyright (C) 2018 R-T Specialty, LLC.
|
||||
*
|
||||
* This file is part of liza.
|
||||
*
|
||||
* liza is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const { Trait } = require( 'easejs' );
|
||||
const DslRaterContext = require( '../rater/DslRaterContext' )
|
||||
const RatingService = require( './RatingService' );
|
||||
|
||||
|
||||
/**
|
||||
* Triggers DataApi when no results are available
|
||||
*
|
||||
* This information is currently stored in `__prem_avail_count`. In the
|
||||
* future, it may be worth accepting a parameter to configure this at
|
||||
* runtime.
|
||||
*
|
||||
* Notification status will persist using the provided DAO. The next time
|
||||
* such a notification is requested, it will only occur if the flag is not
|
||||
* set.
|
||||
*/
|
||||
module.exports = Trait( 'RatingServiceSubmitNotify' )
|
||||
.extend( RatingService,
|
||||
{
|
||||
/**
|
||||
* Function returning DataApi to trigger
|
||||
* @type {Function(UserSession):DataApi}
|
||||
*/
|
||||
'private _dapif': null,
|
||||
|
||||
/**
|
||||
* Data store for notification flag
|
||||
* @type {ServerDao}
|
||||
*/
|
||||
'private _notifyDao': null,
|
||||
|
||||
|
||||
/**
|
||||
* Initialize mixin with DataApi to trigger
|
||||
*
|
||||
* @param {Function(UserSession):DataApi} dapif Function producing DataApi
|
||||
* @param {ServerDao} dao store for notification flag
|
||||
*/
|
||||
__mixin( dapif, dao )
|
||||
{
|
||||
this._dapif = dapif;
|
||||
this._notifyDao = dao;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Trigger previously provided DataApi when no results are available
|
||||
*
|
||||
* Result count is determined by DATA.__prem_avail_count.
|
||||
*
|
||||
* @param {UserRequest} request user request
|
||||
* @param {Object} data rating data returned
|
||||
* @param {Array} actions actions to send to client
|
||||
* @param {Program} program program used to perform rating
|
||||
* @param {Quote} quote quote used for rating
|
||||
*
|
||||
* @return {undefined}
|
||||
*/
|
||||
'override protected postProcessRaterData'(
|
||||
request, data, actions, program, quote
|
||||
)
|
||||
{
|
||||
const quote_id = quote.getId();
|
||||
const avail = ( data.__prem_avail_count || [ 0 ] )[ 0 ];
|
||||
|
||||
if ( avail === 0 )
|
||||
{
|
||||
this._getNotifyState( quote_id, notified =>
|
||||
{
|
||||
if ( notified === true )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this._dapif( request )
|
||||
.request( { quote_id: quote_id }, () => {} );
|
||||
|
||||
this._setNotified( quote_id );
|
||||
} );
|
||||
}
|
||||
|
||||
this.__super( request, data, actions, program, quote );
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Get value of notification flag
|
||||
*
|
||||
* @param {number} quote_id id of quote
|
||||
* @param {function(boolean)} callback callback to call when complete
|
||||
*
|
||||
* @return {undefined}
|
||||
*/
|
||||
'private _getNotifyState'( quote_id, callback )
|
||||
{
|
||||
this._notifyDao.getDocumentField(
|
||||
quote_id,
|
||||
'submitNotified',
|
||||
( err, value ) => callback( value )
|
||||
);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Set notification flag
|
||||
*
|
||||
* @param {number} quote_id id of quote
|
||||
*
|
||||
* @return {undefined}
|
||||
*/
|
||||
'private _setNotified'( quote_id )
|
||||
{
|
||||
this._notifyDao.setDocumentField(
|
||||
quote_id, 'submitNotified', true
|
||||
);
|
||||
},
|
||||
} );
|
|
@ -0,0 +1,87 @@
|
|||
/**
|
||||
* Tests RatingService
|
||||
*
|
||||
* Copyright (C) 2018 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 Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
'use strict'
|
||||
|
||||
|
||||
exports.getStubs = function()
|
||||
{
|
||||
const program_id = 'foo';
|
||||
const program = {
|
||||
getId: () => program_id,
|
||||
};
|
||||
|
||||
// rate reply
|
||||
const stub_rate_data = {};
|
||||
|
||||
const rater = {
|
||||
rate: ( quote, session, indv, callback ) => callback( stub_rate_data ),
|
||||
};
|
||||
|
||||
const raters = {
|
||||
byId: () => rater,
|
||||
};
|
||||
|
||||
const logger = {
|
||||
log: () => {},
|
||||
};
|
||||
|
||||
const server = {
|
||||
sendResponse: () => {},
|
||||
sendError: () => {},
|
||||
};
|
||||
|
||||
const dao = {
|
||||
mergeBucket: () => {},
|
||||
saveQuoteClasses: () => {},
|
||||
setWorksheets: () => {},
|
||||
};
|
||||
|
||||
const session = {
|
||||
isInternal: () => false,
|
||||
};
|
||||
|
||||
const request = {
|
||||
getSession: () => session,
|
||||
getSessionIdName: () => {},
|
||||
};
|
||||
const response = {};
|
||||
|
||||
const quote = {
|
||||
getProgramId: () => program_id,
|
||||
getProgram: () => program,
|
||||
getId: () => 0,
|
||||
};
|
||||
|
||||
return {
|
||||
program: program,
|
||||
stub_rate_data: stub_rate_data,
|
||||
rater: rater,
|
||||
raters: raters,
|
||||
logger: logger,
|
||||
server: server,
|
||||
dao: dao,
|
||||
session: session,
|
||||
request: request,
|
||||
response: response,
|
||||
quote: quote,
|
||||
};
|
||||
};
|
|
@ -0,0 +1,123 @@
|
|||
/**
|
||||
* Tests HttpDataApiUrlData
|
||||
*
|
||||
* Copyright (C) 2018 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 Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
'use strict'
|
||||
|
||||
const { Class } = require( 'easejs' );
|
||||
const { expect } = require( 'chai' );
|
||||
|
||||
const {
|
||||
dapi: {
|
||||
http: {
|
||||
HttpDataApi,
|
||||
HttpImpl,
|
||||
HttpDataApiUrlData: Sut,
|
||||
},
|
||||
},
|
||||
} = require( '../../../' );
|
||||
|
||||
|
||||
describe( 'HttpDataApiUrlData', () =>
|
||||
{
|
||||
[
|
||||
{
|
||||
fields: [],
|
||||
data: {
|
||||
foo: "foodata",
|
||||
bar: "bardata",
|
||||
},
|
||||
base_url: "base",
|
||||
after_data: "foo=foodata&bar=bardata",
|
||||
expected: "base",
|
||||
},
|
||||
{
|
||||
fields: [ 'foo', 'bar' ],
|
||||
data: {
|
||||
foo: "foodata",
|
||||
bar: "bardata",
|
||||
baz: "shouldnotuse",
|
||||
},
|
||||
base_url: "base2",
|
||||
after_data: "baz=shouldnotuse",
|
||||
expected: "base2/foodata/bardata",
|
||||
},
|
||||
].forEach( ( { fields, data, base_url, after_data, expected }, i ) =>
|
||||
it( `can include portion of data in url (#${i})`, done =>
|
||||
{
|
||||
const expected_method = 'PUT';
|
||||
|
||||
const impl = Class.implement( HttpImpl ).extend(
|
||||
{
|
||||
'virtual requestData'( url, method, given_data, callback )
|
||||
{
|
||||
expect( url ).to.equal( expected );
|
||||
expect( method ).to.equal( expected_method );
|
||||
expect( given_data ).to.deep.equal( after_data );
|
||||
|
||||
// should not have mutated the original object
|
||||
// (they shouldn't be the same object)
|
||||
expect( data ).to.not.equal( given_data );
|
||||
|
||||
// should be done
|
||||
callback();
|
||||
},
|
||||
|
||||
setOptions: () => {},
|
||||
} )();
|
||||
|
||||
const sut = HttpDataApi.use( Sut( fields ) )(
|
||||
base_url, expected_method, impl
|
||||
);
|
||||
|
||||
const result = sut.request( data, done );
|
||||
} )
|
||||
);
|
||||
|
||||
|
||||
it( "throws error if param is missing from data", done =>
|
||||
{
|
||||
const impl = Class.implement( HttpImpl ).extend(
|
||||
{
|
||||
'virtual requestData': ( url, method, data, callback ) => {},
|
||||
setOptions: () => {},
|
||||
} )();
|
||||
|
||||
const sut = HttpDataApi.use( Sut( [ 'foo' ] ) )(
|
||||
'', 'PUT', impl
|
||||
);
|
||||
|
||||
// missing `foo` in data
|
||||
sut.request( { unused: "missing foo" }, ( err, data ) =>
|
||||
{
|
||||
expect( err ).to.be.instanceof( Error );
|
||||
expect( err.message ).to.match( /\bfoo\b/ );
|
||||
|
||||
expect( data ).to.equal( null );
|
||||
|
||||
done();
|
||||
} );
|
||||
} );
|
||||
} );
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,164 @@
|
|||
/**
|
||||
* Tests RatingServiceSubmitNotify
|
||||
*
|
||||
* Copyright (C) 2018 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 Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
'use strict'
|
||||
|
||||
const { Class } = require( 'easejs' );
|
||||
const { expect } = require( 'chai' );
|
||||
|
||||
|
||||
const {
|
||||
dapi: {
|
||||
DataApi,
|
||||
},
|
||||
server: {
|
||||
service: {
|
||||
RatingServiceSubmitNotify: Sut,
|
||||
RatingService,
|
||||
},
|
||||
},
|
||||
test: {
|
||||
server: {
|
||||
service: {
|
||||
RatingServiceStub,
|
||||
},
|
||||
},
|
||||
},
|
||||
} = require( '../../../' );
|
||||
|
||||
|
||||
describe( 'RatingServiceSubmitNotify', () =>
|
||||
{
|
||||
[
|
||||
{
|
||||
prem_avail_count: [ 0 ],
|
||||
prev_called: false,
|
||||
expected_request: true,
|
||||
},
|
||||
{
|
||||
prem_avail_count: [ 2 ],
|
||||
prev_called: false,
|
||||
expected_request: false,
|
||||
},
|
||||
{
|
||||
// this shouldn't happen; ignore all but first index
|
||||
prem_avail_count: [ 2, 2 ],
|
||||
prev_called: false,
|
||||
expected_request: false,
|
||||
},
|
||||
|
||||
// save as above, but already saved
|
||||
{
|
||||
prem_avail_count: [ 0 ],
|
||||
prev_called: true,
|
||||
expected_request: false,
|
||||
},
|
||||
{
|
||||
prem_avail_count: [ 2 ],
|
||||
prev_called: true,
|
||||
expected_request: false,
|
||||
},
|
||||
{
|
||||
// this shouldn't happen; ignore all but first index
|
||||
prem_avail_count: [ 2, 2 ],
|
||||
prev_called: true,
|
||||
expected_request: false,
|
||||
},
|
||||
].forEach( ( { prem_avail_count, expected_request, prev_called }, i ) =>
|
||||
it( `sends request on post process if no premiums (#${i})`, done =>
|
||||
{
|
||||
const {
|
||||
dao,
|
||||
logger,
|
||||
quote,
|
||||
raters,
|
||||
request,
|
||||
response,
|
||||
server,
|
||||
stub_rate_data,
|
||||
} = RatingServiceStub.getStubs();
|
||||
|
||||
const quote_id = 1234;
|
||||
let requested = false;
|
||||
|
||||
const dapif = given_request =>
|
||||
Class.implement( DataApi ).extend(
|
||||
{
|
||||
// warning: if an expectation fails, because of how
|
||||
// RatingService handles errors, it will cause the test to
|
||||
// _hang_ rather than throw the assertion error
|
||||
request( data, callback )
|
||||
{
|
||||
expect( given_request ).to.equal( request );
|
||||
expect( data ).to.deep.equal( { quote_id: quote_id } );
|
||||
|
||||
requested = true;
|
||||
},
|
||||
} )();
|
||||
|
||||
const sut = RatingService.use( Sut( dapif, dao ) )(
|
||||
logger, dao, server, raters
|
||||
);
|
||||
|
||||
quote.getId = () => quote_id;
|
||||
|
||||
// one of the methods that is called by the supertype
|
||||
let save_called = false;
|
||||
dao.setWorksheets = () => save_called = true;
|
||||
|
||||
// whether the notify flag is actually set
|
||||
let notify_saved = false;
|
||||
|
||||
// request for notification status
|
||||
dao.getDocumentField = ( qid, key, callback ) =>
|
||||
{
|
||||
expect( qid ).to.equal( quote_id );
|
||||
expect( key ).to.equal( 'submitNotified' );
|
||||
|
||||
callback( null, prev_called );
|
||||
};
|
||||
|
||||
dao.setDocumentField = ( qid, key, value, callback ) =>
|
||||
{
|
||||
expect( qid ).to.equal( quote_id );
|
||||
expect( key ).to.equal( 'submitNotified' );
|
||||
expect( value ).to.equal( true );
|
||||
|
||||
notify_saved = true;
|
||||
};
|
||||
|
||||
stub_rate_data.__prem_avail_count = prem_avail_count;
|
||||
|
||||
sut.request( request, response, quote, 'something', () =>
|
||||
{
|
||||
expect( requested ).to.equal( expected_request );
|
||||
expect( save_called ).to.be.true;
|
||||
|
||||
// only save notification status if we're notifying
|
||||
expect( notify_saved ).to.equal(
|
||||
!prev_called && expected_request
|
||||
);
|
||||
|
||||
done();
|
||||
} );
|
||||
} )
|
||||
);
|
||||
} );
|
|
@ -0,0 +1,65 @@
|
|||
/**
|
||||
* Tests RatingService
|
||||
*
|
||||
* Copyright (C) 2018 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 Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
'use strict'
|
||||
|
||||
const { expect } = require( 'chai' );
|
||||
const Sut = require( '../../../' ).server.service.RatingService;
|
||||
const RatingServiceStub = require( '../../../' ).test.server.service.RatingServiceStub;
|
||||
|
||||
describe( 'RatingService', () =>
|
||||
{
|
||||
describe( "protected API", () =>
|
||||
{
|
||||
it( "calls #postProcessRaterData after rating before save", done =>
|
||||
{
|
||||
let processed = false;
|
||||
|
||||
const {
|
||||
logger,
|
||||
server,
|
||||
raters,
|
||||
dao,
|
||||
request,
|
||||
response,
|
||||
quote,
|
||||
} = RatingServiceStub.getStubs();
|
||||
|
||||
dao.mergeBucket = () =>
|
||||
{
|
||||
expect( processed ).to.equal( true );
|
||||
done();
|
||||
};
|
||||
|
||||
const sut = Sut.extend(
|
||||
{
|
||||
'override postProcessRaterData'(
|
||||
request, data, actions, program, quote
|
||||
)
|
||||
{
|
||||
processed = true;
|
||||
}
|
||||
} )( logger, dao, server, raters );
|
||||
|
||||
sut.request( request, response, quote, 'something', () => {} );
|
||||
} );
|
||||
} );
|
||||
} );
|
Loading…
Reference in New Issue