UNPKG

class-hydrator

Version:

Transformation typescript class instance to stringifiable(serializable) plain object

249 lines (245 loc) 8.7 kB
import {Hydrator, hydrate, dehydrate, serialize, deserialize, OnHydrate, OnDehydrate, Exclude} from '../index'; import './sampleClasses'; describe("Hydrator.classes",function(){ class Arbitary{ public thisIsForTest:string; } class OverwrittenClass{ public thisIsForTest:number; } it('should provided with abiraty classes by Hydrator.provideClasses',function(){ Hydrator.provideClasses([Arbitary]); expect(Hydrator.classes["Arbitary"]).toBe(Arbitary); }); it('should be overwritten with arbitary classes by Hydrator.resetClasses', function(){ Hydrator.resetClasses([OverwrittenClass]); expect(Hydrator.classes["Arbitary"]).toBeUndefined(); expect(Hydrator.classes["OverwrittenClass"]).toBe(OverwrittenClass); }) }); describe("Hydratable", function(){ it('should restore children in HydratableClass (HydratableArgs.providers) work)', function(){ class Plant{ constructor(public weight:number){} } class Fruit extends Plant{ constructor(weight:number, public sweetiness:number){ super(weight); } } class Apple extends Fruit{ constructor(weight:number, sweetiness:number, public color:string, public parent:Fruit){ super(weight, sweetiness); } } Hydrator.provideClasses([Plant, Fruit, Apple]); let redFruit = new Fruit(30, 30); let apple = new Apple(25, 28, 'red', redFruit); let dehydratedApple = dehydrate(apple); let hydratedApple = hydrate(dehydratedApple, Apple); expect(hydratedApple).toEqual(jasmine.any(Apple)); expect(hydratedApple.parent).toEqual(jasmine.any(Fruit)); }); }); describe("hydrate exception handlers",function(){ it("should throw error when there was not provided class to hydrate", function(){ class Plant{ constructor(public weight:number){} } class Fruit extends Plant{ constructor(weight:number, public sweetiness:number){ super(weight); } } class Apple extends Fruit{ constructor(weight:number, sweetiness:number, public color:string, public parent:Fruit){ super(weight, sweetiness); } } Hydrator.resetClasses([Apple]); let redFruit = new Fruit(30, 30); let apple = new Apple(25, 28, 'red', redFruit); let dehydratedApple = dehydrate(apple); expect(()=>{hydrate(dehydratedApple, Apple)}).toThrowError("Fruit was not provided to Hydrator") }) }); describe("OnHydrate", function(){ class Parent{ @OnHydrate(()=>"Parent.OnHydrate applied") name:string; constructor(name){ this.name = name } } class Child extends Parent{ @OnHydrate(()=>"Child.OnHydrate applied") age:number; constructor(name, age){ super(name); this.age = age;} } Hydrator.resetClasses([Parent, Child]); describe("with original instance", function(){ let child = new Child('child', 12); let hydratedChild = hydrate(child, Child); it("should work on own property", function(){ expect(hydratedChild.age).toBe("Child.OnHydrate applied"); }); it("should work on inherited property", function(){ expect(hydratedChild.name).toBe("Parent.OnHydrate applied"); }); }); describe("with dehydrated objects", function(){ let child = new Child('child', 12); let dehydratedChild = dehydrate(child); let hydratedChild = hydrate(dehydratedChild, Child); it("should work on own property", function(){ expect(hydratedChild.age).toBe("Child.OnHydrate applied"); }); it("should work on inherited property", function(){ expect(hydratedChild.name).toBe("Parent.OnHydrate applied"); }); }); }); describe("OnDehydrate", function(){ class Parent{ @OnDehydrate(()=>"Parent.OnDehydrate applied") name:string; constructor(name){ this.name = name } } class Child extends Parent{ @OnDehydrate(()=>"Child.OnDehydrate applied") age:number; constructor(name, age){ super(name); this.age = age;} } Hydrator.resetClasses([Parent, Child]); describe("with original instance", function(){ let child = new Child('child', 12); let dehydratedChild = dehydrate(child); it("should work on own property", function(){ expect(dehydratedChild.age).toBe("Child.OnDehydrate applied"); }); it("should work on inherited property", function(){ expect(dehydratedChild.name).toBe("Parent.OnDehydrate applied"); }); }); }); describe("both OnDehydrate and OnHydrate", function(){ class Parent{ @OnDehydrate(()=>"Parent.OnDehydrate applied") @OnHydrate(()=>"Parent.OnHydrate applied") name:string; constructor(name){ this.name = name } } class Child extends Parent{ @OnDehydrate(()=>"Child.OnDehydrate applied") @OnHydrate(()=>"Child.OnHydrate applied") age:number; constructor(name, age){ super(name); this.age = age;} } Hydrator.resetClasses([Parent, Child]); describe("with original instance", function(){ let child = new Child('child', 12); let dehydratedChild = dehydrate(child); let hydratedChild = hydrate(dehydratedChild, Child); let serializedChild = serialize(child); let deserializedChild = deserialize(serializedChild, Child); it("should work on own property", function(){ expect(dehydratedChild.age).toBe("Child.OnDehydrate applied"); expect(hydratedChild.age).toBe("Child.OnHydrate applied"); expect(deserializedChild.age).toBe("Child.OnHydrate applied"); }); it("should work on inherited property", function(){ expect(dehydratedChild.name).toBe("Parent.OnDehydrate applied"); expect(hydratedChild.name).toBe("Parent.OnHydrate applied"); }); }); }); describe("Exclude", function(){ class Parent{ @Exclude() name:string; constructor(name){ this.name = name } } class Child extends Parent{ @Exclude() age:number; constructor(name, age){ super(name); this.age = age;} } Hydrator.resetClasses([Parent, Child]); describe("with original instance", function(){ let child = new Child('child', 12); let dehydratedChild = dehydrate(child); it("should work on own property", function(){ expect(dehydratedChild.age).toBe("_N_"); // _N_ means NULL }); it("should work on inherited property", function(){ expect(dehydratedChild.name).toBe("_N_"); }); }); }); describe("Dehydrate", function(){ class Point { constructor(public x:number, public y:number){} } Hydrator.resetClasses([Point]); let leftTop = new Point(0,0); let dehydratedLeftTop = dehydrate(leftTop); it("should not ignore number member '0'", function(){ expect(dehydratedLeftTop.x).not.toBeUndefined(); expect(dehydratedLeftTop.y).not.toBeUndefined(); }); }); describe("both Exclude and OnHydrate", function(){ class Parent{ @Exclude() @OnHydrate(()=>"Parent.OnHydrate applied") name:string; constructor(name){ this.name = name } } class Child extends Parent{ @Exclude() @OnHydrate(()=>"Child.OnHydrate applied") age:number; constructor(name, age){ super(name); this.age = age;} } Hydrator.resetClasses([Parent, Child]); describe("with original instance", function(){ let child = new Child('child', 12); let dehydratedChild = dehydrate(child); let hydratedChild = hydrate(dehydratedChild, Child); let serializedChild = serialize(child); let deserializedChild = deserialize(serializedChild, Child); it("should work on own property", function(){ expect(hydratedChild.age).toBe("Child.OnHydrate applied"); expect(deserializedChild.age).toBe("Child.OnHydrate applied"); }); it("should work on inherited property", function(){ expect(hydratedChild.name).toBe("Parent.OnHydrate applied"); expect(deserializedChild.name).toBe("Parent.OnHydrate applied"); }); }); }); describe("getter setter", function(){ class Human{ public fullName:string; constructor(public age:number, public lastName:string){ this.fullName = lastName; } set firstName(firstName:string){ this.fullName = firstName+' '+this.lastName; } get firstName(){ let nameArr = this.fullName.split(' '); return nameArr[0]; } } Hydrator.resetClasses([Human]); let human = new Human(12, 'Kim'); let dehydratedHuman = dehydrate(human); let hydratedHuman = hydrate(dehydratedHuman, Human); console.log('human:',human); console.log('dehydratedHuman:',dehydratedHuman); console.log('hydratedHuman:',hydratedHuman); hydratedHuman.firstName = 'Taemin'; it("should available after dehydrated and hydrated", function(){ expect(hydratedHuman.fullName).toBe('Taemin Kim'); expect(hydratedHuman.firstName).toBe('Taemin'); }); });