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

nu-sl2t

v1.0.0

Published

nuances' Liquid Testing Tool

Readme

Liquid Testing Tool

Render Shopify Liquid sections/snippets in a real browser and test them with Playwright. Your theme’s JS (TypeScript) and CSS (Tailwind) are loaded globally so components behave like in production.

Requirements

  • Node 20+
  • Bun (to run the dev server commands)
  • Playwright browsers (first run):
    • npx playwright install

Install (in your Shopify theme)

pnpm add -D liquid-testing-tool @playwright/test
# one-time (per machine)
npx playwright install
# recommended runtime for the dev server (optional but suggested)
brew install oven-sh/bun/bun

Configure

Create liquidtest.config.mjs in your repo:

export default {
  entries: {
    css: ['/assets/main.css'],
    js: ['/assets/main.ts']
  },
  theme: {
    // optional; defaults to [process.cwd()]
    // roots: [process.cwd()]
  },
  server: {
    port: 5175,
    useVite: true,                 // JIT TS + Tailwind via Vite middleware
    rootContainerSelector: '#__liquidtest-root'
  }
};

Commands

  • Start dev server and browse manually:
liquidtest dev ./liquidtest.config.mjs
# open http://localhost:5175
  • Or via Playwright (webServer) it will auto-start (see below).
  • Run E2E tests:
pnpm test          # headless
pnpm test:e2e:headed
pnpm test:e2e:ui   # Playwright UI mode

Writing tests

Encode a render payload into a single GET param p (base64url JSON). Use the helper to do this for you.

Example (Playwright):

// tests/utils.ts
import type { Locator, Page } from '@playwright/test';
import type { LiquidRenderPayload } from 'liquid-testing-tool';

export async function prepareLiquidTest(page: Page, input: LiquidRenderPayload) {
  const payload: LiquidRenderPayload = 'component' in input
    ? { component: input.component, context: input.context }
    : { components: input.components, context: input.context };
  const json = JSON.stringify(payload);
  const b64 = Buffer.from(json).toString('base64').replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
  const url = `/render?p=${b64}`;
  await page.goto(url);
  const testContainer: Locator = page.locator('#__liquidtest-root');
  return { testContainer };
}

// tests/render.spec.ts
import { test, expect } from '@playwright/test';
import { prepareLiquidTest } from './utils';

test('render single component', async ({ page }) => {
  const { testContainer } = await prepareLiquidTest(page, {
    component: 'sections/hello.liquid',
    context: { section: { settings: { heading: 'Hello' } } },
  });
  await expect(testContainer.locator('.title')).toHaveText(/Hello/);
});

test('render multiple components in order', async ({ page }) => {
  const { testContainer } = await prepareLiquidTest(page, {
    components: [
      { component: 'sections/hello.liquid', context: { section: { settings: { heading: 'First' } } } },
      { component: 'sections/hello.liquid', context: { section: { settings: { heading: 'Second' } } } },
    ],
    context: { globals: { locale: 'en' } },
  });
  await expect(testContainer.locator('.title')).toHaveCount(2);
});

How it works

  • Dev server exposes /render?p=....
  • Payload supports either { component, context } or { components: [...], context }.
  • Context is merged: global context then per-item context.
  • HTML shell is in src/server/shell.html; CSS/JS entries are injected for every page.

Web components / external JS

  • With useVite: true, TypeScript is JIT-transpiled and Tailwind runs via your local config.
  • Your main.ts registers web components and third-party libs; they’re available in tests and when browsing pages.

Playwright integration (webServer)

Add playwright.config.ts to auto-start the server for tests.

import { defineConfig, devices } from '@playwright/test';

export default defineConfig({
  testDir: './tests-e2e',
  use: { baseURL: 'http://localhost:5175' },
  projects: [{ name: 'chromium', use: { ...devices['Desktop Chrome'] } }],
  webServer: {
    command: 'liquidtest dev ./liquidtest.config.mjs',
    url: 'http://localhost:5175/health',
    reuseExistingServer: true,
    timeout: 30000
  }
});

Roadmap / Notes

  • Optional HTML normalization (serializer) for stable text/snapshot assertions.
  • Broader Shopify Liquid coverage (image filters, URL helpers, money, etc.).
  • Visual snapshot testing with Playwright (optional).

Reference