DataValidator, ValidStateMonitor: Add #clearFailures argument
This allows clearing only the specified failures. * src/validate/ValidStateMonitor.js (clearFailures): Add `fields' argument. Make method more concise. (_fixFailure): Handle clearing `_failures' record. * src/validate/DataValidator.js (clearFailures): Add `fields' argument. * test/validate/ValidStateMonitorTest.js: Add test. * test/validate/DataValidatorTest.js: Add test.master
parent
e7700e8b69
commit
ed21707920
|
@ -159,13 +159,21 @@ module.exports = Class( 'DataValidator',
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clear all recorded failures
|
* Clear specified failures, or otherwise all recorded failures
|
||||||
|
*
|
||||||
|
* `fields` must be a key-value map with the field name as the key and
|
||||||
|
* an array of indexes as the value. Any field in `fields` that has no
|
||||||
|
* failure is ignored.
|
||||||
|
*
|
||||||
|
* See `ValidStateMonitor#clearFailures` for more information.
|
||||||
|
*
|
||||||
|
* @param {Object} fields key-value names of fields/indexes to clear
|
||||||
*
|
*
|
||||||
* @return {DataValidator} self
|
* @return {DataValidator} self
|
||||||
*/
|
*/
|
||||||
'public clearFailures'()
|
'public clearFailures'( failures )
|
||||||
{
|
{
|
||||||
this._field_monitor.clearFailures();
|
this._field_monitor.clearFailures( failures );
|
||||||
return this;
|
return this;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -263,7 +263,6 @@ module.exports = Class( 'ValidStateMonitor' )
|
||||||
// looks like it has been resolved
|
// looks like it has been resolved
|
||||||
this._fixFailure( fixed, name, fail_i, result );
|
this._fixFailure( fixed, name, fail_i, result );
|
||||||
|
|
||||||
delete past_fail[ fail_i ];
|
|
||||||
return true;
|
return true;
|
||||||
} );
|
} );
|
||||||
} ) ).then( fixes => fixes.some( fix => fix === true ) );
|
} ) ).then( fixes => fixes.some( fix => fix === true ) );
|
||||||
|
@ -328,48 +327,58 @@ module.exports = Class( 'ValidStateMonitor' )
|
||||||
'private _fixFailure'( fixed, name, index, value )
|
'private _fixFailure'( fixed, name, index, value )
|
||||||
{
|
{
|
||||||
( fixed[ name ] = fixed[ name ] || [] )[ index ] = value;
|
( fixed[ name ] = fixed[ name ] || [] )[ index ] = value;
|
||||||
|
|
||||||
|
// caller is expected to have ensured that this exists
|
||||||
|
delete this._failures[ name ][ index ];
|
||||||
|
|
||||||
return fixed;
|
return fixed;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clear all recorded failures
|
* Clear specified failures, or otherwise all recorded failures
|
||||||
*
|
*
|
||||||
* For each recorded failure, a `fix` even is emitted. All failure
|
* `fields` must be a key-value map with the field name as the key and
|
||||||
* records are then cleared.
|
* an array of indexes as the value. Any field in `fields` that has no
|
||||||
|
* failure is ignored.
|
||||||
|
*
|
||||||
|
* For each specified failure, a `fix` event is emitted. If no failures
|
||||||
|
* are specified by `fields`, all recorded failures are marked as
|
||||||
|
* fixed. If a field in `fields` is not known, it is ignored.
|
||||||
*
|
*
|
||||||
* Normally the resulting fix object contains the values that triggered
|
* Normally the resulting fix object contains the values that triggered
|
||||||
* the fix. Instead, each fixed index will contain `undefined`.
|
* the fix. Instead, each fixed index will contain `null`.
|
||||||
*
|
*
|
||||||
* This process is synchronous, and only a single `fix` event is emitted
|
* This process is synchronous, and only a single `fix` event is emitted
|
||||||
* after all failures have been cleared.
|
* after all failures have been cleared.
|
||||||
*
|
*
|
||||||
|
* @param {Object} fields key-value names of fields/indexes to clear
|
||||||
|
*
|
||||||
* @return {ValidStateMonitor} self
|
* @return {ValidStateMonitor} self
|
||||||
*/
|
*/
|
||||||
'public clearFailures'()
|
'public clearFailures'( fields )
|
||||||
{
|
{
|
||||||
|
const failures = this._failures;
|
||||||
|
|
||||||
let fixed = {};
|
let fixed = {};
|
||||||
|
|
||||||
for ( let name in this._failures )
|
const isRequestedIndex = ( fields )
|
||||||
{
|
? field => ( fields[ field.getName() ] || [] ).indexOf(
|
||||||
const failure = this._failures[ name ];
|
field.getIndex()
|
||||||
|
) !== -1
|
||||||
|
: () => true;
|
||||||
|
|
||||||
for ( let cause_i in failure )
|
Object.keys( failures )
|
||||||
{
|
.reduce(
|
||||||
const cause = failure[ cause_i ];
|
( all_fields, name ) => all_fields.concat(
|
||||||
|
failures[ name ].map( cause => cause.getField() )
|
||||||
for ( let cause_i in cause )
|
),
|
||||||
{
|
[]
|
||||||
let fail_i = cause.getField().getIndex();
|
)
|
||||||
|
.filter( isRequestedIndex )
|
||||||
this._fixFailure( fixed, name, fail_i, undefined );
|
.forEach( field => this._fixFailure(
|
||||||
}
|
fixed, field.getName(), field.getIndex(), null
|
||||||
}
|
) );
|
||||||
}
|
|
||||||
|
|
||||||
// clear _before_ emitting the fixes (listeners might trigger
|
|
||||||
// additional failures, for example, or call `#hasFailures`)
|
|
||||||
this._failures = {};
|
|
||||||
|
|
||||||
this.emit( 'fix', fixed );
|
this.emit( 'fix', fixed );
|
||||||
|
|
||||||
|
|
|
@ -217,7 +217,7 @@ describe( 'DataValidator', () =>
|
||||||
|
|
||||||
describe( '#clearFailures', () =>
|
describe( '#clearFailures', () =>
|
||||||
{
|
{
|
||||||
it( 'marks all failures as fixed', () =>
|
it( 'proxies to validator', () =>
|
||||||
{
|
{
|
||||||
const bvalidator = createMockBucketValidator();
|
const bvalidator = createMockBucketValidator();
|
||||||
const vmonitor = ValidStateMonitor();
|
const vmonitor = ValidStateMonitor();
|
||||||
|
@ -229,9 +229,14 @@ describe( 'DataValidator', () =>
|
||||||
bvalidator, vmonitor, dep_factory, createStubStore()
|
bvalidator, vmonitor, dep_factory, createStubStore()
|
||||||
);
|
);
|
||||||
|
|
||||||
mock_vmonitor.expects( 'clearFailures' ).once();
|
const failures = [ 'foo', 'bar' ];
|
||||||
|
|
||||||
expect( sut.clearFailures() )
|
mock_vmonitor
|
||||||
|
.expects( 'clearFailures' )
|
||||||
|
.once()
|
||||||
|
.withExactArgs( failures );
|
||||||
|
|
||||||
|
expect( sut.clearFailures( failures ) )
|
||||||
.to.equal( sut );
|
.to.equal( sut );
|
||||||
|
|
||||||
mock_vmonitor.verify();
|
mock_vmonitor.verify();
|
||||||
|
|
|
@ -596,7 +596,7 @@ describe( 'ValidStateMonitor', function()
|
||||||
|
|
||||||
describe( '#clearFailures', () =>
|
describe( '#clearFailures', () =>
|
||||||
{
|
{
|
||||||
it( 'clears all failures', () =>
|
it( 'clears all failures when provided no arguments', () =>
|
||||||
{
|
{
|
||||||
return new Promise( ( accept, reject ) =>
|
return new Promise( ( accept, reject ) =>
|
||||||
{
|
{
|
||||||
|
@ -608,7 +608,7 @@ describe( 'ValidStateMonitor', function()
|
||||||
.on( 'fix', fixed =>
|
.on( 'fix', fixed =>
|
||||||
{
|
{
|
||||||
expect( fixed )
|
expect( fixed )
|
||||||
.to.deep.equal( { foo: [ undefined ] } );
|
.to.deep.equal( { foo: [ null ] } );
|
||||||
|
|
||||||
expect( sut.hasFailures() ).to.be.false;
|
expect( sut.hasFailures() ).to.be.false;
|
||||||
|
|
||||||
|
@ -620,6 +620,52 @@ describe( 'ValidStateMonitor', function()
|
||||||
.catch( e => reject( e ) );
|
.catch( e => reject( e ) );
|
||||||
} );
|
} );
|
||||||
} );
|
} );
|
||||||
|
|
||||||
|
|
||||||
|
it( 'clears only provided failures when provided array argument', () =>
|
||||||
|
{
|
||||||
|
return new Promise( ( accept, reject ) =>
|
||||||
|
{
|
||||||
|
mkstore( {} ).then( empty =>
|
||||||
|
{
|
||||||
|
const sut = Sut();
|
||||||
|
|
||||||
|
return sut
|
||||||
|
.on( 'fix', fixed =>
|
||||||
|
{
|
||||||
|
debugger;
|
||||||
|
// `bar' not cleared
|
||||||
|
expect( fixed )
|
||||||
|
.to.deep.equal( {
|
||||||
|
foo: [ null ],
|
||||||
|
baz: [ , null ],
|
||||||
|
} );
|
||||||
|
|
||||||
|
// still has `bar'
|
||||||
|
expect( sut.hasFailures() ).to.be.true;
|
||||||
|
|
||||||
|
accept( true );
|
||||||
|
} )
|
||||||
|
.update( empty, {
|
||||||
|
foo: mkfail( 'foo', [ 'bar1', 'bar2' ] ),
|
||||||
|
bar: mkfail( 'bar', [ 'baz' ] ),
|
||||||
|
baz: mkfail( 'baz', [ 'quux', 'quuux' ] ),
|
||||||
|
} )
|
||||||
|
.then( sut => sut.clearFailures( {
|
||||||
|
foo: [ 0 ],
|
||||||
|
baz: [ 1 ],
|
||||||
|
} ) );
|
||||||
|
} )
|
||||||
|
.catch( e => reject( e ) );
|
||||||
|
} );
|
||||||
|
} );
|
||||||
|
|
||||||
|
|
||||||
|
it( 'does not error on non-existent failure', () =>
|
||||||
|
{
|
||||||
|
expect( () => Sut().clearFailures( [ 'foo', 'baz' ] ) )
|
||||||
|
.to.not.throw( Error );
|
||||||
|
} );
|
||||||
} );
|
} );
|
||||||
} );
|
} );
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue