测试 MSAL React 应用程序时模拟身份验证

11
我们的应用程序是以标准方式使用@azure/msal-react中的MSAL身份验证模板包装的 - 关键代码段如下所述。
我们想使用React测试库(或类似工具)测试应用程序的各个组件。当然,如果要像下面的简单测试一样正确呈现React组件(例如SampleComponentUnderTest),则必须将其包装在MSAL组件中。
有没有适当的方法来模拟MSAL身份验证过程以进行此类测试?是否有一种方法可以将待测试的组件包装在MSAL中,并直接向该待测组件提供测试用户的凭据?如果您能给出有用的文档、博客文章、视频等参考资料,将不胜感激。
一个简单的测试:
test('first test', () => {
  const { getByText } = render(<SampleComponentUnderTest />);
  const someText = getByText('A line of text');
  expect(someText).toBeInTheDocument();
});

配置

export const msalConfig: Configuration = {
  auth: {
    clientId: `${process.env.REACT_APP_CLIENT_ID}`,
    authority: `https://login.microsoftonline.com/${process.env.REACT_APP_TENANT_ID}`,
    redirectUri:
      process.env.NODE_ENV === 'development'
        ? 'http://localhost:3000/'
        : process.env.REACT_APP_DEPLOY_URL,
  },
  cache: {
    cacheLocation: 'sessionStorage',
    storeAuthStateInCookie: false,
  },
  system: {
    loggerOptions: {
      loggerCallback: (level, message, containsPii) => {
        if (containsPii) {
          return;
        }
        switch (level) {
          case LogLevel.Error:
            console.error(message);
            return;
          case LogLevel.Info:
            console.info(message);
            return;
          case LogLevel.Verbose:
            console.debug(message);
            return;
          case LogLevel.Warning:
            console.warn(message);
            return;
          default:
            console.error(message);
        }
      },
    },
  },
};

主应用程序组件

const msalInstance = new PublicClientApplication(msalConfig);

<MsalProvider instance={msalInstance}>
  {!isAuthenticated && <UnauthenticatedHomePage />}
  {isAuthenticated && <Protected />}
</MsalProvider>

未经身份验证的组件

const signInClickHandler = (instance: IPublicClientApplication) => {
  instance.loginRedirect(loginRequest).catch((e) => {
    console.log(e);
  });
};

<UnauthenticatedTemplate>
  <Button onClick={() => signInClickHandler(instance)}>Sign in</Button>
</UnauthenticatedTemplate>

受保护的组件

<MsalAuthenticationTemplate
  interactionType={InteractionType.Redirect}
  errorComponent={ErrorComponent}
  loadingComponent={LoadingComponent}
>
    <SampleComponentUnderTest />
</MsalAuthenticationTemplate>
2个回答

10
我也遇到了与你相同的问题,涉及到在msal-react下进行组件测试。 我花了几天时间才想出如何实现正确的身份验证模拟。 这就是为什么我创建了一个包,您可以在此处找到,它封装了所有样板代码:https://github.com/Mimetis/msal-react-tester 基本上,您可以在几行代码中执行多个场景(用户已经登录,用户未登录,用户必须登录等...),而无需进行任何配置,当然,在任何情况下都不需要访问Azure AD:
describe('Home page', () => {

  let msalTester: MsalReactTester;
  beforeEach(() => {
    // new instance of msal tester for each test
    msalTester = new MsalReactTester();

    // spy all required msal things
    msalTester.spyMsal();
  });

  afterEach(() => {
    msalTester.resetSpyMsal();
  });

  test('Home page render correctly when user is logged in', async () => {

    msalTester.isLogged();

    render(
      <MsalProvider instance={msalTester.client}>
        <MemoryRouter>
          <Layout>
            <HomePage />
          </Layout>
        </MemoryRouter>
      </MsalProvider>,
    );

    await msalTester.waitForRedirect();

    let allLoggedInButtons = await screen.findAllByRole('button', { name: `${msalTester.activeAccount.name}` });
    expect(allLoggedInButtons).toHaveLength(2);
  });

  test('Home page render correctly when user logs in using redirect', async () => {

    msalTester.isNotLogged();
    render(
      <MsalProvider instance={msalTester.client}>
        <MemoryRouter>
          <Layout>
            <HomePage />
          </Layout>
        </MemoryRouter>
      </MsalProvider>,
    );

    await msalTester.waitForRedirect();

    let signin = screen.getByRole('button', { name: 'Sign In - Redirect' });
    userEvent.click(signin);

    await msalTester.waitForLogin();

    let allLoggedInButtons = await screen.findAllByRole('button', { name: `${msalTester.activeAccount.name}` });
    expect(allLoggedInButtons).toHaveLength(2);
  });



3
这真的很棒,非常感谢您将这个软件包整理在一起! - savreline
谢谢您。解决了我今天一直在苦苦挣扎的问题。 - Yass
老兄,上帝保佑你!工作得像魔法一样! - Dobromir Ivanov

1
我也对此很好奇,但是从稍微不同的角度来看。为了避免在需要更换身份提供者时直接在代码库中使用来自msal的组件,我正在尝试使用钩子作为抽象层,例如通过该钩子公开isAuthenticated,而不是直接使用msal组件库本身。 useAuth钩子将直接使用MSAL包。然而,对于包装器组件,我认为我们必须创建一个单独的组件,该组件返回MsalProvider或您选择的模拟身份验证提供者。由于MsalProvider在内部使用useContext,因此我认为您不需要将其包装在另一个上下文提供程序中。
希望这些想法能够在您考虑如何实现此目标时有所帮助。请注意,这不是对您问题的直接回答。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接