import Immutable, { Map, OrderedMap } from 'immutable'; import Serialize from '../src/immutable'; import { SerializedData } from '../src/helpers'; const serialize = Serialize(Immutable); const stringify = serialize.stringify; const parse = serialize.parse; const data = { map: Immutable.Map({ a: 1, b: 2, c: 3, d: 4 }), orderedMap: Immutable.OrderedMap({ b: 2, a: 1, c: 3, d: 4 }), list: Immutable.List([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]), range: Immutable.Range(0, 7), repeat: Immutable.Repeat('hi', 100), set: Immutable.Set([10, 9, 8, 7, 6, 5, 4, 3, 2, 1]), orderedSet: Immutable.OrderedSet([10, 9, 8, 7, 6, 5, 4, 3, 2, 1]), seq: Immutable.Seq([1, 2, 3, 4, 5, 6, 7, 8]), stack: Immutable.Stack.of('a', 'b', 'c'), }; describe('Immutable', function () { const stringified: { [key: string]: string } = {}; describe('Stringify', function () { Object.keys(data).forEach(function (key) { it(key, function () { stringified[key] = stringify(data[key as keyof typeof data]); expect(stringified[key]).toMatchSnapshot(); }); }); }); describe('Parse', function () { Object.keys(data).forEach(function (key) { it(key, function () { expect(parse(stringified[key])).toEqual(data[key as keyof typeof data]); }); }); }); describe('Record', function () { const ABRecord = Immutable.Record({ a: 1, b: 2 }); const myRecord = new ABRecord({ b: 3 }); const serialize = Serialize(Immutable, [ABRecord]); const stringify = serialize.stringify; const parse = serialize.parse; let stringifiedRecord: string; it('stringify', function () { stringifiedRecord = stringify(myRecord); expect(stringifiedRecord).toMatchSnapshot(); }); it('parse', function () { expect(parse(stringifiedRecord)).toEqual(myRecord); }); }); describe('Nested', function () { const ABRecord = Immutable.Record({ map: Immutable.OrderedMap({ seq: data.seq, stack: data.stack }), repeat: data.repeat, }); const nestedData = Immutable.Set([ABRecord(), data.orderedSet, data.range]); const serialize = Serialize(Immutable, [ABRecord]); const stringify = serialize.stringify; const parse = serialize.parse; let stringifiedNested: string; it('stringify', function () { stringifiedNested = stringify(nestedData); expect(stringifiedNested).toMatchSnapshot(); }); it('parse', function () { expect(parse(stringifiedNested)).toEqual(nestedData); }); }); describe('With references', function () { it('serializes and deserializes', function () { const sharedValue: unknown[] = []; const record = Immutable.Record({ prop: sharedValue, }); const refs = [record]; const obj = Immutable.Map({ fst: new record(), scnd: new record(), }); const serialize = Serialize(Immutable, refs); const serialized = serialize.stringify(obj); const parsed = JSON.parse(serialized); const fstProp = parsed.data.fst.data.prop; const scndProp = parsed.data.scnd.data.prop; expect(fstProp).toEqual(scndProp); expect(Array.isArray(obj.get('fst')!.get('prop'))).toBe(true); }); }); describe('Custom replacer and reviver functions', function () { const customOneRepresentation = 'one'; function customReplacer( key: string, value: unknown, defaultReplacer: (key: string, value: unknown) => unknown ) { if (value === 1) { return { data: customOneRepresentation, __serializedType__: 'number' }; } return defaultReplacer(key, value); } function customReviver( key: string, value: unknown, defaultReviver: (key: string, value: unknown) => unknown ) { if ( typeof value === 'object' && (value as SerializedData).__serializedType__ === 'number' && (value as SerializedData).data === customOneRepresentation ) { return 1; } return defaultReviver(key, value); } const serializeCustom = Serialize( Immutable, null, customReplacer, customReviver ); Object.keys(data).forEach(function (key) { const stringified = serializeCustom.stringify( data[key as keyof typeof data] ); it(key, function () { const deserialized = serializeCustom.parse(stringified); expect(deserialized).toEqual(data[key as keyof typeof data]); if (key === 'map' || key === 'orderedMap') { const deserializedDefault = parse(stringified); expect( (deserializedDefault as | Map | OrderedMap).get('a') ).toEqual(customOneRepresentation); } }); }); }); });