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 🙏

© 2026 – Pkg Stats / Ryan Hefner

@playwright-kit/auth

v0.2.1

Published

Small, production-ready authentication utilities for Playwright.

Readme

@playwright-kit/auth

Infrastructure utilities for managing Playwright storageState auth artifacts before running tests.

  • Users define project-specific auth flows in playwright.auth.config.ts
  • CLI generates .auth/<profile>.json
  • CLI ensure validates and refreshes states before tests (no auto-login during test execution)

Why this package (if Playwright already has storageState)?

Playwright gives you the low-level primitives:

  • Save: context.storageState({ path })
  • Use: test.use({ storageState: "state.json" })
  • Optional: write a custom globalSetup to generate states before a run

This package provides the missing "infrastructure layer" many teams end up building themselves:

  • Multi-profile auth states (admin, user, ...) in one config file
  • Ensure workflow: validate existing states and refresh only when missing/invalid
  • Explicit pre-test step (runs before playwright test, not hidden inside fixtures)
  • Failure artifacts (trace + screenshot) in deterministic locations for CI debugging
  • Optional app startup via webServer so ensure can be self-contained in CI
  • Optional .env loading via --dotenv to keep scripts copy/paste friendly

The "Native Playwright" section below is intentional: it shows that after generation, auth states are plain Playwright storageState files - there's no runtime magic.

Install

npm i -D @playwright-kit/auth

With pnpm:

pnpm add -D @playwright-kit/auth

TL;DR (copy/paste)

  1. Add playwright.auth.config.ts (example below), then:
playwright-kit auth ensure --dotenv
playwright test
  1. In tests, either use native Playwright:
test.use({ storageState: ".auth/admin.json" });

or the wrapper:

import { authTest } from "@playwright-kit/auth";

export const test = authTest({ defaultProfile: "user" });
test.use({ auth: "admin" });

Choose:

  • Native: simplest; you reference .auth/<profile>.json directly.
  • Wrapper: cleaner multi-profile switching via test.use({ auth: "<profile>" }).

What you get

  • Config API: defineAuthConfig(...)
  • CLI: playwright-kit auth setup / playwright-kit auth ensure
  • Test ergonomics: authTest(...) (optional)

Quick start (copy/paste)

1) Add playwright.auth.config.ts

This example supports two profiles: admin and user.

import { defineAuthConfig } from "@playwright-kit/auth";

export default defineAuthConfig({
  baseURL: process.env.BASE_URL ?? "http://127.0.0.1:3000",

  // Optional: have the CLI start your app and wait until it's reachable.
  // Use this in CI (or anytime your app isn't already running).
  // If omitted, the CLI assumes your app is already running at `baseURL`.
  webServer: {
    command: "npm run dev",
    // Optional: extra env for the server process (merged over process.env).
    // env: { PORT: "3000" },
    // Optional; defaults to baseURL when omitted.
    // url: "http://127.0.0.1:3000/login",
  },

  profiles: {
    admin: {
      // Recommended: set validateUrl explicitly for deterministic validation.
      // When omitted, the CLI will fall back to "/".
      validateUrl: "/admin",
      async login(page, { credentials }) {
        await page.goto("/login");
        await page.getByLabel("Email").fill(credentials.email);
        await page.getByLabel("Password").fill(credentials.password);
        await page.getByRole("button", { name: "Sign in" }).click();
      },
      async validate(page) {
        const ok = await page.getByRole("heading", { name: "Admin" }).isVisible();
        return ok ? { ok: true } : { ok: false, reason: "Admin heading not visible" };
      },
    },

    user: {
      // Recommended: set validateUrl explicitly for deterministic validation.
      // When omitted, the CLI will fall back to "/".
      validateUrl: "/me",
      async login(page, { credentials }) {
        await page.goto("/login");
        await page.getByLabel("Email").fill(credentials.email);
        await page.getByLabel("Password").fill(credentials.password);
        await page.getByRole("button", { name: "Sign in" }).click();
      },
      async validate(page) {
        const ok = await page.getByRole("heading", { name: "Me" }).isVisible();
        return ok ? { ok: true } : { ok: false, reason: "Me heading not visible" };
      },
    },
  },
});

2) Provide credentials (env convention)

Default mapping is:

  • AUTH_<PROFILE>_EMAIL
  • AUTH_<PROFILE>_PASSWORD

Where <PROFILE> is uppercased and non-alphanumerics become _ (qa-admin -> QA_ADMIN).

Examples:

  • AUTH_ADMIN_EMAIL, AUTH_ADMIN_PASSWORD
  • AUTH_USER_EMAIL, AUTH_USER_PASSWORD

3) Add scripts to package.json

This keeps tests "pure": auth refresh happens before Playwright tests run.

{
  "scripts": {
    "auth:ensure": "playwright-kit auth ensure --dotenv",
    "pretest": "npm run auth:ensure",
    "test": "playwright test"
  }
}

With pnpm:

{
  "scripts": {
    "auth:ensure": "playwright-kit auth ensure --dotenv",
    "pretest": "pnpm run auth:ensure",
    "test": "playwright test"
  }
}

Now:

npm test

CLI

playwright-kit auth setup

Generate a single profile:

playwright-kit auth setup --profile admin --dotenv

playwright-kit auth ensure

Ensure all profiles from config (default):

playwright-kit auth ensure --dotenv

Ensure a subset:

playwright-kit auth ensure --profile admin --profile user --dotenv

--dotenv / --dotenv-path

Node does not load .env automatically. If you want .env support:

playwright-kit auth ensure --dotenv

Or:

playwright-kit auth ensure --dotenv-path .env.ci

Notes:

  • .env loading is provided via the dotenv package.

Using in tests

Native Playwright

Use this if you prefer the simplest, framework-native approach: you reference the generated storageState file directly. This does not require any @playwright-kit/auth test wrapper.

import { test } from "@playwright/test";

test.use({ storageState: ".auth/admin.json" });

authTest() wrapper (recommended ergonomics)

Use this if you have multiple profiles and want clean switching via test.use({ auth: "user" }) (Playwright-native patterns), while still keeping auth refresh outside of test execution.

Create a single fixtures file and reuse it:

// tests/fixtures.ts
import { authTest } from "@playwright-kit/auth";

export const test = authTest({ defaultProfile: "user" });
export const expect = test.expect;

Usage (default profile):

import { test, expect } from "./fixtures";

test("user by default", async ({ page }) => {
  await page.goto("/me");
  await expect(page.getByTestId("whoami")).toHaveText("user");
});

Switch profile using native Playwright patterns:

import { test, expect } from "./fixtures";

test.use({ auth: "admin" });

test("admin view", async ({ page }) => {
  await page.goto("/admin");
  await expect(page.getByTestId("whoami")).toHaveText("admin");
});

The wrapper never regenerates state; if a state file is missing/invalid it fails with instructions to run playwright-kit auth ensure.

Artifacts

  • Auth states: .auth/<profile>.json
  • Failures: .auth/.failures/<profile>/<runId>/{trace.zip,screenshot.png,error.txt}
  • Locks: .auth/.locks/<profile>.lock (prevents concurrent setup/ensure from overwriting state)

.gitignore

Recommended:

.auth/

When is webServer required?

  • Required when your login() / validate() needs the app UI (via baseURL), but the app is not guaranteed to be running before playwright-kit auth ensure/setup (typical in CI).
  • Not needed if the app is already started externally (docker-compose, separate terminal/job) before running the auth CLI.
  • Recommended for CI to avoid "connection refused" and to keep ensure self-contained and deterministic.