npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

pw-otp-client

v1.0.0

Published

OTP code retrieval from SMS for Playwright e2e tests

Readme

Playwright OTP Client

npm version License: MIT TypeScript Playwright

A versatile NPM package for retrieving One-Time Password (OTP) codes from SMS messages in Playwright-based E2E UI tests.

Features

  • 🚀 Easily retrieve SMS OTP codes in your Playwright tests
  • 🔄 Multiple SMS providers supported:
  • 🧩 Modular architecture with clean provider abstractions
  • 🔧 Simple configuration through constructor options
  • ⚙️ Comprehensive test coverage

Installation

npm install pw-otp-client --save-dev

Quick Start

import { test, expect } from "@playwright/test";
import { PlaywrightOtpClient } from "pw-otp-client";

test("login with OTP", async ({ page }) => {
  // Initialize the OTP client with MailSlurp (default provider)
  const otpClient = new PlaywrightOtpClient({
    providerConfig: {
      apiKey: process.env.MAILSLURP_API_KEY,
    },
  });

  await otpClient.initialize();

  // Get a phone number for receiving SMS
  const phoneNumber = await otpClient.getPhoneNumber();

  // Navigate to your application and submit the phone number
  await page.goto("https://your-app.com/login");
  await page.fill("#phone-input", phoneNumber);
  await page.click("#send-otp-button");

  // Wait for the OTP code to arrive via SMS
  const otpCode = await otpClient.getOtpCode(phoneNumber);

  // Enter the OTP code in your application
  await page.fill("#otp-input", otpCode);
  await page.click("#verify-button");

  // Verify successful login
  await expect(page.locator(".welcome-message")).toBeVisible();

  // Clean up
  await otpClient.cleanup();
});

SMS Provider Setup Guide

MailSlurp (Default)

Getting API Key

  1. Create an account:

  2. Get your API key:

    • Log in to your MailSlurp dashboard
    • Navigate to "API Keys" section
    • Copy your API key or generate a new one
  3. Configure in your tests:

import { PlaywrightOtpClient } from "pw-otp-client";

const otpClient = new PlaywrightOtpClient({
  provider: "mailslurp", // optional, this is the default
  providerConfig: {
    apiKey: "your-mailslurp-api-key",
  },
});

Phone Number Setup

With MailSlurp, the library will:

  1. First try to use existing phone numbers in your account
  2. If no numbers exist, attempt to create a new one (requires paid plan)

Environment Variables

Add to your .env file:

MAILSLURP_API_KEY=your_mailslurp_api_key_here

Common Issues and Solutions

| Issue | Solution | | ---------------------------- | ----------------------------------------------------------------------------------- | | "Failed to get phone number" | Verify your API key is correct and your account has SMS enabled | | "No SMS message received" | Ensure your test app is sending messages to the correct phone number | | Phone number creation fails | Check if your MailSlurp plan supports SMS (free tier has limited SMS functionality) | | Timeout waiting for OTP | Increase the timeout parameter in getOtpCode method |

Twilio

Getting API Credentials

  1. Create an account:

    • Sign up at Twilio
    • Complete the verification process
  2. Get your credentials:

    • From your Twilio dashboard, find your Account SID and Auth Token
    • These are located on your Twilio Console home page
  3. Set up phone number:

    • Purchase a phone number from the Twilio Console
    • Make sure the number can receive SMS messages
  4. Configure in your tests:

import { PlaywrightOtpClient } from "pw-otp-client";

const otpClient = new PlaywrightOtpClient({
  provider: "twilio",
  providerConfig: {
    accountSid: "your-twilio-account-sid",
    authToken: "your-twilio-auth-token",
    fromPhoneNumber: "+12345678900", // Your Twilio phone number
  },
});

Phone Number Management

Unlike MailSlurp and Mailosaur, Twilio requires you to:

  1. Purchase phone numbers manually through their console
  2. Provide the number in your configuration
  3. Ensure your account has sufficient funds for SMS reception

Environment Variables

Add to your .env file:

TWILIO_ACCOUNT_SID=your_twilio_account_sid_here
TWILIO_AUTH_TOKEN=your_twilio_auth_token_here
TWILIO_FROM_PHONE_NUMBER=+12345678900

Common Issues and Solutions

| Issue | Solution | | --------------------------- | ---------------------------------------------------------------------- | | Authentication failed | Double-check your Account SID and Auth Token | | "No phone number available" | Specify a fromPhoneNumber in the provider config | | SMS delivery failures | Ensure the phone number is correctly formatted with country code | | Rate limiting | Twilio has API rate limits - add backoff logic for high-volume testing | | Billing issues | Verify your Twilio account has sufficient credit |

Mailosaur

Getting API Key and Server ID

  1. Create an account:

    • Sign up at Mailosaur
    • Create a new server from your dashboard
  2. Get your API key:

    • Go to API tab in your Mailosaur dashboard
    • Copy your API key
  3. Get your server ID:

    • Select your server from the dashboard
    • Copy the server ID from the URL or server settings
  4. Configure in your tests:

import { PlaywrightOtpClient } from "pw-otp-client";

const otpClient = new PlaywrightOtpClient({
  provider: "mailosaur",
  providerConfig: {
    apiKey: "your-mailosaur-api-key",
    serverId: "your-mailosaur-server-id",
    phoneCountryCode: "US", // Optional, defaults to 'US'
  },
});

Phone Number Setup

Mailosaur will:

  1. Check for existing SMS numbers on your server
  2. If no numbers exist, attempt to create a new one (requires appropriate plan)
  3. Return the phone number for testing

Environment Variables

Add to your .env file:

MAILOSAUR_API_KEY=your_mailosaur_api_key_here
MAILOSAUR_SERVER_ID=your_mailosaur_server_id_here

Common Issues and Solutions

| Issue | Solution | | ------------------------------------ | ----------------------------------------------------- | | "API key and server ID are required" | Ensure both values are provided in your configuration | | "Failed to create SMS number" | Check if your plan includes SMS functionality | | No SMS detected | Verify the server has SMS capability enabled | | Message searching fails | Check if your server exists and is active | | OTP extraction failure | Try increasing timeout or check the message format |

Sending and Receiving SMS Messages

Sending Test Messages

For testing your OTP client setup without integrating with your actual application:

Using Twilio for Sending Test Messages

import twilio from "twilio";

async function sendTestSMS(to: string, message: string) {
  const client = twilio(
    process.env.TWILIO_ACCOUNT_SID,
    process.env.TWILIO_AUTH_TOKEN
  );

  try {
    const message = await client.messages.create({
      body: `Your verification code is: 123456`,
      from: process.env.TWILIO_FROM_PHONE_NUMBER,
      to: to,
    });

    console.log(`Message sent with SID: ${message.sid}`);
    return true;
  } catch (error) {
    console.error("Error sending test message:", error);
    return false;
  }
}

// Example usage
const phoneNumber = await otpClient.getPhoneNumber();
await sendTestSMS(phoneNumber, "Your verification code is: 123456");
const otpCode = await otpClient.getOtpCode(phoneNumber);
console.log(`Received OTP code: ${otpCode}`); // Should output: 123456

Receiving and Parsing Messages

The OTP client handles message receiving and parsing automatically, but here's what happens behind the scenes:

  1. Message Polling:

    • The client polls the SMS provider API at regular intervals
    • For Twilio and Mailosaur, this is approximately every 2 seconds
    • For MailSlurp, it uses the waitForLatestSms API when available
  2. OTP Extraction:

    • The client uses various regex patterns to extract OTP codes
    • Default pattern looks for 4-8 digits after words like "code", "код", "otp", etc.
    • Fallback patterns are used if the default pattern doesn't match
  3. Timeout Handling:

    • If no OTP is received within the timeout period, an error is thrown
    • Default timeout is 30 seconds but can be configured

Troubleshooting

General Issues

  1. No OTP code received:

    • Verify the SMS was actually sent by your application
    • Check if the phone number format is correct (international format with country code)
    • Increase the timeout parameter (some providers or networks may be slow)
    • Check provider account for any delivery issues or logs
  2. Wrong OTP extracted:

    • If the wrong digits are being extracted, provide a custom regex pattern:
// Direct use of OTP extractor with custom pattern
import { OtpExtractor } from "pw-otp-client";

// Extract using a custom pattern that matches exactly 6 digits after "code:"
const message = "Your verification code: 123456";
const otpCode = OtpExtractor.extractOtp(message, /code:\s*(\d{6})/i);
  1. Provider API errors:
    • Make sure your internet connection is stable
    • Check if provider services are operational
    • Verify your API credentials are current (some providers rotate keys)
    • Check if you've exceeded API rate limits or account quotas

Debugging Tips

  1. Enable verbose logging:

    // Add this before using the OTP client
    process.env.DEBUG = "pw-otp-client:*";
  2. Manual message checking:

    • Log in to your provider's dashboard to verify message delivery
    • Check if messages are being delivered but not matched by the OTP extraction
  3. Network issues:

    • If testing behind corporate firewalls, ensure outbound connections to provider APIs are permitted
    • Check if proxy configuration is needed for your environment

Custom SMS Provider

You can implement your own SMS provider by implementing the ISmsProvider interface:

import {
  PlaywrightOtpClient,
  ISmsProvider,
  BaseSmsProvider,
} from "pw-otp-client";

class MyCustomSmsProvider extends BaseSmsProvider implements ISmsProvider {
  constructor(config: any) {
    super(config);
  }

  async initialize(): Promise<void> {
    // Initialize your SMS provider
  }

  async getPhoneNumber(): Promise<string> {
    // Get a phone number for receiving SMS
    return "+1234567890";
  }

  async waitForOtpCode(phoneNumber: string, timeout?: number): Promise<string> {
    // Wait for and extract OTP code from SMS
    return "123456";
  }

  async cleanup(): Promise<void> {
    // Clean up resources
  }
}

// Use your custom provider
const otpClient = new PlaywrightOtpClient({
  provider: "custom",
  customProvider: new MyCustomSmsProvider({
    // Your custom config
  }),
});

API Reference

PlaywrightOtpClient

The main class for interacting with SMS providers and retrieving OTP codes.

Constructor Options

interface OtpClientConfig {
  provider?: "mailslurp" | "twilio" | "mailosaur" | "custom";
  providerConfig?: any;
  customProvider?: ISmsProvider;
  timeout?: number; // Default: 30000 (30 seconds)
}

Methods

  • initialize(): Initialize the OTP client
  • cleanup(): Clean up resources used by the client
  • getPhoneNumber(): Get a phone number for receiving SMS
  • getOtpCode(phoneNumber?, timeout?): Wait for and extract OTP code from SMS
  • getPhoneNumberAndOtpCode(timeout?): Convenience method to get both phone number and OTP code

CI Integration

To use this package in CI environments, you'll need to provide your SMS provider API credentials as environment variables.

GitHub Actions Example

name: E2E Tests

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  test:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v3
      - name: Setup Node.js
        uses: actions/setup-node@v3
        with:
          node-version: "18"
      - name: Install dependencies
        run: npm ci
      - name: Install Playwright browsers
        run: npx playwright install --with-deps
      - name: Run Playwright tests
        env:
          MAILSLURP_API_KEY: ${{ secrets.MAILSLURP_API_KEY }}
          # Add other provider keys as needed
        run: npx playwright test

Environment Variables

Create a .env file in your project (and add it to .gitignore):

# MailSlurp configuration
MAILSLURP_API_KEY=your_mailslurp_api_key_here

# Twilio configuration
TWILIO_ACCOUNT_SID=your_twilio_account_sid_here
TWILIO_AUTH_TOKEN=your_twilio_auth_token_here
TWILIO_FROM_PHONE_NUMBER=+12345678900  # Optional

# Mailosaur configuration
MAILOSAUR_API_KEY=your_mailosaur_api_key_here
MAILOSAUR_SERVER_ID=your_mailosaur_server_id_here

Then in your tests:

import dotenv from "dotenv";
dotenv.config();

const otpClient = new PlaywrightOtpClient({
  provider: "mailslurp",
  providerConfig: {
    apiKey: process.env.MAILSLURP_API_KEY,
  },
});

License

MIT © 2023-2024 Alex Bobyr

See LICENSE for more information.