Lock quotes past expiration date
commit
6edd5297a2
|
@ -40,6 +40,7 @@ If `configure` is not available, see the section "Configuring" above.
|
||||||
```
|
```
|
||||||
$ ./configure # see --help for optional arguments
|
$ ./configure # see --help for optional arguments
|
||||||
$ make # build
|
$ make # build
|
||||||
|
$ npm install # install js dependencies
|
||||||
$ make check # run test cases
|
$ make check # run test cases
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -2206,6 +2206,9 @@ module.exports = Class( 'Client' )
|
||||||
var client = this,
|
var client = this,
|
||||||
explicit_step = this._quote.getExplicitLockStep();
|
explicit_step = this._quote.getExplicitLockStep();
|
||||||
|
|
||||||
|
var lock_msg = this._quote.getExplicitLockReason() ||
|
||||||
|
"The quote is locked and cannot be modified.";
|
||||||
|
|
||||||
// if the step is locked to step 1, then there is no noticable effect;
|
// if the step is locked to step 1, then there is no noticable effect;
|
||||||
// don't bother
|
// don't bother
|
||||||
if ( explicit_step == 1 )
|
if ( explicit_step == 1 )
|
||||||
|
@ -2222,9 +2225,7 @@ module.exports = Class( 'Client' )
|
||||||
{
|
{
|
||||||
client.ui.showNotifyBar(
|
client.ui.showNotifyBar(
|
||||||
$( '<div>' ).append(
|
$( '<div>' ).append(
|
||||||
$( '<div class="text">' ).html(
|
$( '<div class="text">' ).html( lock_msg )
|
||||||
"The quote is locked and cannot be modified."
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}, 25 );
|
}, 25 );
|
||||||
|
|
|
@ -26,7 +26,6 @@ var Class = require( 'easejs' ).Class,
|
||||||
Program = require( '../program/Program' ).Program,
|
Program = require( '../program/Program' ).Program,
|
||||||
EventEmitter = require( 'events' ).EventEmitter;
|
EventEmitter = require( 'events' ).EventEmitter;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new quote
|
* Creates a new quote
|
||||||
*
|
*
|
||||||
|
@ -271,6 +270,71 @@ module.exports = Class( 'BaseQuote' )
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the quote's expiration date
|
||||||
|
*
|
||||||
|
* @return {number} quote's initial rated date
|
||||||
|
*/
|
||||||
|
'public getExpirationDate': function()
|
||||||
|
{
|
||||||
|
var post_rate = ( this._initialRatedDate > 0 );
|
||||||
|
|
||||||
|
// Don't attempt to calculate expiration date if expiration is not defined
|
||||||
|
if ( !this._program
|
||||||
|
|| !this._program.lockTimeout
|
||||||
|
|| ( !post_rate && !this._program.lockTimeout.preRateExpiration )
|
||||||
|
|| ( post_rate && !this._program.lockTimeout.postRateExpiration ))
|
||||||
|
{
|
||||||
|
return Number.POSITIVE_INFINITY;
|
||||||
|
}
|
||||||
|
|
||||||
|
var reference_date = ( post_rate ) ? this._initialRatedDate : this._startDate;
|
||||||
|
var expiration_period = ( post_rate )
|
||||||
|
? this._program.lockTimeout.postRateExpiration
|
||||||
|
: this._program.lockTimeout.preRateExpiration;
|
||||||
|
|
||||||
|
// Use Date.setDate to accommodate leap seconds, leap years, DST, etc.
|
||||||
|
var expiration_date = new Date( reference_date );
|
||||||
|
expiration_date.setDate( expiration_date.getDate() + expiration_period );
|
||||||
|
|
||||||
|
return expiration_date.getTime();
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether the quote has expired or not
|
||||||
|
*
|
||||||
|
* @param {Date} current_date current date to determine if expiration date has passed
|
||||||
|
*
|
||||||
|
* @return {boolean} flag indicating if the quote has expired
|
||||||
|
*/
|
||||||
|
'public hasExpired': function( current_date )
|
||||||
|
{
|
||||||
|
var timeout = ( this._program && this._program.lockTimeout )
|
||||||
|
? this._program.lockTimeout
|
||||||
|
: { preRateGracePeriod: 0, postRateGracePeriod: 0 };
|
||||||
|
|
||||||
|
var grace_period = ( this._initialRatedDate > 0 )
|
||||||
|
? ( timeout.postRateGracePeriod || 0 )
|
||||||
|
: ( timeout.preRateGracePeriod || 0 );
|
||||||
|
|
||||||
|
var expiration_timestamp = this.getExpirationDate();
|
||||||
|
|
||||||
|
// If the timestamp is INFINITY, the quote will never expire
|
||||||
|
// NOTE: The Date constructor does not support INFINITY as the timestamp
|
||||||
|
if ( expiration_timestamp === Number.POSITIVE_INFINITY )
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use Date.setDate to accommodate leap seconds, leap years, DST, etc.
|
||||||
|
var expiration_date = new Date( expiration_timestamp );
|
||||||
|
expiration_date.setDate( expiration_date.getDate() + grace_period );
|
||||||
|
|
||||||
|
return current_date.getTime() > expiration_date.getTime();
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets id of agent that owns the quote
|
* Sets id of agent that owns the quote
|
||||||
*
|
*
|
||||||
|
@ -681,7 +745,7 @@ module.exports = Class( 'BaseQuote' )
|
||||||
'public getExplicitLockReason': function()
|
'public getExplicitLockReason': function()
|
||||||
{
|
{
|
||||||
return ( this.isBound() )
|
return ( this.isBound() )
|
||||||
? 'Quote has been bound'
|
? 'This quote has been bound and cannot be modified.'
|
||||||
: this._explicitLock;
|
: this._explicitLock;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -255,6 +255,12 @@ module.exports = Class( 'Server' )
|
||||||
/**
|
/**
|
||||||
* Initializes a quote with any existing quote data
|
* Initializes a quote with any existing quote data
|
||||||
*
|
*
|
||||||
|
* @param Integer quote_id id of the quote
|
||||||
|
* @param Program program program that the quote will be a part of
|
||||||
|
* @param Object request request to create quote
|
||||||
|
* @param Function( quote ) callback function to call when quote is ready
|
||||||
|
* @param Function( quote ) callback function to call when an error occurs
|
||||||
|
*
|
||||||
* @return Server self to allow for method chaining
|
* @return Server self to allow for method chaining
|
||||||
*/
|
*/
|
||||||
initQuote: function( quote, program, request, callback, error_callback )
|
initQuote: function( quote, program, request, callback, error_callback )
|
||||||
|
@ -696,6 +702,15 @@ module.exports = Class( 'Server' )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Expire quote as needed
|
||||||
|
if ( quote.hasExpired( new Date() ) )
|
||||||
|
{
|
||||||
|
quote.setExplicitLock(
|
||||||
|
'This quote has expired and cannot be modified. ' +
|
||||||
|
'Please contact support with any questions.'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
var bucket = quote.getBucket(),
|
var bucket = quote.getBucket(),
|
||||||
lock = quote.getExplicitLockReason(),
|
lock = quote.getExplicitLockReason(),
|
||||||
lock_step = quote.getExplicitLockStep(),
|
lock_step = quote.getExplicitLockStep(),
|
||||||
|
@ -722,7 +737,7 @@ module.exports = Class( 'Server' )
|
||||||
)
|
)
|
||||||
} ];
|
} ];
|
||||||
|
|
||||||
lock = 'concurrent-access';
|
lock = 'Quote is locked due to concurrent access.';
|
||||||
}
|
}
|
||||||
|
|
||||||
// decrypt bucket contents, if necessary, and return
|
// decrypt bucket contents, if necessary, and return
|
||||||
|
|
|
@ -635,7 +635,9 @@ function doRoute( program, request, data, resolve, reject )
|
||||||
*
|
*
|
||||||
* @param Integer quote_id id of the quote
|
* @param Integer quote_id id of the quote
|
||||||
* @param Program program program that the quote will be a part of
|
* @param Program program program that the quote will be a part of
|
||||||
|
* @param Object request request to create quote
|
||||||
* @param Function( quote ) callback function to call when quote is ready
|
* @param Function( quote ) callback function to call when quote is ready
|
||||||
|
* @param Function( quote ) callback function to call when an error occurs
|
||||||
*
|
*
|
||||||
* @return undefined
|
* @return undefined
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -178,6 +178,6 @@ module.exports = Class( 'ServerSideQuote' )
|
||||||
|
|
||||||
this._metabucket.setValues( data );
|
this._metabucket.setValues( data );
|
||||||
return this;
|
return this;
|
||||||
},
|
}
|
||||||
} );
|
} );
|
||||||
|
|
||||||
|
|
|
@ -245,8 +245,29 @@ exports.stubCmatch = ( cmatch_dfn ) =>
|
||||||
return cmatch;
|
return cmatch;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Produce a stub class that extends the abstract Program class
|
||||||
|
*
|
||||||
|
* @param {Program} ProgramSut class to extend
|
||||||
|
* @param {function} mockInitQuote optional: mock implementation of 'initQuote' function
|
||||||
|
*
|
||||||
|
* @return {Class} stub class for creating mock Program object(s)
|
||||||
|
*/
|
||||||
|
exports.stubProgram = ( ProgramSut, mockInitQuote ) =>
|
||||||
|
{
|
||||||
|
// TODO: Make ProgramSut optional
|
||||||
|
if ( !ProgramSut )
|
||||||
|
{
|
||||||
|
throw new Error( "Class for Program stub must be specified." );
|
||||||
|
}
|
||||||
|
|
||||||
exports.stubProgram = Program => Program.extend(
|
mockInitQuote = mockInitQuote ||
|
||||||
|
ProgramSut.initQuote ||
|
||||||
|
( ( bucket, store_only ) => {} );
|
||||||
|
|
||||||
|
return ProgramSut.extend(
|
||||||
{
|
{
|
||||||
classifier: __dirname + '/DummyClassifier',
|
classifier: __dirname + '/DummyClassifier',
|
||||||
|
initQuote: mockInitQuote
|
||||||
} );
|
} );
|
||||||
|
};
|
||||||
|
|
|
@ -24,35 +24,388 @@
|
||||||
const chai = require( 'chai' );
|
const chai = require( 'chai' );
|
||||||
const expect = chai.expect;
|
const expect = chai.expect;
|
||||||
const { BaseQuote } = require( '../../' ).quote;
|
const { BaseQuote } = require( '../../' ).quote;
|
||||||
|
const Program = require( '../../src/program/Program' ).Program;
|
||||||
|
const Util = require( '../../src/test/program/util' );
|
||||||
|
|
||||||
|
const messages = {
|
||||||
|
expire: 'This quote has expired and cannot be modified. ' +
|
||||||
|
'Please contact support with any questions.',
|
||||||
|
bound: 'This quote has been bound and cannot be modified.'
|
||||||
|
};
|
||||||
|
|
||||||
describe( 'BaseQuote', () =>
|
describe( 'BaseQuote', () =>
|
||||||
|
{
|
||||||
|
describe( 'accessors & mutators', () =>
|
||||||
{
|
{
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
property: 'startDate',
|
property: 'startDate',
|
||||||
value: 12345
|
default: 0,
|
||||||
|
value: 946684800
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
property: 'initialRatedDate',
|
property: 'initialRatedDate',
|
||||||
value: 12345
|
default: 0,
|
||||||
|
value: 946684800
|
||||||
|
},
|
||||||
|
{
|
||||||
|
property: 'agentId',
|
||||||
|
default: 0,
|
||||||
|
value: 12345678
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
property: 'agentEntityId',
|
property: 'agentEntityId',
|
||||||
value: 12434300
|
default: 0,
|
||||||
|
value: 12345678
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
property: 'agentName',
|
||||||
|
default: '',
|
||||||
|
value: 'name'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
property: 'imported',
|
||||||
|
default: false,
|
||||||
|
value: true,
|
||||||
|
accessor: 'is'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
property: 'bound',
|
||||||
|
default: false,
|
||||||
|
value: true,
|
||||||
|
accessor: 'is'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
property: 'currentStepId',
|
||||||
|
default: 1,
|
||||||
|
value: 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
property: 'topVisitedStepId',
|
||||||
|
default: 1,
|
||||||
|
value: 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
property: 'topSavedStepId',
|
||||||
|
value: 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
property: 'error',
|
||||||
|
default: '',
|
||||||
|
value: 'ERROR'
|
||||||
|
}
|
||||||
|
|
||||||
].forEach( testCase =>
|
].forEach( testCase =>
|
||||||
{
|
{
|
||||||
const quote = BaseQuote( 123, {} );
|
const quote = BaseQuote( 123, {} );
|
||||||
const property = testCase.property;
|
const property = testCase.property;
|
||||||
const title_cased = property.charAt( 0 ).toUpperCase() + property.slice( 1 );
|
const title_cased = property.charAt( 0 ).toUpperCase() + property.slice( 1 );
|
||||||
const setter = 'set' + title_cased;
|
const setter = ( testCase.mutator || 'set' ) + title_cased;
|
||||||
const getter = 'get' + title_cased;
|
const getter = ( testCase.accessor || 'get' ) + title_cased;
|
||||||
|
|
||||||
it( property + ' can be mutated and accessed', () =>
|
it( property + ' can be mutated and accessed', () =>
|
||||||
{
|
{
|
||||||
expect( quote[getter].call( null ) ).to.be.undefined;
|
expect( quote[ getter ].call( quote ) ).to.equal( testCase.default );
|
||||||
quote[setter].call( null, testCase.value );
|
quote[ setter ].call( quote, testCase.value );
|
||||||
expect( quote[getter].call( null ) ).to.equal( testCase.value );
|
expect( quote[ getter ].call( quote ) ).to.equal( testCase.value );
|
||||||
} );
|
} );
|
||||||
} );
|
} );
|
||||||
} );
|
} );
|
||||||
|
|
||||||
|
describe( 'locking mechanisms', () =>
|
||||||
|
{
|
||||||
|
[
|
||||||
|
{
|
||||||
|
description: 'default values',
|
||||||
|
reason: '',
|
||||||
|
step: 0,
|
||||||
|
bound: false,
|
||||||
|
imported: false,
|
||||||
|
locks: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: 'quote with a reason',
|
||||||
|
reason: 'reason',
|
||||||
|
step: 0,
|
||||||
|
bound: false,
|
||||||
|
imported: false,
|
||||||
|
locks: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: 'quote with a lock on step #2',
|
||||||
|
reason: '',
|
||||||
|
step: 2,
|
||||||
|
bound: false,
|
||||||
|
imported: false,
|
||||||
|
locks: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: 'quote with a reason and a lock on step #2',
|
||||||
|
reason: 'reason',
|
||||||
|
step: 2,
|
||||||
|
bound: false,
|
||||||
|
imported: false,
|
||||||
|
locks: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: 'bound quote',
|
||||||
|
reason: { given: '', expected: messages.bound },
|
||||||
|
step: 0,
|
||||||
|
bound: true,
|
||||||
|
imported: false,
|
||||||
|
locks: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: 'imported quote',
|
||||||
|
reason: '',
|
||||||
|
step: 0,
|
||||||
|
bound: false,
|
||||||
|
imported: true,
|
||||||
|
locks: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: 'bound and imported quote',
|
||||||
|
reason: { given: '', expected: messages.bound },
|
||||||
|
step: 0,
|
||||||
|
bound: true,
|
||||||
|
imported: true,
|
||||||
|
locks: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: 'bound quote with a lock on step #2',
|
||||||
|
reason: { given: '', expected: messages.bound },
|
||||||
|
step: { given: 2, expected: 0 },
|
||||||
|
bound: true,
|
||||||
|
imported: false,
|
||||||
|
locks: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: 'imported quote with a lock on step #2',
|
||||||
|
reason: '',
|
||||||
|
step: 2,
|
||||||
|
bound: false,
|
||||||
|
imported: true,
|
||||||
|
locks: false
|
||||||
|
}
|
||||||
|
|
||||||
|
].forEach( testCase =>
|
||||||
|
{
|
||||||
|
const quote = BaseQuote( 123, {} );
|
||||||
|
const description = 'Locking is correct for ' + testCase.description;
|
||||||
|
const bound = !!testCase.bound;
|
||||||
|
const imported = !!testCase.imported;
|
||||||
|
const locks = !!testCase.locks;
|
||||||
|
|
||||||
|
const givenReason = ( testCase.reason.given !== undefined ) ?
|
||||||
|
'' + testCase.reason.given :
|
||||||
|
'' + testCase.reason;
|
||||||
|
const expectedReason = ( testCase.reason.expected !== undefined ) ?
|
||||||
|
'' + testCase.reason.expected :
|
||||||
|
'' + testCase.reason;
|
||||||
|
|
||||||
|
const givenStep = ( testCase.step.given !== undefined ) ?
|
||||||
|
+testCase.step.given :
|
||||||
|
+testCase.step;
|
||||||
|
const expectedStep = ( testCase.step.expected !== undefined ) ?
|
||||||
|
+testCase.step.expected :
|
||||||
|
+testCase.step;
|
||||||
|
|
||||||
|
it( description, () =>
|
||||||
|
{
|
||||||
|
expect( quote.getExplicitLockReason() ).to.equal( '' );
|
||||||
|
expect( quote.getExplicitLockStep() ).to.equal( 0 );
|
||||||
|
|
||||||
|
quote.setBound( bound )
|
||||||
|
.setImported( imported )
|
||||||
|
.setExplicitLock( givenReason, givenStep );
|
||||||
|
|
||||||
|
expect( quote.getExplicitLockReason() ).to.equal( expectedReason );
|
||||||
|
expect( quote.getExplicitLockStep() ).to.equal( expectedStep );
|
||||||
|
expect( quote.isLocked() ).to.equal( locks );
|
||||||
|
|
||||||
|
quote.clearExplicitLock();
|
||||||
|
expect( quote.getExplicitLockReason() ).to.equal( bound ? messages.bound : '' );
|
||||||
|
expect( quote.getExplicitLockStep() ).to.equal( 0 );
|
||||||
|
} );
|
||||||
|
} );
|
||||||
|
} );
|
||||||
|
|
||||||
|
describe( 'quote expiration', () =>
|
||||||
|
{
|
||||||
|
[
|
||||||
|
{
|
||||||
|
description: 'default values',
|
||||||
|
currentDate: 0,
|
||||||
|
expired: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: 'quote immediately after start',
|
||||||
|
lockTimeout:
|
||||||
|
{
|
||||||
|
preRateExpiration: 90,
|
||||||
|
postRateExpiration: 30
|
||||||
|
},
|
||||||
|
startDate: 86400000,
|
||||||
|
expirationDate: 7862400000,
|
||||||
|
currentDate: 86400000,
|
||||||
|
expired: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: 'quote immediately after rate',
|
||||||
|
lockTimeout:
|
||||||
|
{
|
||||||
|
preRateExpiration: 90,
|
||||||
|
postRateExpiration: 30
|
||||||
|
},
|
||||||
|
startDate: 86400000,
|
||||||
|
initialRatedDate: 172800000,
|
||||||
|
expirationDate: 2764800000,
|
||||||
|
currentDate: 172800000,
|
||||||
|
expired: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: 'quote 31 days after rate',
|
||||||
|
lockTimeout:
|
||||||
|
{
|
||||||
|
preRateExpiration: 90,
|
||||||
|
postRateExpiration: 30
|
||||||
|
},
|
||||||
|
startDate: 86400,
|
||||||
|
initialRatedDate: 172800000,
|
||||||
|
expirationDate: 2764800000,
|
||||||
|
currentDate: 2851200000,
|
||||||
|
expired: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: 'quote 31 days after rate (with grace period)',
|
||||||
|
lockTimeout:
|
||||||
|
{
|
||||||
|
preRateExpiration: 90,
|
||||||
|
preRateGracePeriod: 15,
|
||||||
|
postRateExpiration: 30,
|
||||||
|
postRateGracePeriod: 5
|
||||||
|
},
|
||||||
|
startDate: 86400,
|
||||||
|
initialRatedDate: 172800000,
|
||||||
|
expirationDate: 2764800000,
|
||||||
|
currentDate: 2851200000,
|
||||||
|
expired: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: 'quote 62 days after start',
|
||||||
|
lockTimeout:
|
||||||
|
{
|
||||||
|
preRateExpiration: 90,
|
||||||
|
postRateExpiration: 30
|
||||||
|
},
|
||||||
|
startDate: 86400000,
|
||||||
|
expirationDate: 7862400000,
|
||||||
|
currentDate: 5356800000,
|
||||||
|
expired: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: 'quote 61 days after rate',
|
||||||
|
lockTimeout:
|
||||||
|
{
|
||||||
|
preRateExpiration: 90,
|
||||||
|
postRateExpiration: 30
|
||||||
|
},
|
||||||
|
startDate: 86400000,
|
||||||
|
initialRatedDate: 172800000,
|
||||||
|
expirationDate: 2764800000,
|
||||||
|
currentDate: 5356800000,
|
||||||
|
expired: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: 'quote 91 days after start',
|
||||||
|
lockTimeout:
|
||||||
|
{
|
||||||
|
preRateExpiration: 90,
|
||||||
|
postRateExpiration: 30
|
||||||
|
},
|
||||||
|
startDate: 86400000,
|
||||||
|
expirationDate: 7862400000,
|
||||||
|
currentDate: 7948800000,
|
||||||
|
expired: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: 'quote 91 days after start (with grace period)',
|
||||||
|
lockTimeout:
|
||||||
|
{
|
||||||
|
preRateExpiration: 90,
|
||||||
|
preRateGracePeriod: 15,
|
||||||
|
postRateExpiration: 30,
|
||||||
|
postRateGracePeriod: 5
|
||||||
|
},
|
||||||
|
startDate: 86400000,
|
||||||
|
expirationDate: 7862400000,
|
||||||
|
currentDate: 7948800000,
|
||||||
|
expired: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: 'quote 121 days after start',
|
||||||
|
lockTimeout:
|
||||||
|
{
|
||||||
|
preRateExpiration: 90,
|
||||||
|
postRateExpiration: 30
|
||||||
|
},
|
||||||
|
startDate: 86400000,
|
||||||
|
expirationDate: 7862400000,
|
||||||
|
currentDate: 10540800000,
|
||||||
|
expired: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: 'quote 120 days after rate',
|
||||||
|
lockTimeout:
|
||||||
|
{
|
||||||
|
preRateExpiration: 90,
|
||||||
|
postRateExpiration: 30
|
||||||
|
},
|
||||||
|
startDate: 86400000,
|
||||||
|
initialRatedDate: 172800000,
|
||||||
|
expirationDate: 2764800000,
|
||||||
|
currentDate: 10540800000,
|
||||||
|
expired: true
|
||||||
|
}
|
||||||
|
|
||||||
|
].forEach( testCase =>
|
||||||
|
{
|
||||||
|
const quote = BaseQuote( 123, {} );
|
||||||
|
const description = "Expiration is correct for " + testCase.description;
|
||||||
|
const start_date = testCase.startDate;
|
||||||
|
const initial_rated_date = testCase.initialRatedDate;
|
||||||
|
const current_date = testCase.currentDate;
|
||||||
|
const expiration_date = testCase.expirationDate;
|
||||||
|
const expired = testCase.expired;
|
||||||
|
|
||||||
|
quote.setProgram( createStubProgram( testCase.lockTimeout ) );
|
||||||
|
|
||||||
|
it( description, () =>
|
||||||
|
{
|
||||||
|
if ( start_date !== undefined )
|
||||||
|
{
|
||||||
|
quote.setStartDate( start_date );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( initial_rated_date !== undefined )
|
||||||
|
{
|
||||||
|
quote.setInitialRatedDate( initial_rated_date );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( expiration_date !== undefined )
|
||||||
|
{
|
||||||
|
expect( quote.getExpirationDate() ).to.equal( +expiration_date );
|
||||||
|
}
|
||||||
|
|
||||||
|
expect( quote.hasExpired( new Date( current_date ) ) ).to.equal( !!expired );
|
||||||
|
} );
|
||||||
|
} );
|
||||||
|
} );
|
||||||
|
} );
|
||||||
|
|
||||||
|
function createStubProgram( lockTimeout )
|
||||||
|
{
|
||||||
|
let stubProgram = Util.stubProgram( Program )();
|
||||||
|
stubProgram.lockTimeout = lockTimeout || {};
|
||||||
|
return stubProgram;
|
||||||
|
}
|
|
@ -0,0 +1,125 @@
|
||||||
|
/**
|
||||||
|
* Tests ServerSideQuote
|
||||||
|
*
|
||||||
|
* Copyright (C) 2017, 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.quote.ServerSideQuote;
|
||||||
|
|
||||||
|
describe( 'ServerSideQuote', () =>
|
||||||
|
{
|
||||||
|
describe( 'accessors & mutators', () =>
|
||||||
|
{
|
||||||
|
[
|
||||||
|
{
|
||||||
|
property: 'startDate',
|
||||||
|
default: 0,
|
||||||
|
value: 946684800
|
||||||
|
},
|
||||||
|
{
|
||||||
|
property: 'initialRatedDate',
|
||||||
|
default: 0,
|
||||||
|
value: 946684800
|
||||||
|
},
|
||||||
|
{
|
||||||
|
property: 'agentId',
|
||||||
|
default: 0,
|
||||||
|
value: 12345678
|
||||||
|
},
|
||||||
|
{
|
||||||
|
property: 'agentEntityId',
|
||||||
|
default: 0,
|
||||||
|
value: 12345678
|
||||||
|
},
|
||||||
|
{
|
||||||
|
property: 'agentName',
|
||||||
|
default: '',
|
||||||
|
value: 'name'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
property: 'imported',
|
||||||
|
default: false,
|
||||||
|
value: true,
|
||||||
|
accessor: 'is'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
property: 'bound',
|
||||||
|
default: false,
|
||||||
|
value: true,
|
||||||
|
accessor: 'is'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
property: 'currentStepId',
|
||||||
|
default: 1,
|
||||||
|
value: 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
property: 'topVisitedStepId',
|
||||||
|
default: 1,
|
||||||
|
value: 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
property: 'topSavedStepId',
|
||||||
|
value: 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
property: 'error',
|
||||||
|
default: '',
|
||||||
|
value: 'ERROR'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
property: 'programVersion',
|
||||||
|
default: '',
|
||||||
|
value: '1.0.0'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
property: 'creditScoreRef',
|
||||||
|
default: 0,
|
||||||
|
value: 800
|
||||||
|
},
|
||||||
|
{
|
||||||
|
property: 'lastPremiumDate',
|
||||||
|
default: 0,
|
||||||
|
value: 946684800
|
||||||
|
},
|
||||||
|
{
|
||||||
|
property: 'ratedDate',
|
||||||
|
default: 0,
|
||||||
|
value: 946684800
|
||||||
|
}
|
||||||
|
|
||||||
|
].forEach( testCase =>
|
||||||
|
{
|
||||||
|
const quote = Sut( 123, {} );
|
||||||
|
const property = testCase.property;
|
||||||
|
const title_cased = property.charAt( 0 ).toUpperCase() + property.slice( 1 );
|
||||||
|
const setter = ( testCase.mutator || 'set' ) + title_cased;
|
||||||
|
const getter = ( testCase.accessor || 'get' ) + title_cased;
|
||||||
|
|
||||||
|
it( property + ' can be mutated and accessed', () =>
|
||||||
|
{
|
||||||
|
expect( quote[getter].call( quote ) ).to.equal( testCase.default );
|
||||||
|
quote[setter].call( quote, testCase.value );
|
||||||
|
expect( quote[getter].call( quote ) ).to.equal( testCase.value );
|
||||||
|
} );
|
||||||
|
} );
|
||||||
|
} );
|
||||||
|
} );
|
Loading…
Reference in New Issue