class-hydrator
Version:
Transformation typescript class instance to stringifiable(serializable) plain object
249 lines (245 loc) • 8.7 kB
text/typescript
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{
(()=>"Parent.OnHydrate applied")
name:string;
constructor(name){ this.name = name }
}
class Child extends Parent{
(()=>"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{
(()=>"Parent.OnDehydrate applied")
name:string;
constructor(name){ this.name = name }
}
class Child extends Parent{
(()=>"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{
(()=>"Parent.OnDehydrate applied")
(()=>"Parent.OnHydrate applied")
name:string;
constructor(name){ this.name = name }
}
class Child extends Parent{
(()=>"Child.OnDehydrate applied")
(()=>"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{
()
name:string;
constructor(name){ this.name = name }
}
class Child extends Parent{
()
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{
()
(()=>"Parent.OnHydrate applied")
name:string;
constructor(name){ this.name = name }
}
class Child extends Parent{
()
(()=>"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');
});
});