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

@manufac/general-tests

v0.10.1

Published

A library for general tests for landing pages

Readme

@manufac/general-tests

Shared Playwright regression suite for landing pages, built from the Landing Page Test Plan. It ships generic, page-agnostic checks (page load, responsive layout, forms, CTAs/links, media, orientation, touch targets, etc.) that any landing-page app in the monorepo can run against its own pages.

See CHANGELOG.md for release notes.

Consuming from an app

Add it as a normal dependency, pinned to the version you want to consume:

npm install @manufac/general-tests

Then wire it into the app's playwright.config.ts.

First, declare the app-specific pages in a small local config file, typed against ManufacTestConfig:

// manufac-test.config.ts
import type { ManufacTestConfig } from "@manufac/general-tests/schema/index.js";

export const Config: ManufacTestConfig = {
  pages: ["/", "/pricing", "/contact-us", "/privacy"],
};

Then reference it from playwright.config.ts:

import { defineConfig, devices } from "@playwright/test";
import { dirname, join } from "node:path";
import {
  DesktopBreakpoints,
  ResponsiveLayoutBreakpoints,
  LoadingPageTestMatch,
  ResponsiveLayoutTestMatch,
} from "@manufac/general-tests/config/projects.js";
import type { PageTestOptions } from "@manufac/general-tests/fixtures/index.js";
import type { Project } from "@playwright/test";
import { Config } from "./manufac-test.config.js";

// Resolves to node_modules/@manufac/general-tests/dist/specs, wherever it's installed from.
const GeneralTestsSpecsDir = join(dirname(require.resolve("@manufac/general-tests/config/projects.js")), "..", "specs");

const Projects: Project[] = [
  {
    name: "Desktop Chrome",
    testDir: GeneralTestsSpecsDir,
    testMatch: [LoadingPageTestMatch, ResponsiveLayoutTestMatch],
    use: { ...devices["Desktop Chrome"], viewport: DesktopBreakpoints.Desktop },
  },
  {
    name: "Desktop Safari",
    testDir: GeneralTestsSpecsDir,
    testMatch: [LoadingPageTestMatch, ResponsiveLayoutTestMatch],
    use: { ...devices["Desktop Safari"], viewport: DesktopBreakpoints.Desktop },
  },
  {
    name: "Desktop Firefox",
    testDir: GeneralTestsSpecsDir,
    testMatch: [LoadingPageTestMatch, ResponsiveLayoutTestMatch],
    use: { ...devices["Desktop Firefox"], viewport: DesktopBreakpoints.Desktop },
  },
  {
    name: "Responsive 375",
    testDir: GeneralTestsSpecsDir,
    testMatch: ResponsiveLayoutTestMatch,
    use: { ...devices["Desktop Chrome"], viewport: ResponsiveLayoutBreakpoints.MobileL },
  },
  {
    name: "Responsive 768",
    testDir: GeneralTestsSpecsDir,
    testMatch: ResponsiveLayoutTestMatch,
    use: { ...devices["Desktop Chrome"], viewport: ResponsiveLayoutBreakpoints.Tablet },
  },
];

export default defineConfig<PageTestOptions>({
  testDir: "./e2e",
  use: {
    baseURL: "https://your-app.example.com",
    pages: Config.pages,
  },
  projects: Projects,
});
  • LoadingPageTestMatch runs loading-page.spec.ts — page-load/console-error/network checks, once per project, over every page in Config.pages.
  • ResponsiveLayoutTestMatch runs responsive-layout.spec.ts — checked at whichever viewport each project sets, so add one project per breakpoint you care about (ResponsiveLayoutBreakpoints.MobileL / .Tablet / .Desktop).
  • require.resolve + join(..., "..", "specs") finds the package's built specs directory regardless of how it's installed (registry, file:, or a vendored tarball) — testDir must point there since these two spec files aren't re-exported any other way.
  • PageTestOptions (from fixtures/index.js) types the use block so pages (and forms, if you set it) are checked against the fixture's actual shape.

Storybook visual regression

VisualRegressionTestMatch runs visual-regression.spec.ts — a single generic test that walks every story in a running Storybook instance and compares it against a baseline screenshot with Playwright's toHaveScreenshot(). No per-component spec files are needed; new stories are picked up automatically.

It needs its own Playwright config, separate from the one above, since it runs against Storybook's dev server instead of the app itself:

// playwright.storybook.config.ts
import { defineConfig, devices } from "@playwright/test";
import { dirname, join } from "node:path";
import { VisualRegressionTestMatch } from "@manufac/general-tests/config/projects.js";

const GeneralTestsSpecsDir = join(dirname(require.resolve("@manufac/general-tests/config/projects.js")), "..", "specs");

export default defineConfig({
  testDir: GeneralTestsSpecsDir,
  testMatch: VisualRegressionTestMatch,
  // Relative, so Playwright resolves it against this config file's own directory (not
  // testDir, which points into the installed package) — baselines stay in this repo.
  snapshotPathTemplate: "e2e-visual/__screenshots__/{arg}{ext}",
  reporter: [["html", { open: "never" }]],
  expect: { toHaveScreenshot: { maxDiffPixelRatio: 0.001, animations: "disabled" } },
  use: { ...devices["Desktop Chrome"], viewport: { width: 1366, height: 768 }, baseURL: "http://localhost:6006" },
  webServer: {
    command: "npm run start:sb -- --ci --port 6006",
    url: "http://localhost:6006",
    reuseExistingServer: true,
  },
});

Then add two scripts to the app's package.json (adjust start:sb/build:sb to however the app runs Storybook):

{
  "scripts": {
    "test:visual": "npm run build:sb && playwright test -c playwright.storybook.config.ts",
    "update:visual": "npm run build:sb && playwright test -c playwright.storybook.config.ts --update-snapshots"
  }
}

Baselines land in e2e-visual/__screenshots__/<story-id>.png, next to playwright.storybook.config.ts.

Full-page visual regression

PageVisualRegressionTestMatch runs page-visual-regression.spec.ts — one generic test that visits every page in Config.pages and compares a full-page screenshot against a saved baseline with toHaveScreenshot(). A page path becomes the snapshot name by trimming slashes (/ -> home, /pricing -> pricing, /docs/setup -> docs-setup). Failures are collected, so one broken page doesn't hide the others.

Setup

Run it in its own project, so it starts only after the other projects finish. Full-page screenshots of long pages are slow and sensitive to load, and running them next to other tests makes them flaky. Projects that list each other in dependencies run one after another, so only one visual project runs at a time.

import { LoadingPageTestMatch, PageVisualRegressionTestMatch } from "@manufac/general-tests/config/projects.js";

const Projects: Project[] = [
  {
    name: "Desktop Chrome",
    testDir: GeneralTestsSpecsDir,
    testMatch: [LoadingPageTestMatch],
    use: { ...devices["Desktop Chrome"], viewport: DesktopBreakpoints.Desktop },
  },
  {
    name: "Desktop Chrome Visual",
    testDir: GeneralTestsSpecsDir,
    testMatch: PageVisualRegressionTestMatch,
    dependencies: ["Desktop Chrome"],
    snapshotPathTemplate: "e2e/__screenshots__/Desktop-Chrome/{arg}{ext}",
    use: { ...devices["Desktop Chrome"], viewport: DesktopBreakpoints.Desktop },
  },
  {
    // Chain the next visual project onto the previous one.
    name: "Responsive 375 Visual",
    testDir: GeneralTestsSpecsDir,
    testMatch: PageVisualRegressionTestMatch,
    dependencies: ["Desktop Chrome Visual"],
    snapshotPathTemplate: "e2e/__screenshots__/Responsive-375/{arg}{ext}",
    use: { ...devices["Desktop Chrome"], viewport: ResponsiveLayoutBreakpoints.MobileL },
  },
];

export default defineConfig<PageTestOptions>({
  testDir: "./e2e",
  expect: { timeout: 10_000, toHaveScreenshot: { maxDiffPixelRatio: 0.001, animations: "disabled" } },
  use: { baseURL: "https://your-app.example.com", pages: Config.pages, actionTimeout: 10_000 },
  projects: Projects,
});
  • Each visual project has its own snapshotPathTemplate, so baselines are kept per project (Desktop Chrome and 375 differ in layout) and stay in the repo.
  • The image and video waits have no timeout of their own. They use use.actionTimeout, so one stuck image fails that page instead of hanging the suite.
  • workers is a global Playwright setting and can't be set per project. Chaining the projects gives the same result for the visual ones, because each has a single test and only one project runs at a time.
  • If a project in dependencies fails, the visual projects are skipped. Use --no-deps to run them on their own.

Scripts

{
  "scripts": {
    "test:visual:pages": "playwright test page-visual-regression --no-deps --workers=1 --project=\"* Visual\"",
    "update:visual:pages": "npm run test:visual:pages -- --update-snapshots=all"
  }
}
  • The first run has no baselines, so use update:visual:pages.
  • Use --update-snapshots=all to rewrite every baseline. A plain --update-snapshots only rewrites the ones that fail the comparison, so old files can stay behind.
  • Review the new images before committing them. Check that the header is at the top and the video area is a solid box.
  • Don't run two Playwright runs at once in the same app. They share test-results, and one run can delete the other's files.

CTA & link destination checks

CTADestinationsTestMatch runs cta-destinations.spec.ts — CT-01 clicks each configured CTA and verifies it lands on its expected destination (same tab by default, or a new tab when opensInNewTab is set); CT-02 visits every internal link reachable from Config.pages and checks it isn't a 404 or blank page, then verifies each configured legal link still points to its expected URL.

Both are driven entirely by config, since the shared package has no way to know an individual app's design spec on its own:

// manufac-test.config.ts
import type { ManufacTestConfig } from "@manufac/general-tests/schema/index.js";

export const Config: ManufacTestConfig = {
  pages: ["/", "/pricing", "/contact-us", "/privacy"],
  ctas: [
    { ctaID: "hero-cta", page: "/", name: "Get Started", expectedHref: "/contact-us" },
    { ctaID: "pricing-cta", page: "/pricing", name: "Book a demo", expectedHref: "/contact-us", opensInNewTab: true },
  ],
  legalLinks: [{ page: "/", name: "Privacy Policy", expectedHref: "/privacy" }],
};

Add CTADestinationsTestMatch to a project's testMatch the same way as LoadingPageTestMatch. CT-01 skips entirely if ctas is left empty.