keajs / kea-test-utils

MIT License
0 stars 1 forks source link

Be able to match values from connected logics #2

Open danielmariz opened 2 years ago

danielmariz commented 2 years ago

I was expecting a way to match values from connected logic: My current case is using kea-router

Code:

// authLogic file
urlToAction: ({ actions }) => ({
        '/auth/callback': (pathname, search, hash) => {
            if (hash?.error) {
                actions.authenticationFailed(hash as Auth0Error)
                return
            }
            actions.requestUserData()
        },
    }),
listeners: ({ actions }) => ({
    requestUserData: async () => {
            try {
                const userInfo = (await parseAuthorization()) as UserInfoType
                actions.userDataResponse(userInfo)
                //explicitly dispatches userLogic action
                userLogic.actions.setUserInfo(userInfo)

                if (router.values.location.pathname === '/auth/callback') {
                    router.actions.push('/')
                }
            } catch (error: any) {
                const msg = error?.message || 'Error occurred while trying to get user profile!'
                actions.userDataFailed(msg)
            }
        },
})

Test case:

    beforeEach(() => {
        const history = createMemoryHistory()
        ;(history as any).pushState = history.push
        ;(history as any).replaceState = history.replace
        resetContext({ 
            createStore: true,
            plugins: [
                testUtilsPlugin,
                routerPlugin({ 
                    history: history, 
                    location: history.location 
                } as any),
                waitForPlugin, 
            ]
        })

        authTestLogic = authLogic()
        unmount = authTestLogic.mount()
    })

    afterEach(() => {
        unmount()
    })

    test('urlToAction listener should trigger requestUserData action when redirected to "/auth/callback"', async () => {
        const unmountRouter = router.mount()\
        const unmountUserLogic = userLogic.mount()

        await expectLogic(authLogic, () => router.actions.push('/auth/callback'))
            .toDispatchActions([
                'requestUserData'
            ])
            .toNotHaveDispatchedActions([
                'authenticationFailed'
            ])
            .toMatchValues({
                //FIXME: connected logic needs to be tested
                router.values.location.pathname === '/auth/callback'
            })
            .toDispatchActionsInAnyOrder([
                'userDataResponse'
                //FIXME: connected logic needs to be tested
                userLogic.actionTypes.setUserInfo,
                //FIXME: connected logic needs to be tested
                router.actionCreators.push('/')
            ])
            .toFinishListeners()

        //ATENTION: this is current working but the value should be '/' requestUserData listener is finished
        expect(router.values.location.pathname).toBe('/auth/callback')
        unmountRouter()
        unmountUserLogic()
    })

Error printed:

Timed out waiting for action: "setUserInfo" in logic containers.user.auth
     At timeout had received these actions: {"type":"@KEA/ATTACH_REDUCER","payload":{"path":["kea","router"]}}
    {"type":"@KEA/ATTACH_REDUCER","payload":{"path":["containers","user","auth"]}}
    {"type":"@KEA/ATTACH_REDUCER","payload":{"path":["containers","user","main"]}}
    {"type":"push (kea.router)","payload":{"url":"/auth/callback"}}
    {"type":"location changed (kea.router)","payload":{"method":"PUSH","pathname":"/auth/callback","search":"","searchParams":{},"hash":"","hashParams":{},"initial":false}}
    {"type":"request user data (containers.user.auth)","payload":{"value":true}}
    {"type":"user data response (containers.user.auth)","payload":{}}
    {"type":"user data failed (containers.user.auth)","payload":{"message":"Cannot read properties of undefined (reading 'profile')"}}

      at node_modules/kea-test-utils/src/functions/toDispatchActions.ts:28:19
mariusandra commented 2 years ago

Something else is going on. Connected logics can be tested easily. I don't see why this wouldn't work:

        await expectLogic(authLogic, () => router.actions.push('/auth/callback'))
            .toDispatchActions([
                'requestUserData'
            ])
            .toNotHaveDispatchedActions([
                'authenticationFailed'
            ])

        await expectLogic(router)
            .toMatchValues({
               location: partial({pathname: '/auth/callback'})
            })
        // continue checking the other logic

You can also always write expect(router.values.location.pathname).toEqual('/auth/callback') as well, but know that kea test utils always match values right after an action, whereas router.values.location will always give the last one.