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-labs/fixture-gmail

v0.3.0

Published

Gmail fixture integration for Playwright/test — find, read and send emails via the Gmail API

Downloads

213

Readme

Playwright Gmail support

Gmail fixture for Playwright/test — find, read and send emails straight from your tests via the Gmail API.

test("someTest", async ({ gmail }) => {
  const emails = await gmail.findEmail({ subject: /qwe/ });
  expect(emails).not.toBeNull();

  const body = await gmail.readEmail(emails![0].id);
  expect(body).toContain("123456");
});

Installation

npm i -D @playwright/test @playwright-labs/fixture-gmail
pnpm add -D @playwright/test @playwright-labs/fixture-gmail
yarn add -D @playwright/test @playwright-labs/fixture-gmail

Authentication

The client talks to the Gmail API with an OAuth2 access token. Two setups are supported:

  1. Refresh token (recommended) — the client exchanges it for a short-lived access token and caches it:
    • GMAIL_CLIENT_ID, GMAIL_CLIENT_SECRET, GMAIL_REFRESH_TOKEN
  2. Static access token — used as-is (expires in ~1 hour, fine for local runs):
    • GMAIL_ACCESS_TOKEN

To get a refresh token: create a Google Cloud project, enable the Gmail API, create OAuth2 credentials (web application), then authorize the https://mail.google.com/ scope (e.g. via the OAuth 2.0 Playground with your own client id/secret) and exchange the authorization code for tokens.

Values can also be passed directly via options:

const gmail = useGmail({ clientId, clientSecret, refreshToken });
// or
const gmail = useGmail({ accessToken });

Fixture

  • gmail: Gmail — ready-to-use client configured from the GMAIL_* env variables.
  • useGmail(options?: GmailOptions): Gmail — factory for a client with custom options.
import { test, expect } from "@playwright-labs/fixture-gmail";

test("custom client", async ({ useGmail }) => {
  const gmail = useGmail({ accessToken: process.env.SECOND_ACCOUNT_TOKEN });
  await gmail.sendEmail({ to: "[email protected]", subject: "hi", body: "<h1>hello</h1>" });
});

API

findEmail(options?): Promise<Email[] | null>

Searches the mailbox and returns matching emails (newest first) or null when nothing matches.

| Option | Type | Description | | --------- | ------------------- | --------------------------------------------------------------------------- | | subject | string \| RegExp | String -> Gmail query subject:"...", RegExp -> client-side header filter | | from | string \| RegExp | Sender filter (same rules as subject) | | to | string \| RegExp | Recipient filter (same rules as subject) | | query | string | Raw Gmail search query, e.g. "newer_than:1h has:attachment" | | unread | boolean | Adds is:unread to the query | | limit | number | Max messages to inspect (default 10) |

Email contains id, threadId, subject, from, to, date and snippet — plus bound body readers: email.readAsString(), email.readAsBytes() and email.readAsStream().

readEmail(emailId, options?): Promise<string>

Returns the decoded body of a message. HTML is preferred by default; pass { format: "text" } for plain text. Falls back to the other format when the preferred part is absent.

waitForEmail(options?): Promise<Email>

Polls findEmail until at least one email matches and returns the newest one. Accepts all findEmail options plus timeout (default 30000 ms) and interval (default 1000 ms). Throws when nothing matches within the timeout.

const email = await gmail.waitForEmail({ to: user.email, subject: /verify/i });

getEmailLinks(emailId): Promise<string[]>

Reads the email's HTML body and returns all unique href values — handy for confirmation/reset links:

const [confirmUrl] = await gmail.getEmailLinks(email.id);
await page.goto(confirmUrl!);

markAsRead(emailId): Promise<void>

Marks a message as read (removes the UNREAD label via users.messages.modify). Requires the gmail.modify scope.

sendEmail(options): Promise<{ id, threadId }>

await gmail.sendEmail({
  to: ["[email protected]", "[email protected]"],
  cc: "[email protected]",
  bcc: "[email protected]",
  subject: "Test report",
  body, // HTML string
  attachments: [{ filename: "report.html", path: "playwright-report/index.html" }],
});

attachments follow the nodemailer Attachment shape — filename, content (string | Buffer | base64), path, href, contentType, and cid for inline images.

Body primitives

The package re-exports the same string HTML primitives as @playwright-labs/reporter-email — every helper returns a string, so they compose by plain nesting:

h, fragment, html, head, title, body, div, p, a, img, ul, li, table, thead, tbody, tr, td, th, h1h6, br, hr.

import { div, fragment, h1, table, tbody, td, thead, tr, img } from "@playwright-labs/fixture-gmail";

const body = div(
  fragment(
    h1("Playwright Test Report"),
    table(
      fragment(
        thead(tr(fragment(td("Test"), td("Status")))),
        tbody(tr(fragment(td("login.spec.ts"), td("passed")))),
      ),
    ),
    img({ src: "cid:logo" }), // inline image from attachments
  ),
);

await gmail.sendEmail({
  to: "[email protected]",
  subject: "Report",
  body,
  attachments: [{ path: "./logo.png", cid: "logo" }],
});

License

MIT