keajs / kea-test-utils

MIT License
0 stars 1 forks source link

Connected logic actions can not be tested inside listeners #1

Open danielmariz opened 2 years ago

danielmariz commented 2 years ago

Two issues I found while refactoring my logic using this test utils when they are connected

I have a listener inside one logic that dispatch another logic action

// authLogic file
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)
            }
        },
})

if I understood correctly the documentation I was expecting that this test will pass

test(`requestUserData action call succeeded: 
        * should trigger its listener  
        * wait for user authorization to be revoked
        * dispatch setUserInfo action in userLogic
        * evaluate isLoadingProfile reducer
        *`, async () => {

        const unmountUserLogic = userLogic.mount()

        await expectLogic(authTestLogic, () => {
            expect(authTestLogic.values.isLoadingProfile).toBe(false)
            authTestLogic.actions.requestUserData()
        })
            .toMount([authTestLogic, userLogic()]) //This test proves that the logic is connected
            .toDispatchActions([
                'requestUserData',
            ])
            .toNotHaveDispatchedActions([
                'userDataFailed',
            ])
            .toMatchValues({
                isLoadingProfile: true,
            })
            .toDispatchActionsInAnyOrder([
                'userDataResponse',
                //FIXME: this needs to be tested, if I comment next line the test pass
                userLogic.actionTypes.setUserInfo, 
            ])
            .toMatchValues({
                isLoadingProfile: false,
            })
            .toFinishListeners()
            .clearHistory()

        expect(parseAuthorization).toBeCalled()
        unmountUserLogic()
    })

So while trying to get around this I found another issue: I've tried to instead of explicitly dispatching the outer logic's action do using connect instead `connect: [userLogic],' but than the type script started complaining

'authLogic' implicitly has type 'any' because it does not have a type annotation and is referenced directly or indirectly in its own initializer.ts(7022) the work around was to type logic as any const authLogic:any = kea<authLogicType>({ which is weird, but still the test fails anyways.

Maybe was a misunderstanding one of the tools or this type of feature check should be added.

mariusandra commented 2 years ago

Hey, is this an issue that's still open?

Starting with Kea 3.0 there's no automatic and magical mounting, so the code would probably fail at userLogic.actions.*. Now you need to explicitly define dependencies via connect: [userLogic]... or assure that specific logics are always mounted (e.g. userLogic is globally mounted with the app and is always there, so no need to manually connect everywhere).

In your case, regarding the second error, did you try to add userLogic to authLogic via connect, or vice versa? You should have added connect:[userLogic] to authLogic, not connect:[authLogic] to userLogic. Other than this, it's hard to say what could have caused that error. I did significantly upgrade typegen's type import support for Kea 3.0, so perhaps the issue is already fixed... 🤔