diff --git a/packages/serialize/package.json b/packages/serialize/package.json index 27922d4c4..1658cdb45 100644 --- a/packages/serialize/package.json +++ b/packages/serialize/package.json @@ -64,14 +64,14 @@ }, "homepage": "https://github.com/jaredwray/keyv", "dependencies": { - "buffer": "^6.0.1" + "buffer": "^6.0.3" }, "devDependencies": { "@keyv/test-suite": "*", "keyv": "*", "ts-node": "^10.9.2", "tsd": "^0.31.0", - "typescript": "^5.4.3" + "typescript": "^5.4.5" }, "tsd": { "directory": "test" diff --git a/packages/serialize/test/test.ts b/packages/serialize/test/test.ts index 9749f54be..5978401c6 100644 --- a/packages/serialize/test/test.ts +++ b/packages/serialize/test/test.ts @@ -1,3 +1,4 @@ +import {Buffer} from 'node:buffer'; import test from 'ava'; import {defaultDeserialize, defaultSerialize} from '../src'; @@ -19,8 +20,55 @@ test('serialization and deserialization of boolean value', t => { t.is(deserialized.value, true); }); +test('serialization and deserialization of only string value', t => { + const serialized = defaultSerialize('foo'); + t.is(defaultDeserialize(serialized), 'foo'); +}); + +test('serialization and deserialization of only string value with colon', t => { + const serialized = defaultSerialize(':base64:aGVsbG8gd29ybGQ='); + t.is(defaultDeserialize(serialized), ':base64:aGVsbG8gd29ybGQ='); +}); + test('serialization and deserialization of object value', t => { const serialized = defaultSerialize({value: {foo: 'bar', bar: 5, baz: true, def: undefined, nul: null}}); const deserialized = defaultDeserialize<{value: {foo: string; bar: number; baz: boolean; def?: string; nul: string | undefined}}>(serialized); t.deepEqual(deserialized.value, {foo: 'bar', bar: 5, baz: true, nul: null}); }); + +test('defaultSerialize converts Buffer to base64 JSON string', t => { + const buffer = Buffer.from('hello world', 'utf8'); + const expectedResult = JSON.stringify(':base64:' + buffer.toString('base64')); + const result = defaultSerialize(buffer); + t.is(result, expectedResult); +}); + +test('serialization toJSON is called on object', t => { + // eslint-disable-next-line @typescript-eslint/naming-convention + const serialized = defaultSerialize({value: {toJSON: () => 'foo'}}); + const deserialized = defaultDeserialize<{value: string}>(serialized); + t.is(deserialized.value, 'foo'); +}); + +test('serialization with array in array', t => { + const serialized = defaultSerialize({value: [[1, 2], [3, 4]]}); + const deserialized = defaultDeserialize<{value: number[][]}>(serialized); + t.deepEqual(deserialized.value, [[1, 2], [3, 4]]); +}); + +test('defaultSerialize detects base64 on string', t => { + const json = JSON.stringify({ + encoded: ':base64:aGVsbG8gd29ybGQ=', // "hello world" in base64 + }); + const result = defaultDeserialize<{encoded: Buffer}>(json); + t.is(result.encoded.toString(), 'hello world'); +}); + +test('removes the first colon from strings not prefixed by base64', t => { + const json = JSON.stringify({ + simple: ':hello', + }); + + const result = defaultDeserialize<{simple: string}>(json); + t.is(result.simple, 'hello'); +});