veza/apps/web/src/components/settings/security/TwoFactorSetup.stories.tsx

116 lines
2.7 KiB
TypeScript
Raw Normal View History

2026-02-03 08:56:11 +00:00
import type { Meta, StoryObj } from '@storybook/react';
import { fn } from '@storybook/test';
import { within, userEvent } from '@storybook/test';
import { http, HttpResponse } from 'msw';
import { TwoFactorSetup, TwoFactorSetupSkeleton } from './TwoFactorSetup';
2026-02-03 08:56:11 +00:00
const meta: Meta<typeof TwoFactorSetup> = {
title: 'Components/Features/Settings/Security/TwoFactorSetup',
component: TwoFactorSetup,
parameters: {
layout: 'padded',
docs: {
description: {
component:
'Assistant de configuration 2FA en 3 étapes: choix de méthode, scan QR code, codes de backup.',
},
2026-02-03 08:56:11 +00:00
},
},
tags: ['autodocs'],
args: {
onBack: fn(),
onComplete: fn(),
},
argTypes: {
onBack: {
description: "Callback appelé quand l'utilisateur revient en arrière",
action: 'onBack',
2026-02-03 08:56:11 +00:00
},
onComplete: {
description: "Callback appelé quand la configuration est terminée",
action: 'onComplete',
2026-02-03 08:56:11 +00:00
},
},
decorators: [
(Story) => (
<div className="max-w-2xl mx-auto p-4 bg-kodo-background min-h-layout-page-sm">
<Story />
</div>
),
],
2026-02-03 08:56:11 +00:00
};
export default meta;
type Story = StoryObj<typeof meta>;
export const Default: Story = {
name: 'Par défaut',
};
2026-02-03 08:56:11 +00:00
export const Step1_ChooseMethod: Story = {
name: 'Étape 1: Choix de méthode',
parameters: {
docs: {
description: {
story:
'Première étape: choisir entre Authenticator App (TOTP) ou SMS.',
},
2026-02-03 08:56:11 +00:00
},
},
2026-02-03 08:56:11 +00:00
};
export const Step2_QRCode: Story = {
name: 'Étape 2: QR Code',
play: async ({ canvasElement }) => {
const canvas = within(canvasElement);
const totpOption = canvas.getByText(/authenticator app/i);
await userEvent.click(totpOption);
},
parameters: {
docs: {
description: {
story:
'Deuxième étape: scanner le QR code et entrer le code de vérification.',
},
2026-02-03 08:56:11 +00:00
},
},
2026-02-03 08:56:11 +00:00
};
export const Loading: Story = {
name: 'Chargement',
render: () => <TwoFactorSetupSkeleton />,
parameters: {
docs: {
description: {
story: 'Skeleton de lassistant 2FA (en-tête + cartes méthode).',
},
},
},
};
2026-02-03 08:56:11 +00:00
export const Error: Story = {
name: 'Erreur',
play: async ({ canvasElement }) => {
const canvas = within(canvasElement);
const totpOption = canvas.getByText(/authenticator app/i);
await userEvent.click(totpOption);
},
parameters: {
msw: {
handlers: [
http.post('*/api/v1/auth/2fa/setup', () =>
HttpResponse.json(
{ success: false, error: { message: 'Setup failed' } },
{ status: 500 },
),
),
],
2026-02-03 08:56:11 +00:00
},
docs: {
description: {
story: 'MSW retourne 500 sur POST /auth/2fa/setup. Toast + onBack.',
},
2026-02-03 08:56:11 +00:00
},
},
2026-02-03 08:56:11 +00:00
};