115 lines
2.7 KiB
TypeScript
115 lines
2.7 KiB
TypeScript
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';
|
||
|
||
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.',
|
||
},
|
||
},
|
||
},
|
||
tags: ['autodocs'],
|
||
args: {
|
||
onBack: fn(),
|
||
onComplete: fn(),
|
||
},
|
||
argTypes: {
|
||
onBack: {
|
||
description: "Callback appelé quand l'utilisateur revient en arrière",
|
||
action: 'onBack',
|
||
},
|
||
onComplete: {
|
||
description: "Callback appelé quand la configuration est terminée",
|
||
action: 'onComplete',
|
||
},
|
||
},
|
||
decorators: [
|
||
(Story) => (
|
||
<div className="max-w-2xl mx-auto p-4 bg-background min-h-layout-page-sm">
|
||
<Story />
|
||
</div>
|
||
),
|
||
],
|
||
};
|
||
|
||
export default meta;
|
||
type Story = StoryObj<typeof meta>;
|
||
|
||
export const Default: Story = {
|
||
name: 'Par défaut',
|
||
};
|
||
|
||
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.',
|
||
},
|
||
},
|
||
},
|
||
};
|
||
|
||
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.',
|
||
},
|
||
},
|
||
},
|
||
};
|
||
|
||
export const Loading: Story = {
|
||
name: 'Chargement',
|
||
render: () => <TwoFactorSetupSkeleton />,
|
||
parameters: {
|
||
docs: {
|
||
description: {
|
||
story: 'Skeleton de l’assistant 2FA (en-tête + cartes méthode).',
|
||
},
|
||
},
|
||
},
|
||
};
|
||
|
||
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 },
|
||
),
|
||
),
|
||
],
|
||
},
|
||
docs: {
|
||
description: {
|
||
story: 'MSW retourne 500 sur POST /auth/2fa/setup. Toast + onBack.',
|
||
},
|
||
},
|
||
},
|
||
};
|