NextAuth.js 模拟

用于 Jest、Storybook 等的 NextAuth.js 模拟提供程序。

在 Github 上查看

next-auth-mock

安装

通过将其添加到您的 devDependencies 中来安装此库

pnpm add --save-dev @tomfreudenberg/next-auth-mock

Storybook

添加到您的 Storybook 预览中

更新 .storybook/main.js 并追加到您的插件列表中

module.exports = {
  addons: ['@tomfreudenberg/next-auth-mock/storybook']
}

使用工具栏菜单

重新启动 Storybook 后,工具栏中将出现一个额外的图标

这允许您选择会话状态。

编写故事并包含您的组件

// ./stories/pages/denied.stories.jsx

import DeniedPage from '@/pages/auth/denied';

export default {
  title: 'Pages/Auth',
  component: DeniedPage
};

export const DeniedPageStory = (args) => <DeniedPage />;

DeniedPageStory.parameters = {};

您现在可以通过工具栏项目控制和测试您的 useSession() 组件状态

next-auth-mock-storybook-preview

使用固定状态测试组件

为了确保您的组件可以使用固定的身份验证状态进行测试,而不管工具栏选择如何,您可以使用故事中的参数覆盖会话属性

// /stories/pages/signin.stories.jsx

import SigninPage from '@/pages/auth/signin';

export default {
  title: 'Pages/Auth',
  component: SigninPage
};

export const SigninPageStory = (props) => <SigninPage />;

SigninPageStory.parameters = {
  nextAuthMock: {
    session: 'unknown'
  }
};

以上将加载由 id unknown 定义的会话集。您还可以定义一个完整的会话对象,例如

SigninPageStory.parameters = {
  nextAuthMock: {
    session: {
      data: {
        id: 999,
        login: 'user',
        role: 'user',
        roles: ['user'],
        username: 'User',
        email: 'user@local'
      },
      status: 'unauthenticated'
    }
  }
};

在故事中访问当前会话数据

如果您需要在使用会话值时更改故事代码,可以通过 useSession hook 访问它们。

import { useSession } from 'next-auth/react';

export const MyStory = (props) => {
  // get access to current session data
  const session = useSession();

  ...

自定义会话身份验证状态

此组件提供一组默认的身份验证状态:unknownloadingadminadminAutheduseruserAuthed

/**
 *
 * default items for toolbar menu to select different auth-states while mocking
 *
 */
export const mockAuthStates = {
  unknown: {
    title: 'session unknown',
    session: null
  },
  loading: {
    title: 'session loading',
    session: {
      data: null,
      status: 'loading'
    }
  },
  admin: {
    title: 'admin not authenticated',
    session: {
      data: {
        id: 1,
        login: 'admin',
        role: 'admin',
        roles: ['admin', 'user'],
        username: 'Administrator',
        email: 'admin@local'
      },
      status: 'unauthenticated'
    }
  },
  adminAuthed: {
    title: 'admin authenticated',
    session: {
      data: {
        id: 1,
        login: 'admin',
        role: 'admin',
        roles: ['admin', 'user'],
        username: 'Administrator',
        email: 'admin@local'
      },
      status: 'authenticated'
    }
  },
  user: {
    title: 'user not authenticated',
    session: {
      data: {
        id: 999,
        login: 'user',
        role: 'user',
        roles: ['user'],
        username: 'User',
        email: 'user@local'
      },
      status: 'unauthenticated'
    }
  },
  userAuthed: {
    title: 'user authenticated',
    session: {
      data: {
        id: 999,
        login: 'user',
        role: 'user',
        roles: ['user'],
        username: 'User',
        email: 'user@local'
      },
      status: 'authenticated'
    }
  }
};

这组状态可以根据您的需要完全或部分更改。因此,您可以在本地文件夹中创建一个名为 .storybook/previewMockAuthStates.js 的文件,并为 webpack 定义一个别名。

更新 .storybook/main.js

module.exports = {
  addons: ['@tomfreudenberg/next-auth-mock/storybook'],
  webpackFinal: async (config) => {
    config.resolve.alias['@tomfreudenberg/next-auth-mock/storybook/preview-mock-auth-states'] = path.resolve(__dirname, 'previewMockAuthStates.js');
  }
};

Webpack 现在将加载您的文件 .storybook/previewMockAuthStates.js 以获取 previewMockAuthStates 集

只需克隆默认状态
const defaultMockAuthStates = require('@tomfreudenberg/next-auth-mock').mockAuthStates;

module.exports = defaultMockAuthStates;
更改部分状态
const defaultMockAuthStates = require('@tomfreudenberg/next-auth-mock').mockAuthStates;

module.exports = {
  ...defaultMockAuthStates,
  admin: {
    title: 'My Admin unauthenticated',
    session: {
      data: {
        id: 777,
        field: 'Additional session field'
      }
    }
  }
}
仅使用您自己的状态
module.exports = {
  state0: {
    title: 'State zero',
    session: null
  },
  state1: {
    title: 'A State',
    session: {
      data: {
        id: 1,
        user: 'What you like'
      }
    }
  }
}

自定义工具栏图标和项目

工具栏条目也可以完全更改。为此,您需要在 preview.js 中手动实现装饰器,并将选项设置为 mockAuthPreviewToolbarItem(),如您所愿。注意:在这种情况下,请勿将组件添加到插件中。

更新 .storybook/preview.js

import { mockAuthPreviewToolbarItem, withMockAuth } from '@tomfreudenberg/next-auth-mock/storybook';
import { previewMockAuthStates } from '@tomfreudenberg/next-auth-mock/storybook/preview-mock-auth-states';

export const globalTypes = {
  ...mockAuthPreviewToolbarItem({
    description: 'Auswahl Anmeldestatus',
    defaultValue = null,
    icon = 'user',
    items = previewMockAuthStates
  })
};

export const decorators = [withMockAuth];

Jest

编写测试并包含您的组件

// ./tests/pages/signout.stories.jsx

import { render, screen } from '@testing-library/react'
import { withMockAuth } from '@tomfreudenberg/next-auth-mock/jest';
import SignoutPage from '@/pages/auth/signout';

describe('Pages', () => {
  describe('Signout', () => {
    it('should render want to sign out', () => {
      render(withMockAuth(<SignoutPage />, 'userAuthed'));
      expect(screen.getByText('Do you want to sign out?'));
    });
    it('should render not signed in', () => {
      render(withMockAuth(<SignoutPage />, 'unknown'));
      expect(screen.getByText('You are not signed in!'));
    });
  });
});

您可以将 mockAuthStates 条目的名称作为 withMockAuth 的参数输入,或输入会话对象。

import { mockAuthStates } from '@tomfreudenberg/next-auth-mock';
render(withMockAuth(<SignoutPage />, mockAuthStates.userAuthed.session));

// is equal to

render(withMockAuth(<SignoutPage />, 'userAuthed'));

有效状态为:unknownloadingadminadminAutheduseruserAuthed

贡献

如果您想为 next-auth-mock 包做出贡献或需要从源代码使用它,则必须安装 devDependencies 并构建 dist 包。

只需执行以下操作

git clone [email protected]:TomFreudenberg/next-auth-mock.git

cd next-auth-mock

pnpm install

pnpm build

欢迎您的想法和 PR。

npm 包

您可以在 npmjs.com 上找到、使用和下载 npm 包。

npm 版本  

文档

项目主页 - 您可以在 Github 上找到 README

作者及鸣谢

作者:Tom Freudenberg

版权所有 (c) 2022 Tom Freudenberg,根据 MIT 许可证发布