<commit_before>import { dispatch } from 'core/dispatch'
import { evolve, NodeDescriptor } from 'core'
import * as jsxFactory from 'core/jsxFactory'

/**
 * evolve
 */
describe('core.dispatch', () => {
    it('updates state and calls render', () => {
        const update = (x: number, arg: number) => evolve(x + arg)
        const context = {
            spec: {
                name: '',
                init: { state: undefined },
                view: () => <div>a text</div>
            },
            parentNode: document.body,
            mounted: false,
            mountArg: undefined,
            dispatchLevel: 0,
            isUpdating: false,
            state: 1,
            oldView: undefined,
            rootNode: document.body
        }
        const render = () => {
            expect(context.state).toBe(2)
            return null as any as Node
        }
        dispatch(context, render, update, 2)
    })

    it('does not call render if dispatchLevel > 1', () => {
        const update = (x: number, arg: number) => evolve(x + arg)
        const context = {
            spec: {
                name: '',
                init: { state: undefined },
                view: () => <div>a text</div>
            },
            parentNode: document.body,
            mounted: false,
            mountArg: undefined,
            dispatchLevel: 1,
            isUpdating: false,
            state: undefined,
            oldView: undefined,
            rootNode: document.body
        }
        const renderMock = {
            render: () => {
                return null as any as Node
            }
        }

        spyOn(renderMock, 'render')

        dispatch(context, renderMock.render, update, 2)

        expect(renderMock.render).not.toHaveBeenCalled()
    })

    it('throws if already updating', () => {
        const update = (x: number, arg: number) => evolve(x + arg)
        const context = {
            spec: {
                name: '',
                init: { state: undefined },
                view: () => <div>a text</div>
            },
            parentNode: document.body,
            mounted: false,
            mountArg: undefined,
            dispatchLevel: 0,
            isUpdating: true,
            state: 1,
            oldView: undefined,
            rootNode: document.body
        }
        const render = () => {
            return null as any as Node
        }

        expect(() => dispatch(context, render, update, 2)).toThrow()
    })

    it('call onBeforeRender if a listener is supplied', () => {
        const mock = {
            onBeforeRender: (nodeDescriptor: NodeDescriptor) => {
                expect(nodeDescriptor.__type).toBe(2)
            }
        }<commit_msg>More test coverage<commit_after>import { dispatch } from 'core/dispatch'
import { evolve, NodeDescriptor, Apply } from 'core'
import * as jsxFactory from 'core/jsxFactory'

/**
 * evolve
 */
describe('core.dispatch', () => {
    it('updates state and calls render', () => {
        const update = (x: number, arg: number) => evolve(x + arg)
        const context = {
            spec: {
                name: '',
                init: { state: undefined },
                view: () => <div>a text</div>
            },
            parentNode: document.body,
            mounted: false,
            mountArg: undefined,
            dispatchLevel: 0,
            isUpdating: false,
            state: 1,
            oldView: undefined,
            rootNode: document.body
        }
        const render = () => {
            expect(context.state).toBe(2)
            return null as any as Node
        }
        dispatch(context, render, update, 2)
    })

    it('does not call render if dispatchLevel > 1', () => {
        const update = (x: number, arg: number) => evolve(x + arg)
        const context = {
            spec: {
                name: '',
                init: { state: undefined },
                view: () => <div>a text</div>
            },
            parentNode: document.body,
            mounted: false,
            mountArg: undefined,
            dispatchLevel: 1,
            isUpdating: false,
            state: undefined,
            oldView: undefined,
            rootNode: document.body
        }
        const renderMock = {
            render: () => {
                return null as any as Node
            }
        }

        spyOn(renderMock, 'render')

        dispatch(context, renderMock.render, update, 2)

        expect(renderMock.render).not.toHaveBeenCalled()
    })

    it('throws if already updating', () => {
        const update = (x: number, arg: number) => evolve(x + arg)
        const context = {
            spec: {
                name: '',
                init: { state: undefined },
                view: () => <div>a text</div>
            },
            parentNode: document.body,
            mounted: false,
            mountArg: undefined,
            dispatchLevel: 0,
            isUpdating: true,
            state: 1,
            oldView: undefined,
            rootNode: document.body
        }
        const render = () => {
            return null as any as Node
        }

        expect(() => dispatch(context, render, update, 2)).toThrow()
    })

    it('throws if Update result is not an object', () => {
        const update = () => undefined
        const context = {
            spec: {
                name: '',
                init: { state: undefined },
                view: () => <div>a text</div>
            },
            parentNode: document.body,
            mounted: false,
            mountArg: undefined,
            dispatchLevel: 0,
            isUpdating: true,
            state: 1,
            oldView: undefined,
            rootNode: document.body
        }
        const render = () => {
            return null as any as Node
        }

        expect(() => dispatch(context as any, render, update as any, 2)).toThrow()
    })

    it('invokes effects with an Apply function', () => {

        const mockEffects = {
            effect1: (apply: Apply) => {
                expect(apply).toBeDefined()
            },
            effect2: (apply: Apply) => {
                expect(apply).toBeDefined()
            }
        }

        spyOn(mockEffects, 'effect1')
        spyOn(mockEffects, 'effect2')

        const update = (x: number, arg: number) =>
            evolve(x + arg).and(mockEffects.effect1, mockEffects.effect2)

        const context = {
            spec: {
                name: '',
                init: { state: undefined },
                view: () => <div>a text</div>
            },
            parentNode: document.body,
            mounted: false,
            mountArg: undefined,
            dispatchLevel: 0,
            isUpdating: false,
            state: 1,
            oldView: undefined,
            rootNode: document.body
        }
        const render = () => null as any as Node

        dispatch(context, render, update, 2)

        expect(mockEffects.effect1).toHaveBeenCalledTimes(1)
        expect(mockEffects.effect2).toHaveBeenCalledTimes(1)
    })

    it('call onBeforeRender if a listener is supplied', () => {
        const mock = {
            onBeforeRender: (nodeDescriptor: NodeDescriptor) => {
                expect(nodeDescriptor.__type).toBe(2)
            }
        }
{'fraction_non_alphanumeric': 0.1166394779771615, 'fraction_numerical': 0.005165851005981512, 'mean_word_length': 1.400326264274062, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 64, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5195143', 'n_tokens_mistral': 1956, 'n_tokens_neox': 1873, 'n_words': 503}