@@ -6,123 +6,145 @@ import { NativeAttributeValue } from "./models";
66
77describe ( "convertToAttr" , ( ) => {
88 describe ( "null" , ( ) => {
9- it ( `returns for null` , ( ) => {
10- expect ( convertToAttr ( null ) ) . toEqual ( { NULL : true } ) ;
9+ [ true , false ] . forEach ( ( convertClassInstanceToMap ) => {
10+ it ( `returns for null` , ( ) => {
11+ expect ( convertToAttr ( null , { convertClassInstanceToMap } ) ) . toEqual ( { NULL : true } ) ;
12+ } ) ;
1113 } ) ;
1214 } ) ;
1315
1416 describe ( "boolean" , ( ) => {
15- [ true , false ] . forEach ( ( bool ) => {
16- it ( `returns for boolean: ${ bool } ` , ( ) => {
17- expect ( convertToAttr ( bool ) ) . toEqual ( { BOOL : bool } ) ;
17+ [ true , false ] . forEach ( ( convertClassInstanceToMap ) => {
18+ [ true , false ] . forEach ( ( isClassInstance ) => {
19+ [ true , false ] . forEach ( ( boolValue ) => {
20+ const bool = isClassInstance ? new Boolean ( boolValue ) : boolValue ;
21+ it ( `returns for boolean: ${ bool } ` , ( ) => {
22+ expect ( convertToAttr ( bool , { convertClassInstanceToMap } ) ) . toEqual ( { BOOL : bool . valueOf ( ) } ) ;
23+ } ) ;
24+ } ) ;
1825 } ) ;
1926 } ) ;
2027 } ) ;
2128
2229 describe ( "number" , ( ) => {
23- [ 1 , Number . MAX_SAFE_INTEGER , Number . MIN_SAFE_INTEGER ] . forEach ( ( num ) => {
24- it ( `returns for number (integer): ${ num } ` , ( ) => {
25- expect ( convertToAttr ( num ) ) . toEqual ( { N : num . toString ( ) } ) ;
26- } ) ;
27- } ) ;
28-
29- [ 1.01 , Math . PI , Math . E , Number . MIN_VALUE , Number . EPSILON ] . forEach ( ( num ) => {
30- it ( `returns for number (floating point): ${ num } ` , ( ) => {
31- expect ( convertToAttr ( num ) ) . toEqual ( { N : num . toString ( ) } ) ;
32- } ) ;
33- } ) ;
34-
35- [ Number . NaN , Number . POSITIVE_INFINITY , Number . NEGATIVE_INFINITY ] . forEach ( ( num ) => {
36- it ( `throws for number (special numeric value): ${ num } ` , ( ) => {
37- expect ( ( ) => {
38- convertToAttr ( num ) ;
39- } ) . toThrowError ( `Special numeric value ${ num } is not allowed` ) ;
40- } ) ;
41- } ) ;
42-
43- [ Number . MAX_SAFE_INTEGER + 1 , Number . MAX_VALUE ] . forEach ( ( num ) => {
44- it ( `throws for number greater than Number.MAX_SAFE_INTEGER: ${ num } ` , ( ) => {
45- const errorPrefix = `Number ${ num } is greater than Number.MAX_SAFE_INTEGER.` ;
46-
47- expect ( ( ) => {
48- convertToAttr ( num ) ;
49- } ) . toThrowError ( `${ errorPrefix } Use BigInt.` ) ;
30+ [ true , false ] . forEach ( ( convertClassInstanceToMap ) => {
31+ [ true , false ] . forEach ( ( isClassInstance ) => {
32+ [ 1 , Number . MAX_SAFE_INTEGER , Number . MIN_SAFE_INTEGER ] . forEach ( ( numValue ) => {
33+ const num = isClassInstance ? new Number ( numValue ) : numValue ;
34+ it ( `returns for number (integer): ${ num } ` , ( ) => {
35+ expect ( convertToAttr ( num , { convertClassInstanceToMap } ) ) . toEqual ( { N : num . toString ( ) } ) ;
36+ } ) ;
37+ } ) ;
5038
51- const BigIntConstructor = BigInt ;
52- ( BigInt as any ) = undefined ;
53- expect ( ( ) => {
54- convertToAttr ( num ) ;
55- } ) . toThrowError ( `${ errorPrefix } Pass string value instead.` ) ;
56- BigInt = BigIntConstructor ;
57- } ) ;
58- } ) ;
39+ [ 1.01 , Math . PI , Math . E , Number . MIN_VALUE , Number . EPSILON ] . forEach ( ( numValue ) => {
40+ const num = isClassInstance ? new Number ( numValue ) : numValue ;
41+ it ( `returns for number (floating point): ${ num } ` , ( ) => {
42+ expect ( convertToAttr ( num , { convertClassInstanceToMap } ) ) . toEqual ( { N : num . toString ( ) } ) ;
43+ } ) ;
44+ } ) ;
5945
60- [ Number . MIN_SAFE_INTEGER - 1 ] . forEach ( ( num ) => {
61- it ( `throws for number lesser than Number.MIN_SAFE_INTEGER: ${ num } ` , ( ) => {
62- const errorPrefix = `Number ${ num } is lesser than Number.MIN_SAFE_INTEGER.` ;
46+ [ Number . NaN , Number . POSITIVE_INFINITY , Number . NEGATIVE_INFINITY ] . forEach ( ( numValue ) => {
47+ const num = isClassInstance ? new Number ( numValue ) : numValue ;
48+ it ( `throws for number (special numeric value): ${ num } ` , ( ) => {
49+ expect ( ( ) => {
50+ convertToAttr ( num , { convertClassInstanceToMap } ) ;
51+ } ) . toThrowError ( `Special numeric value ${ num . toString ( ) } is not allowed` ) ;
52+ } ) ;
53+ } ) ;
6354
64- expect ( ( ) => {
65- convertToAttr ( num ) ;
66- } ) . toThrowError ( `${ errorPrefix } Use BigInt.` ) ;
55+ [ Number . MAX_SAFE_INTEGER + 1 , Number . MAX_VALUE ] . forEach ( ( numValue ) => {
56+ const num = isClassInstance ? new Number ( numValue ) : numValue ;
57+ it ( `throws for number greater than Number.MAX_SAFE_INTEGER: ${ num } ` , ( ) => {
58+ const errorPrefix = `Number ${ num . toString ( ) } is greater than Number.MAX_SAFE_INTEGER.` ;
59+
60+ expect ( ( ) => {
61+ convertToAttr ( num , { convertClassInstanceToMap } ) ;
62+ } ) . toThrowError ( `${ errorPrefix } Use BigInt.` ) ;
63+
64+ const BigIntConstructor = BigInt ;
65+ ( BigInt as any ) = undefined ;
66+ expect ( ( ) => {
67+ convertToAttr ( num , { convertClassInstanceToMap } ) ;
68+ } ) . toThrowError ( `${ errorPrefix } Pass string value instead.` ) ;
69+ BigInt = BigIntConstructor ;
70+ } ) ;
71+ } ) ;
6772
68- const BigIntConstructor = BigInt ;
69- ( BigInt as any ) = undefined ;
70- expect ( ( ) => {
71- convertToAttr ( num ) ;
72- } ) . toThrowError ( `${ errorPrefix } Pass string value instead.` ) ;
73- BigInt = BigIntConstructor ;
73+ [ Number . MIN_SAFE_INTEGER - 1 ] . forEach ( ( numValue ) => {
74+ const num = isClassInstance ? new Number ( numValue ) : numValue ;
75+ it ( `throws for number lesser than Number.MIN_SAFE_INTEGER: ${ num } ` , ( ) => {
76+ const errorPrefix = `Number ${ num . toString ( ) } is lesser than Number.MIN_SAFE_INTEGER.` ;
77+
78+ expect ( ( ) => {
79+ convertToAttr ( num , { convertClassInstanceToMap } ) ;
80+ } ) . toThrowError ( `${ errorPrefix } Use BigInt.` ) ;
81+
82+ const BigIntConstructor = BigInt ;
83+ ( BigInt as any ) = undefined ;
84+ expect ( ( ) => {
85+ convertToAttr ( num , { convertClassInstanceToMap } ) ;
86+ } ) . toThrowError ( `${ errorPrefix } Pass string value instead.` ) ;
87+ BigInt = BigIntConstructor ;
88+ } ) ;
89+ } ) ;
7490 } ) ;
7591 } ) ;
7692 } ) ;
7793
7894 describe ( "bigint" , ( ) => {
79- const maxSafe = BigInt ( Number . MAX_SAFE_INTEGER ) ;
80- [
81- // @ts -expect-error BigInt literals are not available when targeting lower than ES2020.
82- 1n ,
83- // @ts -expect-error BigInt literals are not available when targeting lower than ES2020.
84- maxSafe * 2n ,
85- // @ts -expect-error BigInt literals are not available when targeting lower than ES2020.
86- maxSafe * - 2n ,
87- BigInt ( Number . MAX_VALUE ) ,
88- BigInt ( "0x1fffffffffffff" ) ,
89- BigInt ( "0b11111111111111111111111111111111111111111111111111111" ) ,
90- ] . forEach ( ( num ) => {
91- it ( `returns for bigint: ${ num } ` , ( ) => {
92- expect ( convertToAttr ( num ) ) . toEqual ( { N : num . toString ( ) } ) ;
95+ [ true , false ] . forEach ( ( convertClassInstanceToMap ) => {
96+ const maxSafe = BigInt ( Number . MAX_SAFE_INTEGER ) ;
97+ [
98+ // @ts -expect-error BigInt literals are not available when targeting lower than ES2020.
99+ 1n ,
100+ // @ts -expect-error BigInt literals are not available when targeting lower than ES2020.
101+ maxSafe * 2n ,
102+ // @ts -expect-error BigInt literals are not available when targeting lower than ES2020.
103+ maxSafe * - 2n ,
104+ BigInt ( Number . MAX_VALUE ) ,
105+ BigInt ( "0x1fffffffffffff" ) ,
106+ BigInt ( "0b11111111111111111111111111111111111111111111111111111" ) ,
107+ ] . forEach ( ( num ) => {
108+ it ( `returns for bigint: ${ num } ` , ( ) => {
109+ expect ( convertToAttr ( num , { convertClassInstanceToMap } ) ) . toEqual ( { N : num . toString ( ) } ) ;
110+ } ) ;
93111 } ) ;
94112 } ) ;
95113 } ) ;
96114
97115 describe ( "binary" , ( ) => {
98- const buffer = new ArrayBuffer ( 64 ) ;
99- const arr = [ ...Array ( 64 ) . keys ( ) ] ;
100- const addPointOne = ( num : number ) => num + 0.1 ;
101-
102- [
103- buffer ,
104- new Blob ( [ new Uint8Array ( buffer ) ] ) ,
105- Buffer . from ( buffer ) ,
106- new DataView ( buffer ) ,
107- new Int8Array ( arr ) ,
108- new Uint8Array ( arr ) ,
109- new Uint8ClampedArray ( arr ) ,
110- new Int16Array ( arr ) ,
111- new Uint16Array ( arr ) ,
112- new Int32Array ( arr ) ,
113- new Uint32Array ( arr ) ,
114- new Float32Array ( arr . map ( addPointOne ) ) ,
115- new Float64Array ( arr . map ( addPointOne ) ) ,
116- new BigInt64Array ( arr . map ( BigInt ) ) ,
117- new BigUint64Array ( arr . map ( BigInt ) ) ,
118- ] . forEach ( ( data ) => {
119- it ( `returns for binary: ${ data . constructor . name } ` , ( ) => {
120- expect ( convertToAttr ( data ) ) . toEqual ( { B : data } ) ;
116+ [ true , false ] . forEach ( ( convertClassInstanceToMap ) => {
117+ const buffer = new ArrayBuffer ( 64 ) ;
118+ const arr = [ ...Array ( 64 ) . keys ( ) ] ;
119+ const addPointOne = ( num : number ) => num + 0.1 ;
120+
121+ [
122+ buffer ,
123+ new Blob ( [ new Uint8Array ( buffer ) ] ) ,
124+ Buffer . from ( buffer ) ,
125+ new DataView ( buffer ) ,
126+ new Int8Array ( arr ) ,
127+ new Uint8Array ( arr ) ,
128+ new Uint8ClampedArray ( arr ) ,
129+ new Int16Array ( arr ) ,
130+ new Uint16Array ( arr ) ,
131+ new Int32Array ( arr ) ,
132+ new Uint32Array ( arr ) ,
133+ new Float32Array ( arr . map ( addPointOne ) ) ,
134+ new Float64Array ( arr . map ( addPointOne ) ) ,
135+ new BigInt64Array ( arr . map ( BigInt ) ) ,
136+ new BigUint64Array ( arr . map ( BigInt ) ) ,
137+ ] . forEach ( ( data ) => {
138+ it ( `returns for binary: ${ data . constructor . name } ` , ( ) => {
139+ expect ( convertToAttr ( data , { convertClassInstanceToMap } ) ) . toEqual ( { B : data } ) ;
140+ } ) ;
121141 } ) ;
122- } ) ;
123142
124- it ( "returns null for Binary when options.convertEmptyValues=true" , ( ) => {
125- expect ( convertToAttr ( new Uint8Array ( ) , { convertEmptyValues : true } ) ) . toEqual ( { NULL : true } ) ;
143+ it ( "returns null for Binary when options.convertEmptyValues=true" , ( ) => {
144+ expect ( convertToAttr ( new Uint8Array ( ) , { convertClassInstanceToMap, convertEmptyValues : true } ) ) . toEqual ( {
145+ NULL : true ,
146+ } ) ;
147+ } ) ;
126148 } ) ;
127149 } ) ;
128150
@@ -273,7 +295,6 @@ describe("convertToAttr", () => {
273295 describe ( "unallowed set" , ( ) => {
274296 it ( "throws error" , ( ) => {
275297 expect ( ( ) => {
276- // @ts -expect-error Type 'Set<boolean>' is not assignable
277298 convertToAttr ( new Set ( [ true , false ] ) ) ;
278299 } ) . toThrowError ( `Only Number Set (NS), Binary Set (BS) or String Set (SS) are allowed.` ) ;
279300 } ) ;
@@ -362,19 +383,25 @@ describe("convertToAttr", () => {
362383 } ) ;
363384
364385 describe ( "string" , ( ) => {
365- [ "" , "string" , "'single-quote'" , '"double-quote"' ] . forEach ( ( str ) => {
366- it ( `returns for string: ${ str } ` , ( ) => {
367- expect ( convertToAttr ( str ) ) . toEqual ( { S : str } ) ;
368- } ) ;
369- } ) ;
386+ [ true , false ] . forEach ( ( convertClassInstanceToMap ) => {
387+ [ true , false ] . forEach ( ( isClassInstance ) => {
388+ [ "" , "string" , "'single-quote'" , '"double-quote"' ] . forEach ( ( strValue ) => {
389+ const str = isClassInstance ? new String ( strValue ) : strValue ;
390+ it ( `returns for string: ${ str } ` , ( ) => {
391+ expect ( convertToAttr ( str , { convertClassInstanceToMap } ) ) . toEqual ( { S : str . toString ( ) } ) ;
392+ } ) ;
393+ } ) ;
370394
371- it ( "returns null for string when options.convertEmptyValues=true" , ( ) => {
372- expect ( convertToAttr ( "" , { convertEmptyValues : true } ) ) . toEqual ( { NULL : true } ) ;
395+ it ( "returns null for string when options.convertEmptyValues=true" , ( ) => {
396+ const str = isClassInstance ? new String ( "" ) : "" ;
397+ expect ( convertToAttr ( str , { convertClassInstanceToMap, convertEmptyValues : true } ) ) . toEqual ( { NULL : true } ) ;
398+ } ) ;
399+ } ) ;
373400 } ) ;
374401 } ) ;
375402
376403 describe ( `unsupported type` , ( ) => {
377- class FooObj {
404+ class FooClass {
378405 constructor ( private readonly foo : string ) { }
379406 }
380407
@@ -385,13 +412,72 @@ describe("convertToAttr", () => {
385412 } ) ;
386413
387414 // ToDo: Serialize ES6 class objects as string https://github.com/aws/aws-sdk-js-v3/issues/1535
388- [ new Date ( ) , new FooObj ( "foo" ) ] . forEach ( ( data ) => {
415+ [ new Date ( ) , new FooClass ( "foo" ) ] . forEach ( ( data ) => {
389416 it ( `throws for: ${ String ( data ) } ` , ( ) => {
390417 expect ( ( ) => {
391- // @ts -expect-error Argument is not assignable to parameter of type 'NativeAttributeValue'
392418 convertToAttr ( data ) ;
393- } ) . toThrowError ( `Unsupported type passed: ${ String ( data ) } ` ) ;
419+ } ) . toThrowError (
420+ `Unsupported type passed: ${ String (
421+ data
422+ ) } . Pass options.convertClassInstanceToMap=true to marshall typeof object as map attribute.`
423+ ) ;
394424 } ) ;
395425 } ) ;
396426 } ) ;
427+
428+ describe ( "typeof object with options.convertClassInstanceToMap=true" , ( ) => {
429+ it ( "returns map for class" , ( ) => {
430+ class FooClass {
431+ constructor (
432+ private readonly nullAttr : null ,
433+ private readonly boolAttr : boolean ,
434+ private readonly strAttr : string ,
435+ private readonly numAttr : number ,
436+ private readonly bigintAttr : bigint ,
437+ private readonly binaryAttr : Uint8Array ,
438+ private readonly listAttr : any [ ] ,
439+ private readonly mapAttr : { [ key : string ] : any }
440+ ) { }
441+ }
442+ expect (
443+ convertToAttr (
444+ new FooClass (
445+ null ,
446+ true ,
447+ "string" ,
448+ 1 ,
449+ BigInt ( Number . MAX_VALUE ) ,
450+ new Uint8Array ( [ ...Array ( 64 ) . keys ( ) ] ) ,
451+ [ null , 1 , "two" , true ] ,
452+ {
453+ nullKey : null ,
454+ numKey : 1 ,
455+ strKey : "string" ,
456+ boolKey : true ,
457+ }
458+ ) ,
459+ {
460+ convertClassInstanceToMap : true ,
461+ }
462+ )
463+ ) . toEqual ( {
464+ M : {
465+ nullAttr : { NULL : true } ,
466+ boolAttr : { BOOL : true } ,
467+ strAttr : { S : "string" } ,
468+ numAttr : { N : "1" } ,
469+ bigintAttr : { N : BigInt ( Number . MAX_VALUE ) . toString ( ) } ,
470+ binaryAttr : { B : new Uint8Array ( [ ...Array ( 64 ) . keys ( ) ] ) } ,
471+ listAttr : { L : [ { NULL : true } , { N : "1" } , { S : "two" } , { BOOL : true } ] } ,
472+ mapAttr : {
473+ M : { nullKey : { NULL : true } , numKey : { N : "1" } , strKey : { S : "string" } , boolKey : { BOOL : true } } ,
474+ } ,
475+ } ,
476+ } ) ;
477+ } ) ;
478+
479+ it ( "returns empty for Date object" , ( ) => {
480+ expect ( convertToAttr ( new Date ( ) , { convertClassInstanceToMap : true } ) ) . toEqual ( { M : { } } ) ;
481+ } ) ;
482+ } ) ;
397483} ) ;
0 commit comments