Authentication

OTP verification

Six-digit code modal validates length, supports paste, and rejects expired codes.

User story

As a user signing in from a new device, I want to enter a one-time code so my account stays protected.

Acceptance criteria

  • Six independent inputs auto-advance focus on each digit
  • Pasting a 6-digit value distributes across all inputs
  • Verify is disabled until all 6 inputs are filled
  • Expired code shows a recoverable error

Manual test steps

  1. 1.Trigger OTP modal from registration
  2. 2.Paste 123456 into the first input
  3. 3.Click Verify
  4. 4.Confirm dashboard land

Expected result

Pasting 123456 fills all 6 inputs and the Verify button enables.

Possible bug risks

  • Paste drops digits when first input has focus mid-type
  • Verify can be invoked via keyboard while disabled
  • Resend button has no cooldown timer

Reference Playwright spec

otp-verification.spec.ts
ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
import { test, expect } from '@playwright/test';

test('otp paste fills six fields @smoke', async ({ page }) => {
  await page.goto('https://lab.hakdogan.com/register');
  // open the OTP modal via the demo flow
  await page.getByRole('button', { name: /continue to verification/i }).click();

  const first = page.locator('#otp-0');
  await first.focus();
  await page.keyboard.insertText('123456');

  await page.getByRole('button', { name: /^verify$/i }).click();
  await expect(page).toHaveURL(/\/dashboard$/);
});