UNPKG

@johngw/stream

Version:

Reactive programming tools using the WHATWG Streams API.

180 lines (161 loc) 3.91 kB
import { write } from '@johngw/stream/sinks/write' import { StatefulSubject } from '@johngw/stream/subjects/StatefulSubject' import { timeout } from '@johngw/stream-common' interface State { authors: string[] } type Actions = { 'add author': string nothing: void } let subject: StatefulSubject<Actions, State> beforeEach(() => { subject = new StatefulSubject<Actions, State>({ __INIT__: () => ({ authors: [] }), 'add author': (state, author) => state.authors.includes(author) ? state : { ...state, authors: [...state.authors, author], }, nothing: (state) => state, }) }) test('the __INIT__ action', async () => { const fn = jest.fn() const controller = subject.control() controller.close() await subject.fork().pipeTo(write(fn)) expect(fn).toHaveBeenCalledTimes(1) expect(fn.mock.calls).toMatchInlineSnapshot(` [ [ { "action": "__INIT__", "state": { "authors": [], }, }, ], ] `) }) test('a reducer that changes state', async () => { const fn = jest.fn() const controller = subject.control() controller.dispatch('add author', 'Jane Austin') controller.close() await subject.fork().pipeTo(write(fn)) expect(fn).toHaveBeenCalledTimes(1) expect(fn.mock.calls).toMatchInlineSnapshot(` [ [ { "action": "add author", "param": "Jane Austin", "state": { "authors": [ "Jane Austin", ], }, }, ], ] `) }) test('a reducer that doesnt change state', async () => { const fn = jest.fn() const controller = subject.control() controller.dispatch('nothing') controller.close() await subject.fork().pipeTo(write(fn)) expect(fn).toHaveBeenCalledTimes(1) expect(fn.mock.calls).toMatchInlineSnapshot(` [ [ { "action": "__INIT__", "state": { "authors": [], }, }, ], ] `) }) test('multiple calls', async () => { const fn = jest.fn() const promise = subject.fork().pipeTo(write(fn)) const controller = subject.control() // There's a bug in the web-streams-polyfill that resolves the above // promise too early. await timeout() controller.dispatch('add author', 'Jane Austin') controller.dispatch('add author', 'George Orwell') controller.dispatch('add author', 'Jane Austin') controller.close() await promise expect(fn).toHaveBeenCalledTimes(3) expect(fn.mock.calls).toMatchInlineSnapshot(` [ [ { "action": "__INIT__", "state": { "authors": [], }, }, ], [ { "action": "add author", "param": "Jane Austin", "state": { "authors": [ "Jane Austin", ], }, }, ], [ { "action": "add author", "param": "George Orwell", "state": { "authors": [ "Jane Austin", "George Orwell", ], }, }, ], ] `) }) test('typing errors', () => { expect( () => new StatefulSubject<Actions, State>( // @ts-expect-error There is no __INIT__ method { 'add author': (state) => state, } ) ).toThrow() new StatefulSubject<Actions, State>({ // @ts-expect-error Incorrect state shape __INIT__: () => ({ mung: 'face' }), // @ts-expect-error Function declaration does not match action nothing: (state, param: string) => ({ ...state, authors: [param] }), }) subject.control().close() return subject.fork().pipeTo( write((chunk) => { // @ts-expect-error Unknown action name if (chunk.action === 'unknown') { // } }) ) })