我们的应用程序以标准方式封装在
@azure/msal-react
的 MSAL 身份验证模板中 - 关键代码段总结如下。
我们想使用反应测试库(或类似的东西)来测试应用程序的各个组件。当然,当要通过测试正确呈现诸如
SampleComponentUnderTest
之类的 React 组件(如下面的简单测试所示)时,它也必须包装在 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>
关于 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);
});
我也对此感到好奇,但角度略有不同。我试图避免直接从 msal 中直接使用组件来乱扔代码库,以防我们想在某个时候更换身份提供者。实现此目的的主要方法是使用钩子作为抽象层,例如通过该钩子而不是 msal 组件库本身公开 isAuthenticated。
useAuth 挂钩将直接使用 MSAL 包。然而,对于包装器组件,我认为我们必须创建一个单独的组件,该组件返回 MsalProvider 或您选择的模拟身份验证提供程序。由于 MsalProvider 在底层使用了 useContext,我认为您不需要将其包装在另一个上下文提供程序中。
希望这些想法在您思考如何做到这一点时有所帮助。要知道这不是对您问题的直接答案。