@@ -690,52 +690,79 @@ Object.defineProperty(exports, 'hasSmallICU', {
690
690
}
691
691
} ) ;
692
692
693
+ class Comparison {
694
+ constructor ( obj , keys ) {
695
+ for ( const key of keys ) {
696
+ if ( key in obj )
697
+ this [ key ] = obj [ key ] ;
698
+ }
699
+ }
700
+ }
701
+
693
702
// Useful for testing expected internal/error objects
694
703
exports . expectsError = function expectsError ( fn , settings , exact ) {
695
704
if ( typeof fn !== 'function' ) {
696
705
exact = settings ;
697
706
settings = fn ;
698
707
fn = undefined ;
699
708
}
709
+
700
710
function innerFn ( error ) {
701
711
const descriptor = Object . getOwnPropertyDescriptor ( error , 'message' ) ;
702
712
assert . strictEqual ( descriptor . enumerable ,
703
713
false , 'The error message should be non-enumerable' ) ;
714
+
715
+ let innerSettings = settings ;
704
716
if ( 'type' in settings ) {
705
717
const type = settings . type ;
706
718
if ( type !== Error && ! Error . isPrototypeOf ( type ) ) {
707
719
throw new TypeError ( '`settings.type` must inherit from `Error`' ) ;
708
720
}
709
- assert ( error instanceof type ,
710
- `${ error . name } is not instance of ${ type . name } ` ) ;
711
- let typeName = error . constructor . name ;
712
- if ( typeName === 'NodeError' && type . name !== 'NodeError' ) {
713
- typeName = Object . getPrototypeOf ( error . constructor ) . name ;
721
+ let constructor = error . constructor ;
722
+ if ( constructor . name === 'NodeError' && type . name !== 'NodeError' ) {
723
+ constructor = Object . getPrototypeOf ( error . constructor ) ;
714
724
}
715
- assert . strictEqual ( typeName , type . name ) ;
725
+ // Add the `type` to the error to properly compare and visualize it.
726
+ if ( ! ( 'type' in error ) )
727
+ error . type = constructor ;
716
728
}
717
- if ( 'info' in settings ) {
718
- assert . deepStrictEqual ( error . info , settings . info ) ;
719
- }
720
- if ( 'message' in settings ) {
721
- const message = settings . message ;
722
- if ( typeof message === 'string' ) {
723
- assert . strictEqual ( error . message , message ) ;
724
- } else {
725
- assert ( message . test ( error . message ) ,
726
- `${ error . message } does not match ${ message } ` ) ;
727
- }
729
+
730
+ if ( 'message' in settings &&
731
+ typeof settings . message === 'object' &&
732
+ settings . message . test ( error . message ) ) {
733
+ // Make a copy so we are able to modify the settings.
734
+ innerSettings = Object . create (
735
+ settings , Object . getOwnPropertyDescriptors ( settings ) ) ;
736
+ // Visualize the message as identical in case of other errors.
737
+ innerSettings . message = error . message ;
728
738
}
729
739
730
740
// Check all error properties.
731
741
const keys = Object . keys ( settings ) ;
732
742
for ( const key of keys ) {
733
- if ( key === 'message' || key === 'type' || key === 'info' )
734
- continue ;
735
- const actual = error [ key ] ;
736
- const expected = settings [ key ] ;
737
- assert . strictEqual ( actual , expected ,
738
- `${ key } : expected ${ expected } , not ${ actual } ` ) ;
743
+ if ( ! util . isDeepStrictEqual ( error [ key ] , innerSettings [ key ] ) ) {
744
+ // Create placeholder objects to create a nice output.
745
+ const a = new Comparison ( error , keys ) ;
746
+ const b = new Comparison ( innerSettings , keys ) ;
747
+
748
+ const tmpLimit = Error . stackTraceLimit ;
749
+ Error . stackTraceLimit = 0 ;
750
+ const err = new assert . AssertionError ( {
751
+ actual : a ,
752
+ expected : b ,
753
+ operator : 'strictEqual' ,
754
+ stackStartFn : assert . throws
755
+ } ) ;
756
+ Error . stackTraceLimit = tmpLimit ;
757
+
758
+ throw new assert . AssertionError ( {
759
+ actual : error ,
760
+ expected : settings ,
761
+ operator : 'common.expectsError' ,
762
+ message : err . message
763
+ } ) ;
764
+ }
765
+
739
766
}
740
767
return true ;
741
768
}
0 commit comments