0.6.0-alpha • Published 29 days ago

@statekit/core v0.6.0-alpha

Weekly downloads
-
License
ISC
Repository
-
Last release
29 days ago

statekit PoC WIP

Check out @statekit/react!

import { anAsyncFn, testLog } from "../../__test__/utils"
import { createDfaConfig, createDfa } from "./dfa"

const initialData = { count: 0, foo: "bar" }
type Data = typeof initialData

const config = createDfaConfig({
   states: ["idle", "running", "paused"],
   data: initialData,
   events: {
      noop: () => {},
      data: ({ draft }) => {
         //console.log(draft)
         draft
      },
      payload: ({ draft }, p: Partial<Data>) => {
         Object.assign(draft, p)
      },
      meta: (meta) => {
         meta.draft.foo = meta.state.toString()
      },
      return: ({ isStateOneOf, S }) => {
         if (isStateOneOf([S.idle, S.paused])) return
      },
      cases: ({ cases, S, draft }) =>
         cases({
            [S.idle]: () => S.running,
            [S.paused]: () => {
               draft.count = 123
            },
         }),
      async: async ({ draft, S }) => {
         draft.foo = "loading"

         draft.foo = await anAsyncFn("success")

         return S.running
      },
   },
   helpers: {
      isCountZero: ({ data }) => data.count === 0,
      isCountEqualTo: ({ data }, to: number) => data.count === to,
      isDataSameAs: ({ data }, payload: Data) =>
         data.count === payload.count && data.foo == payload.foo,
   },
   transitionRules: {
      only: {
         paused: ["running"],
      },
      deny: {
         running: ["paused"],
      },
   },
})

/* TS Tests below */
const _tsEmptyConfig = createDfaConfig({})
const _tsConfig = createDfaConfig({ states: ["asd", "qwe"] })
const _ts1 = createDfa(_tsEmptyConfig)
const _ts2 = createDfa(_tsConfig)
const _ts3 = createDfa(config)
const _ts4 = createDfa({
   states: ["idle", "running", "paused"],
   data: initialData,
   events: {
      noop: () => {},
      data: ({ draft }) => {
         console.log(draft)
      },
      payload: ({ draft }, p: Partial<Data>) => {
         Object.assign(draft, p)
      },
      meta: (meta) => {
         meta.draft.foo = meta.state.toString()
      },
      return: ({ isStateOneOf, S }) => {
         if (isStateOneOf([S.idle, S.paused])) return
      },
      cases: ({ cases, S, draft }) =>
         cases({
            [S.idle]: () => S.running,
            [S.paused]: () => {
               draft.count = 123
            },
         }),
   },
   transitionRules: {
      only: {
         paused: ["running"],
      },
      deny: {
         running: ["paused"],
      },
   },
})
// just using
_ts1
_ts2
_ts3
_ts4
/* */

beforeAll(() => jest.useFakeTimers())
afterAll(() => jest.useRealTimers())

describe("DFA", () => {
   it("should create a machine", () => {
      const m = createDfa(config)

      // also checks TS type inference
      const initialState: 0 = m.STATE[config.states[0]]
      expect(m.state).toEqual(initialState)

      expect(m.STATE).toEqual({ idle: 0, running: 1, paused: 2 })

      expect(m.data).toEqual(config.data)
   })

   it("should emit a state", () => {
      const m = createDfa(config)

      const prevState = m.setState(m.STATE.running)
      expect(prevState).toEqual(m.STATE.idle)
      expect(m.state).toEqual(m.STATE.running)

      const prevState2 = m.setState(m.state)
      expect(prevState2).toEqual(false)
      expect(m.state).toEqual(m.STATE.running)
   })

   it("should emit events", () => {
      const m = createDfa(config)
      const { event } = m

      event.noop()
      expect(m.data).toEqual(initialData)

      event.data()
      expect(m.data).toEqual(initialData)

      event.payload({ count: 1 })
      expect(m.data).toEqual({ ...initialData, count: 1 })

      event.meta()
      expect(m.data.foo).toEqual(m.state.toString())
   })

   it("async events work", async () => {
      const m = createDfa(config)
      const { event, STATE } = m

      expect(m.state).toBe(STATE.idle)
      expect(m.data.foo).toBe(initialData.foo)

      const promise = event.async()

      expect(m.state).toBe(STATE.idle)
      expect(m.data.foo).toBe("loading") // consider

      jest.advanceTimersToNextTimer()
      await promise

      expect(m.state).toBe(STATE.running)
      expect(m.data.foo).toBe("success")
   })

   it("helpers work", async () => {
      const m = createDfa(config)
      const { helper } = m

      expect(helper.isCountZero()).toBe(true)

      m.setData((draft) => {
         draft.count = 1
      })

      expect(helper.isCountZero()).toBe(false)
   })

   it("helpers with params work", async () => {
      const m = createDfa(config)
      const { helper } = m

      // single arg
      expect(helper.isCountEqualTo(1)).toBe(false)
      expect(helper.isCountEqualTo(0)).toBe(true)

      // multiple args
      expect(helper.isDataSameAs({ count: 0, foo: "qwe" })).toBe(false)
      expect(helper.isDataSameAs({ count: 0, foo: "bar" })).toBe(true)
   })
})
0.6.0-alpha

29 days ago

0.5.1-alpha

3 months ago

0.5.0-alpha

1 year ago

0.4.0-alpha

1 year ago

0.3.3-alpha

1 year ago

0.3.2-alpha

1 year ago

0.3.1-alpha

1 year ago

0.3.0-alpha

1 year ago

0.2.1-alpha

2 years ago

0.2.0-alpha

2 years ago

0.1.0-alpha

2 years ago

0.0.1-alpha

2 years ago

0.0.0-alpha

2 years ago