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

iitc-kuku-plugin-tester

v1.1.0

Published

Test environment for IITC plugins

Readme

IITC Plugin Tester

A test harness for IITC (Ingress Intel Total Conversion) plugins. It boots IITC in a real headless Chromium browser and lets you assert plugin behaviour and take screenshots without needing a Niantic account or internet access.

screenshot

How it works

IITC normally runs as a userscript injected into intel.ingress.com. It requires:

  • A logged-in Niantic session (window.PLAYER)
  • Specific minified globals for tile parameters (extractFromStock())
  • Map tile images from CartoDB / Google Maps
  • Ingress API endpoints (POST /r/*)

This project provides all of that as local mocks:

| Component | What it does | |---|---| | server/index.ts | Express server on localhost:3000 | | server/routes/intel-page.ts | Serves a fake intel.ingress.com HTML page with mock globals and inline plugin code | | server/routes/api.ts | Handles POST /r/* Ingress API calls with fixture data | | server/routes/tiles.ts | Serves pre-fetched OSM map tiles from server/fixtures/tiles/; returns a blank tile for any uncached request | | server/fixtures/ | JSON responses for game score, entities, and player data; pre-fetched PNG tiles | | iitc/total-conversion-build.js | The IITC built script (downloaded from the official release, not included) | | plugins/ | Drop plugin .js files here for standalone development -- auto-embedded at boot | | tests/test-plugin.js | Built-in boot-signal plugin (sets data-iitc-fully-loaded, always loaded last) | | tests/helpers/iitc-page.ts | Playwright route interceptions for tiles and fonts | | tests/iitc-loads.spec.ts | Built-in boot verification test with visual screenshot comparison | | tests/entities.spec.ts | Built-in test verifying fake portals, links, and fields for all factions | | tests/screenshots/iitc-loaded.png | Baseline screenshot for visual regression | | scripts/fetch-tiles.js | One-time script to download and cache OSM tiles for the screenshot area |

Non-obvious detail: plugin injection

IITC replaces document.body during boot. Any <script src> tags placed after the IITC script in the HTML end up inserted into the now-detached old body node, which browsers refuse to execute. To work around this, the server reads every .js file from the plugins directory and embeds the code inline in a <script> block that runs before the IITC script. Each plugin pushes its setup() function onto window.bootPlugins, and IITC's boot() calls them once it is fully initialised.

Map tiles

Map tiles are served from server/fixtures/tiles/{z}/{x}/{y}.png. These are real OSM tiles pre-fetched for the default screenshot area (zoom 15, centre 51.5068/-0.1278). Any tile request outside the cached set receives a blank transparent PNG so tests never make real network requests.

To refresh the tile cache after changing the map centre or zoom level:

node scripts/fetch-tiles.js

Quick start (local plugin development)

1. Install

npm install --save-dev iitc-kuku-plugin-tester @playwright/test
npx playwright install chromium

2. Download the IITC script

IITC_VERSION=0.42.2
mkdir -p iitc
curl -sSLo /tmp/iitc.zip \
  "https://github.com/IITC-CE/ingress-intel-total-conversion/releases/download/${IITC_VERSION}/release-${IITC_VERSION}.zip"
unzip -p /tmp/iitc.zip total-conversion-build.user.js > iitc/total-conversion-build.js

Or let the CLI download it for you (see --iitc-version below).

3. Run against your plugin

# Headless
npx iitc-plugin-tester --plugin dist/my-plugin.js

# With a visible browser window
npx iitc-plugin-tester --plugin dist/my-plugin.js -- --headed

# Auto-download a specific IITC version
npx iitc-plugin-tester --plugin dist/my-plugin.js --iitc-version 0.42.2

The command prints a Playwright summary. A Playwright HTML report is written to playwright-report/ and can be opened with:

npx playwright show-report

4. Update the screenshot baseline

On the first run (or after an intentional visual change) the baseline screenshot does not exist yet and the visual test will fail. Regenerate it with:

npx iitc-plugin-tester --plugin dist/my-plugin.js -- --update-snapshots

Commit the resulting tests/screenshots/iitc-loaded.png alongside your plugin.


Usage as an installable package (recommended for CI)

1. Install

npm install --save-dev iitc-kuku-plugin-tester @playwright/test
npx playwright install chromium

2. Provide the IITC built script

The IITC script is not bundled. See Downloading the IITC script below for how to get it in CI or locally.

3. Run

npx iitc-plugin-tester --plugin dist/my-plugin.js

The CLI:

  1. Stages the plugin (and any declared dependencies) into a temporary directory in the correct load order
  2. Starts the mock Express server
  3. Runs Playwright against it
  4. Cleans up

CLI options

| Option | Description | |---|---| | --plugin <path> | Required. Path to the plugin file under test | | --dep <path> | A dependency plugin to load before the plugin under test. Repeatable. | | --iitc-version <ver> | Auto-download this IITC release and test against it. Repeatable. | | --iitc-dir <path> | Use a pre-downloaded IITC directory. Repeatable. | | --cache-dir <path> | Where to cache downloaded IITC scripts (default: ~/.cache/iitc-kuku-plugin-tester) | | --port <number> | Server port (default: 3000) | | -- | Everything after -- is forwarded to Playwright (e.g. -- --headed) |

When --iitc-version or --iitc-dir are given more than once, the full test suite is run once per version and the process exits non-zero if any version fails.

Examples:

# Basic -- uses ./iitc/total-conversion-build.js
npx iitc-plugin-tester --plugin dist/my-plugin.js

# Auto-download a specific version
npx iitc-plugin-tester --plugin dist/my-plugin.js --iitc-version 0.42.2

# Test against multiple versions (downloaded automatically and cached)
npx iitc-plugin-tester --plugin dist/my-plugin.js \
  --iitc-version 0.42.2 \
  --iitc-version 0.43.0

# Pre-downloaded directories
npx iitc-plugin-tester --plugin dist/my-plugin.js \
  --iitc-dir vendor/iitc-0.42.2 \
  --iitc-dir vendor/iitc-0.43.0

# With dependencies
npx iitc-plugin-tester --plugin dist/my-plugin.js \
  --dep node_modules/iitc-plugin-lib/dist/lib.js

# Run headed for debugging
npx iitc-plugin-tester --plugin dist/my-plugin.js -- --headed

Config file

Instead of (or in addition to) CLI flags, create iitc-tester.config.json in your project root:

{
  "plugin": "./dist/my-plugin.js",
  "dependencies": [
    "./node_modules/iitc-plugin-lib/dist/lib.js"
  ],
  "iitcVersions": ["0.42.2", "0.43.0"]
}

CLI flags take precedence over the config file.

All IITC version fields are mutually exclusive; precedence is iitcVersions > iitcDirs > iitcDir.

Declaring plugin dependencies

If your plugin requires other IITC plugins to be loaded first, list them under dependencies. They are staged and loaded in declaration order, before the plugin under test:

load order: dep[0] -> dep[1] -> ... -> your plugin -> test-plugin.js (boot signal)

Downloading the IITC script

IITC releases are published on GitHub: IITC-CE/ingress-intel-total-conversion/releases. Each release ZIP contains total-conversion-build.user.js.

Auto-download (easiest)

Pass --iitc-version and the CLI downloads, extracts, and caches the release automatically:

npx iitc-plugin-tester --plugin dist/my-plugin.js --iitc-version 0.42.2

Downloaded scripts are cached in ~/.cache/iitc-kuku-plugin-tester/<version>/ so subsequent runs are instant. Override with --cache-dir or IITC_CACHE_DIR.

The steps below are for cases where you prefer to manage the download yourself (e.g. to pre-warm a CI layer cache keyed to a Docker image).

Pin a specific version (recommended for reproducible builds)

IITC_VERSION=0.42.2
mkdir -p iitc
curl -sSL "https://github.com/IITC-CE/ingress-intel-total-conversion/releases/download/${IITC_VERSION}/release-${IITC_VERSION}.zip" \
  | python3 -c "import sys,zipfile,io; z=zipfile.ZipFile(io.BytesIO(sys.stdin.buffer.read())); sys.stdout.buffer.write(z.read('total-conversion-build.user.js'))" \
  > iitc/total-conversion-build.js

Or with unzip if you prefer to download first:

IITC_VERSION=0.42.2
curl -sSLo /tmp/iitc.zip \
  "https://github.com/IITC-CE/ingress-intel-total-conversion/releases/download/${IITC_VERSION}/release-${IITC_VERSION}.zip"
mkdir -p iitc
unzip -p /tmp/iitc.zip total-conversion-build.user.js > iitc/total-conversion-build.js

Always use the latest release

mkdir -p iitc
curl -sSL "https://github.com/IITC-CE/ingress-intel-total-conversion/releases/latest/download/total-conversion-build.user.js" \
  > iitc/total-conversion-build.js

Note: Check the releases page to confirm the direct-download asset name, as it may vary between releases. If the asset is only available inside a ZIP, use the pinned-version approach above.

Using the gh CLI

IITC_VERSION=0.42.2
mkdir -p iitc
gh release download "${IITC_VERSION}" \
  --repo IITC-CE/ingress-intel-total-conversion \
  --pattern "release-${IITC_VERSION}.zip" \
  --output /tmp/iitc.zip
unzip -p /tmp/iitc.zip total-conversion-build.user.js > iitc/total-conversion-build.js

Cache it in CI

Downloading on every run is slow. Cache the result by IITC version:

- name: Cache IITC script
  uses: actions/cache@v4
  with:
    path: iitc/
    key: iitc-${{ env.IITC_VERSION }}

Typical CI workflow (GitHub Actions)

Single version -- auto-download

The simplest setup. The CLI downloads and caches the IITC script automatically.

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-node@v4
        with:
          node-version: 20
          cache: npm

      - name: Install dependencies
        run: npm ci

      - name: Install Playwright browsers
        run: npx playwright install --with-deps chromium

      - name: Cache downloaded IITC scripts
        uses: actions/cache@v4
        with:
          path: ~/.cache/iitc-kuku-plugin-tester
          key: iitc-0.42.2

      - name: Build plugin
        run: npm run build

      - name: Test plugin
        run: npx iitc-plugin-tester --plugin dist/my-plugin.js --iitc-version 0.42.2

Matrix -- multiple IITC versions

Run the full suite against every version in parallel. Each job tests one version; the matrix entry is used as both the version string and the cache key.

jobs:
  test:
    runs-on: ubuntu-latest
    strategy:
      fail-fast: false
      matrix:
        iitc-version: ["0.42.2", "0.43.0"]

    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-node@v4
        with:
          node-version: 20
          cache: npm

      - name: Install dependencies
        run: npm ci

      - name: Install Playwright browsers
        run: npx playwright install --with-deps chromium

      - name: Cache downloaded IITC scripts
        uses: actions/cache@v4
        with:
          path: ~/.cache/iitc-kuku-plugin-tester
          key: iitc-${{ matrix.iitc-version }}

      - name: Build plugin
        run: npm run build

      - name: Test plugin against IITC ${{ matrix.iitc-version }}
        run: npx iitc-plugin-tester --plugin dist/my-plugin.js --iitc-version ${{ matrix.iitc-version }}

Single version -- manual download (pre-warm image cache)

Use this if you want the IITC script baked into a Docker layer or cached separately from the plugin tester's own cache.

env:
  IITC_VERSION: 0.42.2

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-node@v4
        with:
          node-version: 20
          cache: npm

      - name: Install dependencies
        run: npm ci

      - name: Install Playwright browsers
        run: npx playwright install --with-deps chromium

      - name: Cache IITC script
        uses: actions/cache@v4
        with:
          path: iitc/
          key: iitc-${{ env.IITC_VERSION }}

      - name: Download IITC script
        run: |
          mkdir -p iitc
          curl -sSLo /tmp/iitc.zip \
            "https://github.com/IITC-CE/ingress-intel-total-conversion/releases/download/${{ env.IITC_VERSION }}/release-${{ env.IITC_VERSION }}.zip"
          unzip -p /tmp/iitc.zip total-conversion-build.user.js > iitc/total-conversion-build.js

      - name: Build plugin
        run: npm run build

      - name: Test plugin
        run: npx iitc-plugin-tester --plugin dist/my-plugin.js

Writing your own tests

The built-in test verifies IITC boots with your plugin loaded. To add plugin-specific assertions, pass extra Playwright arguments pointing to your own test directory:

npx iitc-plugin-tester --plugin dist/my-plugin.js -- --test-dir tests/

Your tests use the standard Playwright API. Wait for [data-iitc-fully-loaded="true"] before asserting anything -- it is the reliable signal that IITC and all plugins have finished booting:

import { test, expect } from '@playwright/test';
import { setupIITCRoutes, suppressIITCDialogs } from 'iitc-kuku-plugin-tester/tests/helpers/iitc-page';

test('my plugin renders a button', async ({ page }) => {
  await page.addInitScript(suppressIITCDialogs);
  await setupIITCRoutes(page);
  await page.goto('/');

  await page.waitForSelector('[data-iitc-fully-loaded="true"]', { timeout: 20000 });

  await expect(page.locator('#my-plugin-button')).toBeVisible();

  // Visual regression: compare against a stored baseline.
  // First run (or --update-snapshots) creates the baseline; subsequent runs
  // fail if the page differs beyond the allowed pixel tolerance.
  await expect(page).toHaveScreenshot('my-plugin.png', {
    mask: [page.locator('#chatinput time')],  // mask the clock to avoid flakiness
    maxDiffPixelRatio: 0.02,
  });
});

Visual regression baseline

The built-in test stores its baseline at tests/screenshots/iitc-loaded.png. Commit this file so CI can compare against it.

To create or refresh a baseline after an intentional UI change:

npx playwright test --update-snapshots

Local development (working on this package)

Prerequisites: Node.js 18+

npm install
npx playwright install chromium

Place the IITC built script at iitc/total-conversion-build.js.

npm test                          # headless
npm run test:headed               # with a visible browser window
npm run server                    # start the mock server standalone on port 3000
npx tsc --noEmit                  # type-check
npx playwright test --update-snapshots   # refresh the baseline screenshot
node scripts/fetch-tiles.js       # re-download OSM tiles for the screenshot area

Drop additional plugin .js files into plugins/ and they are automatically embedded into the page at boot alongside the built-in tests/test-plugin.js.

Plugin file format

Plugins must be IIFEs that push a setup function onto window.bootPlugins. The userscript self-injection wrapper (document.createElement('script')) is not needed -- files already run in page context.

(function () {
  if (typeof window.plugin !== 'function') window.plugin = function () {};
  window.plugin.myPlugin = {};

  function setup() {
    // All IITC globals available: window.map, window.addHook, window.dialog, etc.
  }

  setup.info = { pluginId: 'my-plugin' };
  if (!window.bootPlugins) window.bootPlugins = [];
  window.bootPlugins.push(setup);
  if (window.iitcLoaded && typeof setup === 'function') setup();
})();

Customising mock data

| File | What to change | |---|---| | server/fixtures/player.json | Player nickname, team (RESISTANCE / ENLIGHTENED), level, AP | | server/fixtures/entities.json | Portal/link/field data to populate the map | | server/fixtures/gameScore.json | Enlightened / Resistance MindUnit scores | | server/fixtures/tiles/ | Pre-fetched OSM tiles; run node scripts/fetch-tiles.js to repopulate | | server/routes/api.ts | Add handlers for any other POST /r/* endpoints your plugin calls |

Mocking additional network requests

tests/helpers/iitc-page.ts contains the Playwright route interceptions. Add more page.route() calls there for external URLs your plugin fetches:

await page.route(/my-external-api\.com/, (route) =>
  route.fulfill({ status: 200, contentType: 'application/json', body: '{"ok":true}' })
);

Project structure

iitc-kuku-plugin-tester/
├── bin/
│   └── iitc-plugin-tester.js       # CLI entry point
├── scripts/
│   └── fetch-tiles.js              # Downloads OSM tiles for the screenshot area
├── src/
│   ├── config.ts                   # Config loading (file + CLI args)
│   ├── setup.ts                    # Plugin staging (temp dir)
│   ├── cli.ts                      # CLI logic
│   └── download.ts                 # IITC release downloader + cache
├── iitc/                           # IITC built script (not included -- provide your own)
│   └── total-conversion-build.js
├── plugins/                        # Drop .js files here for standalone dev use
├── server/
│   ├── index.ts                    # Express entry point
│   ├── start.js                    # Plain-JS launcher (used by playwright webServer)
│   ├── fixtures/
│   │   ├── player.json
│   │   ├── gameScore.json
│   │   ├── entities.json
│   │   └── tiles/                  # Pre-fetched OSM tiles ({z}/{x}/{y}.png)
│   └── routes/
│       ├── intel-page.ts           # Mock intel.ingress.com HTML
│       ├── api.ts                  # Mock POST /r/* endpoints
│       └── tiles.ts                # Local tile server (fixtures or blank PNG)
├── tests/
│   ├── helpers/
│   │   └── iitc-page.ts            # Shared route interceptors + dialog suppressor
│   ├── screenshots/
│   │   └── iitc-loaded.png         # Baseline screenshot for visual regression
│   ├── test-plugin.js              # Boot-signal plugin (always loaded last by the harness)
│   ├── iitc-loads.spec.ts          # Built-in boot + visual regression test
│   └── entities.spec.ts            # Verifies portals, links, and fields for all factions
├── iitc-tester.config.json         # (create in your project, not here)
├── playwright.config.ts
└── tsconfig.json

License

WTFPL