import { setupBinding } from "../src/state/stateBinding" import { BB_STATE_BINDINGPATH, BB_STATE_FALLBACK, BB_STATE_BINDINGSOURCE, } from "../src/state/isState" import { EVENT_TYPE_MEMBER_NAME } from "../src/state/eventHandlers" import { writable } from "svelte/store" import { isFunction } from "lodash/fp" describe("setupBinding", () => { it("should correctly create initials props, including fallback values", () => { const { store, props, component } = testSetup() const { initialProps } = testSetupBinding(store, props, component) expect(initialProps.boundWithFallback).toBe("Bob") expect(initialProps.boundNoFallback).toBeUndefined() expect(initialProps.unbound).toBe("hello") expect(isFunction(initialProps.eventBound)).toBeTruthy() initialProps.eventBound() }) it("should update component bound props when store is updated", () => { const { component, store, props } = testSetup() const { bind } = testSetupBinding(store, props, component) bind(component) store.update(s => { s.FirstName = "Bobby" s.LastName = "Thedog" s.Customer = { Name: "ACME inc", Address: "", } s.addressToSet = "123 Main Street" return s }) expect(component.props.boundWithFallback).toBe("Bobby") expect(component.props.boundNoFallback).toBe("Thedog") expect(component.props.multiPartBound).toBe("ACME inc") }) it("should not update unbound props when store is updated", () => { const { component, store, props } = testSetup() const { bind } = testSetupBinding(store, props, component) bind(component) store.update(s => { s.FirstName = "Bobby" s.LastName = "Thedog" s.Customer = { Name: "ACME inc", Address: "", } s.addressToSet = "123 Main Street" return s }) expect(component.props.unbound).toBe("hello") }) it("should update event handlers on state change", () => { const { component, store, props } = testSetup() const { bind } = testSetupBinding(store, props, component) bind(component) expect(component.props.boundToEventOutput).toBe("initial address") component.props.eventBound() expect(component.props.boundToEventOutput).toBe("event fallback address") store.update(s => { s.addressToSet = "123 Main Street" return s }) component.props.eventBound() expect(component.props.boundToEventOutput).toBe("123 Main Street") }) it("event handlers should recognise event parameter", () => { const { component, store, props } = testSetup() const { bind } = testSetupBinding(store, props, component) bind(component) expect(component.props.boundToEventOutput).toBe("initial address") component.props.eventBoundUsingEventParam({ addressOverride: "Overridden Address", }) expect(component.props.boundToEventOutput).toBe("Overridden Address") store.update(s => { s.addressToSet = "123 Main Street" return s }) component.props.eventBound() expect(component.props.boundToEventOutput).toBe("123 Main Street") component.props.eventBoundUsingEventParam({ addressOverride: "Overridden Address", }) expect(component.props.boundToEventOutput).toBe("Overridden Address") }) it("should bind initial props to supplied context", () => { const { component, store, props } = testSetup() const { bind } = testSetupBinding(store, props, component, { ContextValue: "Real Context Value", }) bind(component) expect(component.props.boundToContext).toBe("Real Context Value") }) }); const testSetupBinding = (store, props, component, context) => { const setup = setupBinding(store, props, undefined, context) component.props = setup.initialProps // svelte does this for us in real life return setup } const testSetup = () => { const c = {} c.props = {} c.$set = propsToSet => { for (let pname in propsToSet) c.props[pname] = propsToSet[pname] } const binding = (path, fallback, source) => ({ [BB_STATE_BINDINGPATH]: path, [BB_STATE_FALLBACK]: fallback, [BB_STATE_BINDINGSOURCE]: source || "store" }); const event = (handlerType, parameters) => ({ [EVENT_TYPE_MEMBER_NAME]: handlerType, parameters }); const props = { boundWithFallback: binding("FirstName", "Bob"), boundNoFallback: binding("LastName"), unbound: "hello", multiPartBound: binding("Customer.Name", "ACME"), boundToEventOutput: binding("Customer.Address", "initial address"), boundToContext: binding("ContextValue", "context fallback", "context"), eventBound: [ event("Set State", { path: "Customer.Address", value: binding("addressToSet", "event fallback address"), }), ], eventBoundUsingEventParam: [ event("Set State", { path: "Customer.Address", value: binding("addressOverride", "", "event"), }), ], } return { component: c, store: writable({}), props, } }