Skip to content

Commit 2d9b200

Browse files
authored
test(util-dynamodb): marshall and unmarshall in convertToAttrToNative (#1548)
1 parent 76c0068 commit 2d9b200

File tree

3 files changed

+244
-10
lines changed

3 files changed

+244
-10
lines changed

packages/util-dynamodb/src/convertToAttr.spec.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -136,8 +136,8 @@ describe("convertToAttr", () => {
136136
output: [{ NULL: true }, { BOOL: false }],
137137
},
138138
{
139-
input: [1.01, BigInt(1), "one"],
140-
output: [{ N: "1.01" }, { N: "1" }, { S: "one" }],
139+
input: [1.01, BigInt(9007199254740996), "one"],
140+
output: [{ N: "1.01" }, { N: "9007199254740996" }, { S: "one" }],
141141
},
142142
{
143143
input: [uint8Arr, biguintArr],
@@ -233,8 +233,8 @@ describe("convertToAttr", () => {
233233
output: { nullKey: { NULL: true }, boolKey: { BOOL: false } },
234234
},
235235
{
236-
input: { stringKey: "one", numberKey: 1.01, bigintKey: BigInt(1) },
237-
output: { stringKey: { S: "one" }, numberKey: { N: "1.01" }, bigintKey: { N: "1" } },
236+
input: { stringKey: "one", numberKey: 1.01, bigintKey: BigInt(9007199254740996) },
237+
output: { stringKey: { S: "one" }, numberKey: { N: "1.01" }, bigintKey: { N: "9007199254740996" } },
238238
},
239239
{
240240
input: { uint8ArrKey: uint8Arr, biguintArrKey: biguintArr },
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,234 @@
1+
import { convertToAttr } from "./convertToAttr";
2+
import { convertToNative } from "./convertToNative";
3+
import { NativeAttributeValue } from "./models";
4+
5+
describe("convertToAttrToNative", () => {
6+
describe("null", () => {
7+
it(`returns for null`, () => {
8+
expect(convertToNative(convertToAttr(null))).toEqual(null);
9+
});
10+
});
11+
12+
describe("boolean", () => {
13+
[true, false].forEach((bool) => {
14+
it(`returns for boolean: ${bool}`, () => {
15+
expect(convertToNative(convertToAttr(bool))).toEqual(bool);
16+
});
17+
});
18+
});
19+
20+
describe("number", () => {
21+
const wrapNumbers = true;
22+
23+
[1, Number.MAX_SAFE_INTEGER, Number.MIN_SAFE_INTEGER].forEach((num) => {
24+
it(`returns for number (integer): ${num}`, () => {
25+
expect(convertToNative(convertToAttr(num))).toEqual(num);
26+
});
27+
it(`returns NumberValue for number (integer) with options.wrapNumbers set: ${num}`, () => {
28+
expect(convertToNative(convertToAttr(num), { wrapNumbers })).toEqual({ value: num.toString() });
29+
});
30+
});
31+
32+
[1.01, Math.PI, Math.E, Number.MIN_VALUE, Number.EPSILON].forEach((num) => {
33+
it(`returns for number (floating point): ${num}`, () => {
34+
expect(convertToNative(convertToAttr(num))).toEqual(num);
35+
});
36+
it(`returns NumberValue for number (floating point) with options.wrapNumbers set: ${num}`, () => {
37+
expect(convertToNative(convertToAttr(num), { wrapNumbers })).toEqual({ value: num.toString() });
38+
});
39+
});
40+
});
41+
42+
describe("bigint", () => {
43+
const maxSafe = BigInt(Number.MAX_SAFE_INTEGER);
44+
[
45+
// @ts-expect-error BigInt literals are not available when targeting lower than ES2020.
46+
maxSafe * 2n,
47+
// @ts-expect-error BigInt literals are not available when targeting lower than ES2020.
48+
maxSafe * -2n,
49+
BigInt(Number.MAX_VALUE),
50+
BigInt("0x1fffffffffffffff"),
51+
BigInt("0b111111111111111111111111111111111111111111111111111111"),
52+
].forEach((num) => {
53+
it(`returns for bigint: ${num}`, () => {
54+
expect(convertToNative(convertToAttr(num))).toEqual(num);
55+
});
56+
});
57+
});
58+
59+
describe("binary", () => {
60+
const buffer = new ArrayBuffer(64);
61+
const arr = [...Array(64).keys()];
62+
const addPointOne = (num: number) => num + 0.1;
63+
64+
[
65+
buffer,
66+
new Blob([new Uint8Array(buffer)]),
67+
Buffer.from(buffer),
68+
new DataView(buffer),
69+
new Int8Array(arr),
70+
new Uint8Array(arr),
71+
new Uint8ClampedArray(arr),
72+
new Int16Array(arr),
73+
new Uint16Array(arr),
74+
new Int32Array(arr),
75+
new Uint32Array(arr),
76+
new Float32Array(arr.map(addPointOne)),
77+
new Float64Array(arr.map(addPointOne)),
78+
new BigInt64Array(arr.map(BigInt)),
79+
new BigUint64Array(arr.map(BigInt)),
80+
].forEach((data) => {
81+
it(`returns for binary: ${data.constructor.name}`, () => {
82+
expect(convertToNative(convertToAttr(data))).toEqual(data);
83+
});
84+
});
85+
86+
it("returns null for Binary when options.convertEmptyValues=true", () => {
87+
expect(convertToNative(convertToAttr(new Uint8Array(), { convertEmptyValues: true }))).toEqual(null);
88+
});
89+
});
90+
91+
describe("list", () => {
92+
const arr = [...Array(4).keys()];
93+
const uint8Arr = new Uint32Array(arr);
94+
const biguintArr = new BigUint64Array(arr.map(BigInt));
95+
96+
([
97+
[null, false],
98+
[1.01, BigInt(9007199254740996), "one"],
99+
[uint8Arr, biguintArr],
100+
[
101+
{ nullKey: null, boolKey: false },
102+
{ stringKey: "one", numberKey: 1.01, bigintKey: BigInt(9007199254740996) },
103+
],
104+
[
105+
new Set([1, 2, 3]),
106+
new Set([BigInt(9007199254740996), BigInt(-9007199254740996)]),
107+
new Set([uint8Arr, biguintArr]),
108+
new Set(["one", "two", "three"]),
109+
],
110+
] as NativeAttributeValue[][]).forEach((input) => {
111+
it(`testing list: ${input}`, () => {
112+
expect(convertToNative(convertToAttr(input))).toEqual(input);
113+
});
114+
});
115+
116+
it(`testing list with options.convertEmptyValues=true`, () => {
117+
const input = ["", new Uint8Array(), new Set([])];
118+
expect(convertToNative(convertToAttr(input, { convertEmptyValues: true }))).toEqual([null, null, null]);
119+
});
120+
121+
it(`testing list with options.wrapNumbers=true`, () => {
122+
const input = [1, 1.01, BigInt(9007199254740996)];
123+
expect(convertToNative(convertToAttr(input), { wrapNumbers: true })).toEqual(
124+
input.map((num) => ({ value: num.toString() }))
125+
);
126+
});
127+
});
128+
129+
describe("set", () => {
130+
describe("number set", () => {
131+
const set = new Set([1, 2, 3]);
132+
133+
it("without options.wrapNumbers", () => {
134+
expect(convertToNative(convertToAttr(set))).toEqual(set);
135+
});
136+
137+
it("with options.wrapNumbers=true", () => {
138+
expect(convertToNative(convertToAttr(set), { wrapNumbers: true })).toEqual(
139+
new Set(Array.from(set).map((num) => ({ value: num.toString() })))
140+
);
141+
});
142+
});
143+
144+
describe("bigint set", () => {
145+
// @ts-expect-error BigInt literals are not available when targeting lower than ES2020.
146+
const bigNum = BigInt(Number.MAX_SAFE_INTEGER) + 2n;
147+
const set = new Set([bigNum, -bigNum]);
148+
149+
it("without options.wrapNumbers", () => {
150+
expect(convertToNative(convertToAttr(set))).toEqual(set);
151+
});
152+
153+
it("with options.wrapNumbers=true", () => {
154+
expect(convertToNative(convertToAttr(set), { wrapNumbers: true })).toEqual(
155+
new Set(Array.from(set).map((num) => ({ value: num.toString() })))
156+
);
157+
});
158+
});
159+
160+
it("binary set", () => {
161+
const set = new Set([new ArrayBuffer(4), new ArrayBuffer(8), new ArrayBuffer(16)]);
162+
expect(convertToNative(convertToAttr(set))).toEqual(set);
163+
});
164+
165+
it("string set", () => {
166+
const set = new Set(["one", "two", "three"]);
167+
expect(convertToNative(convertToAttr(set))).toEqual(set);
168+
});
169+
170+
it("returns null for empty set for options.convertEmptyValues=true", () => {
171+
expect(convertToNative(convertToAttr(new Set([]), { convertEmptyValues: true }))).toEqual(null);
172+
});
173+
});
174+
175+
describe("map", () => {
176+
const arr = [...Array(4).keys()];
177+
const uint8Arr = new Uint32Array(arr);
178+
const biguintArr = new BigUint64Array(arr.map(BigInt));
179+
180+
([
181+
{ nullKey: null, boolKey: false },
182+
{ stringKey: "one", numberKey: 1.01, bigintKey: BigInt(9007199254740996) },
183+
{ uint8ArrKey: uint8Arr, biguintArrKey: biguintArr },
184+
{
185+
list1: [null, false],
186+
list2: ["one", 1.01, BigInt(9007199254740996)],
187+
},
188+
{
189+
numberSet: new Set([1, 2, 3]),
190+
bigintSet: new Set([BigInt(9007199254740996), BigInt(-9007199254740996)]),
191+
binarySet: new Set([uint8Arr, biguintArr]),
192+
stringSet: new Set(["one", "two", "three"]),
193+
},
194+
] as { [key: string]: NativeAttributeValue }[]).forEach((input) => {
195+
it(`testing map: ${input}`, () => {
196+
expect(convertToNative(convertToAttr(input))).toEqual(input);
197+
});
198+
});
199+
200+
it(`testing map with options.convertEmptyValues=true`, () => {
201+
const input = { stringKey: "", binaryKey: new Uint8Array(), setKey: new Set([]) };
202+
expect(convertToNative(convertToAttr(input, { convertEmptyValues: true }))).toEqual({
203+
stringKey: null,
204+
binaryKey: null,
205+
setKey: null,
206+
});
207+
});
208+
209+
it(`testing map with options.wrapNumbers=true`, () => {
210+
const input = { numKey: 1, floatNumKey: 1.01, bigintKey: BigInt(9007199254740996) };
211+
expect(convertToNative(convertToAttr(input), { wrapNumbers: true })).toEqual(
212+
Object.entries(input).reduce(
213+
(acc, [key, num]) => ({
214+
...acc,
215+
[key]: { value: num.toString() },
216+
}),
217+
{}
218+
)
219+
);
220+
});
221+
});
222+
223+
describe("string", () => {
224+
["", "string", "'single-quote'", '"double-quote"'].forEach((str) => {
225+
it(`returns for string: ${str}`, () => {
226+
expect(convertToNative(convertToAttr(str))).toEqual(str);
227+
});
228+
});
229+
230+
it("returns null for string when options.convertEmptyValues=true", () => {
231+
expect(convertToNative(convertToAttr("", { convertEmptyValues: true }))).toEqual(null);
232+
});
233+
});
234+
});

packages/util-dynamodb/src/convertToNative.spec.ts

+6-6
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ describe("convertToNative", () => {
4040
it(`returns for number (integer): ${numString}`, () => {
4141
expect(convertToNative({ ...emptyAttr, N: numString })).toEqual(Number(numString));
4242
});
43-
it(`returns NumberValue for number (integer) with options.wrapNumbers set: ${numString}`, () => {
43+
it(`returns NumberValue for number (integer) with options.wrapNumbers=true: ${numString}`, () => {
4444
expect(convertToNative({ ...emptyAttr, N: numString }, { wrapNumbers })).toEqual({ value: numString });
4545
});
4646
});
@@ -51,7 +51,7 @@ describe("convertToNative", () => {
5151
it(`returns for number (floating point): ${numString}`, () => {
5252
expect(convertToNative({ ...emptyAttr, N: numString })).toEqual(Number(numString));
5353
});
54-
it(`returns NumberValue for number (floating point) with options.wrapNumbers set: ${numString}`, () => {
54+
it(`returns NumberValue for number (floating point) with options.wrapNumbers=true: ${numString}`, () => {
5555
expect(convertToNative({ ...emptyAttr, N: numString }, { wrapNumbers })).toEqual({ value: numString });
5656
});
5757
});
@@ -80,7 +80,7 @@ describe("convertToNative", () => {
8080
BigInt = BigIntConstructor;
8181
});
8282

83-
it(`returns NumberValue for numbers outside SAFE_INTEGER range with options.wrapNumbers set: ${numString}`, () => {
83+
it(`returns NumberValue for numbers outside SAFE_INTEGER range with options.wrapNumbers=true: ${numString}`, () => {
8484
expect(convertToNative({ ...emptyAttr, N: numString }, { wrapNumbers })).toEqual({ value: numString });
8585
});
8686
});
@@ -162,7 +162,7 @@ describe("convertToNative", () => {
162162
});
163163
});
164164

165-
it(`testing list with options.wrapNumbers`, () => {
165+
it(`testing list with options.wrapNumbers=true`, () => {
166166
const input = [{ N: "1.01" }, { N: "9007199254740996" }];
167167
expect(convertToNative({ ...emptyAttr, L: input as AttributeValue[] }, { wrapNumbers: true })).toEqual(
168168
input.map((item) => ({ value: item.N }))
@@ -215,7 +215,7 @@ describe("convertToNative", () => {
215215
}
216216
);
217217

218-
it(`testing map with options.wrapNumbers`, () => {
218+
it(`testing map with options.wrapNumbers=true`, () => {
219219
const input = { numberKey: { N: "1.01" }, bigintKey: { N: "9007199254740996" } };
220220
const output = { numberKey: { value: "1.01" }, bigintKey: { value: "9007199254740996" } };
221221
expect(convertToNative({ ...emptyAttr, M: input }, { wrapNumbers: true })).toEqual(output);
@@ -230,7 +230,7 @@ describe("convertToNative", () => {
230230
expect(convertToNative({ ...emptyAttr, NS: input })).toEqual(new Set([1, 2, BigInt(9007199254740996)]));
231231
});
232232

233-
it("with options.wrapNumbers", () => {
233+
it("with options.wrapNumbers=true", () => {
234234
expect(convertToNative({ ...emptyAttr, NS: input }, { wrapNumbers: true })).toEqual(
235235
new Set(input.map((numString) => ({ value: numString })))
236236
);

0 commit comments

Comments
 (0)