使用XState / test测试Auth0身份验证流程

问题描述

我有一个状态机,我正在尝试使用XState / test库进行基于模型的测试。我很难让测试达到所有状态,尤其是“已认证”状态,因为它受到Auth0客户端对象上布尔值条件的保护。

如果有人能够指出我要去哪里,就会朝着正确的方向前进。

AuthenticationMachine.ts

export const authenticationMachine = Machine<AuthMachineContext,AuthMachineschema,AuthMachineEvents>(
  {
    id: 'authentication',initial: 'initializing',context: {
      auth0Client: undefined,user: undefined,error: {
        name: '',message: ''
      }
    },states: {
      initializing: {
        invoke: {
          id: 'getAuthClient',src: 'getAuthClient',onDone: {
            target: 'handleCallback',actions: assign({ auth0Client: (context,event) => event.data })
          },onError: {
            target: 'error'
          }
        },Meta: {
          test: () => {
            expect(true)
          }
        }
      },handleCallback: {
        invoke: {
          id: 'handleCallback',src: 'handleCallback',onDone: {
            target: 'checkingAuthentication'
          },onError: {
            //target: 'unauthenticated'
            target: 'error',//actions: assign({ error: (context,event) => context.error = {name: event.data.name,message: event.data.message} })
          }
        },error: {
        on: {
          RETRY: {
            target: 'checkingAuthentication'
          }
        },checkingAuthentication: {
        id: 'checkingAuthentication',invoke: {
          id: 'isAuthenticated',src: 'isAuthenticated',onDone: [
            {
              cond: (_,event) => event.data,target: 'authenticated'
            },{
              target: 'unauthenticated'
            }
          ],unauthenticated: {
        invoke: {
          id: 'loginWithRedirect',src: 'loginWithRedirect',authenticated: {
        invoke: {
          id: 'getUser',src: 'getUser',onDone: {
            actions: assign({ user: (context,on: {
          logoUT: {
            target: 'unauthenticated',actions: ['logout']
          }
        },Meta: {
          test: () => {
            expect(true)
          }
        }
      }
    }
  },{
    services: {
      getAuthClient: () => {
        return createAuth0Client({
          domain: 'test.auth0.com',client_id: '<my_favorite_client_id>',audience: 'https://my-app/',redirect_uri: window.location.origin 
        })
      },getUser: (ctx) => {
        return ctx.auth0Client!.getUser()
      },handleCallback: (ctx) => {
        if (window.location.search.includes('error=') || (window.location.search.includes('code=') && window.location.search.includes('state='))) {
          // handle the redirect and retrieve tokens
          return ctx.auth0Client!.handleRedirectCallback()
        }
        return Promise.resolve()
      },isAuthenticated: (ctx) => {
        return ctx.auth0Client!.isAuthenticated()
      },loginWithRedirect: (ctx) => {
        return ctx.auth0Client!.loginWithRedirect()
      }
    },actions: {
      logout: (ctx) => {
        ctx.auth0Client!.logout()
      }
    }
  }
)

authenticationMachine.spec.js

jest.mock('@auth0/auth0-spa-js')

const authenticationMachineModel = createModel(authenticationMachine).withEvents({
  logoUT: {
    exec: () =>  console.log("event logout")
  },RETRY: {
    exec: () =>  console.log("event logout")
  },"done.invoke.getAuthClient": {
    exec: () => {
      const client = createAuth0Client({
        domain: 'not-real',client_id: 'fake',audience: 'really-not-real',redirect_uri: window.location.origin
      })
      return client
    }
  },"done.platform.getAuthClient": {
    exec: () => {
      const client = createAuth0Client({
        domain: 'not-real',"done.invoke.handleCallback": {
    exec: () => {
      return Promise.resolve()
    }
  },"done.platform.handleCallback": {
    exec: () => {
      return Promise.resolve()
    }
  },"done.platform.isAuthenticated": {
    exec: () => {
      return Promise.resolve()
    },cases: [new Promise(() => true),new Promise(() => false)]
  },"done.invoke.isAuthenticated": {
    exec: (ctx,event) => {
      return Promise.resolve()
    },"done.platform.loginWithRedirect": {
    exec: () => {
      return Promise.resolve()
    }
  }
})

describe('authentication',() => {
  const testPlans = authenticationMachineModel.getShortestPathPlans()

  testPlans.forEach(plan => {
    describe(plan.description,() => {
      plan.paths.forEach(path => {
        it(path.description,async () => {
          await path.test(path)
        })
      })
    })
  })

  it('should have full coverage',() => {
    return authenticationMachineModel.testCoverage()
  })
})

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)