Skip to content

Instantly share code, notes, and snippets.

@mharris717
Created April 24, 2019 15:43
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mharris717/485a39e2871887344704ec5efebd2556 to your computer and use it in GitHub Desktop.
Save mharris717/485a39e2871887344704ec5efebd2556 to your computer and use it in GitHub Desktop.
Change child type on parent data changes
/* global describe, it, beforeEach */
import expect from "expect";
import { create } from "../src/microstates";
function isStateType(obj, T) {
return obj.constructor.name === `Microstate<${T}>`;
}
function withInitBehavior(T, f) {
return class extends T {
initialize(data = {}) {
let res = T.prototype.initialize.apply(this, [data]);
return f(data, res);
}
};
}
function withPet(T) {
return withInitBehavior(
class extends T {
pet = Animal;
},
(data, res) => {
if (data.demandFish && !isStateType(res.pet, "Fish")) {
return res.set({ pet: create(Fish, data.pet || {}) });
}
return res;
}
);
}
class BaseHuman {
name = String;
initRan = Boolean;
demandFish = Boolean;
initialize(data = {}) {
if (!this.initRan.state) {
return this.initRan.set(true);
}
return this;
}
}
const Human = withPet(BaseHuman);
class Animal {
name = String;
fluffy = Boolean;
initialize(data = {}) {
let res = this;
let nameCheck = (petType, name) => {
if (data.name === name) {
return create(petType, data);
}
return res;
};
res = nameCheck(Dog, "Fido");
res = nameCheck(Fish, "Nemo");
return res;
}
}
class Dog extends Animal {
initialize(data) {
if (!this.fluffy.state) {
return this.fluffy.set(true);
}
return this;
}
get bark() {
return () => "Woof!";
}
}
class Fish extends Animal {
get useGills() {
return () => "Gurgle!";
}
}
describe("child type", () => {
it("has dog - specify class", () => {
let owner = create(Human, {
name: "Steve",
pet: create(Dog, { name: "Fido" })
});
expect(owner.pet.constructor.name).toEqual("Microstate<Dog>");
expect(owner.pet.fluffy.state).toEqual(true);
expect(owner.pet.name.state).toEqual("Fido");
expect(owner.initRan.state).toEqual(true);
owner.pet.bark();
});
it("has fish", () => {
let owner = create(Human, {
name: "Steve",
pet: create(Fish, { name: "Nemo" })
});
expect(owner.pet.constructor.name).toEqual("Microstate<Fish>");
expect(owner.pet.fluffy.state).toEqual(false);
expect(owner.pet.name.state).toEqual("Nemo");
expect(owner.initRan.state).toEqual(true);
owner.pet.useGills();
});
it("has dog - infer it", () => {
let owner = create(Human, {
name: "Steve",
pet: { name: "Fido" }
});
expect(owner.pet.constructor.name).toEqual("Microstate<Dog>");
expect(owner.pet.fluffy.state).toEqual(true);
expect(owner.pet.name.state).toEqual("Fido");
expect(owner.initRan.state).toEqual(true);
owner.pet.bark();
});
it("has fish - infer it", () => {
let owner = create(Human, {
name: "Steve",
pet: { name: "Nemo" }
});
expect(owner.pet.constructor.name).toEqual("Microstate<Fish>");
expect(owner.pet.fluffy.state).toEqual(false);
expect(owner.pet.name.state).toEqual("Nemo");
expect(owner.initRan.state).toEqual(true);
owner.pet.useGills();
});
it("unknown type", () => {
let owner = create(Human, {
name: "Steve",
pet: { name: "Mister Ed" }
});
expect(owner.pet.constructor.name).toEqual("Microstate<Animal>");
expect(owner.pet.fluffy.state).toEqual(false);
expect(owner.pet.name.state).toEqual("Mister Ed");
});
it("has dog - infer it when set after creation", () => {
let owner = create(Human, {
name: "Steve"
});
expect(owner.name.state).toEqual("Steve");
expect(owner.initRan.state).toEqual(true);
owner = owner.pet.set({ name: "Fido" });
expect(owner.pet.constructor.name).toEqual("Microstate<Dog>");
expect(owner.pet.fluffy.state).toEqual(true);
expect(owner.pet.name.state).toEqual("Fido");
owner.pet.bark();
});
it("toggle pet back and forth", () => {
let owner = create(Human, {
name: "Steve",
pet: { name: "Fido" }
});
expect(owner.pet.constructor.name).toEqual("Microstate<Dog>");
expect(owner.pet.fluffy.state).toEqual(true);
expect(owner.pet.name.state).toEqual("Fido");
expect(owner.initRan.state).toEqual(true);
owner.pet.bark();
owner = owner.pet.set({ name: "Nemo" });
expect(owner.pet.constructor.name).toEqual("Microstate<Fish>");
expect(owner.pet.fluffy.state).toEqual(false);
expect(owner.pet.name.state).toEqual("Nemo");
owner.pet.useGills();
owner = owner.pet.set({ name: "Mister Ed" });
expect(owner.pet.constructor.name).toEqual("Microstate<Animal>");
});
it("human demands a fish", () => {
let owner = create(Human, {
name: "Steve",
pet: { name: "Mister Ed" }
});
expect(owner.pet.constructor.name).toEqual("Microstate<Animal>");
owner = owner.demandFish.set(true);
expect(owner.pet.constructor.name).toEqual("Microstate<Fish>");
});
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment