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

@lynx-js/kitten-lynx-test-infra

v0.1.2

Published

A testing framework executing the Lynx explorer Android application

Downloads

161

Readme

Kitten-Lynx (🐾 testing-library)

Kitten-Lynx is a Puppeteer-like / Playwright-like testing library. It is designed specifically for interacting with the Lynx browser engine and the Lynx Explorer Android application.

If you are an AI Agent (or a developer) reading this, this document is optimized to be as clear and straightforward as possible to help you write tests and understand the architecture without guessing.


🌟 What does it do?

Using the Chrome DevTools Protocol (CDP) over USB/ADB, kitten-lynx gives you the power to:

  1. Automatically open the Lynx Explorer app on an Android emulator or physical device.
  2. Navigate to .lynx.bundle URLs.
  3. Access the Lynx DOM (Document Object Model) tree.
  4. Find elements using CSS Selectors (e.g. page.locator('#my-id')).
  5. Read element styles and attributes.
  6. Simulate native touch gestures (like tapping on buttons).

🏗️ Architecture Explained (For Agents)

In standard Web Playwright/Puppeteer, you connect to a persistent browser WebSocket. Lynx is different.

  1. Stateless Connector: This library uses @lynx-js/devtool-connector which operates via Android Debug Bridge (ADB). It sends isolated Request/Response commands. There is no long-living socket.
  2. Session Hopping: When you tell Lynx to navigate to a new URL, Lynx creates an entirely new debugging session.
  3. Lynx.ts: Handles the physical device connection, force-stops the app, restarts it, and ensures the Master devtool switch is ON.
  4. KittenLynxView.ts: Represents a single "Page". When you call goto(url), it sends the navigate command, and then intensely polls the ADB session list until it finds the new session matching your URL, and re-attaches to it.
  5. ElementNode.ts: Represents a physical tag (like <view> or <text>). Cached via WeakRef to save memory. Uses native coordinate math via DOM.getBoxModel to simulate real screen taps.

🚀 Quick Start Guide

Prerequisites

  • You must have an Android Emulator or device running via adb.
  • The Lynx Explorer APK must be installed (adb install LynxExplorer.apk).
  • (In CI) Ensure your test runner can reach your local bundle dev server (you might need adb reverse tcp:8080 tcp:8080).

Example Test Script

Here is the blueprint for a standard test written using kitten-lynx and vitest:

import { expect, test, beforeAll, afterAll } from 'vitest';
import { Lynx } from '@lynx-js/kitten-lynx-test-infra';
import type { KittenLynxView } from '@lynx-js/kitten-lynx-test-infra';

let lynx: Lynx;
let page: KittenLynxView;

// Setup: Connect to device
beforeAll(async () => {
  // Connects to the first available ADB device and opens com.lynx.explorer
  lynx = await Lynx.connect();
  page = await lynx.newPage();
}, 60000); // Give ADB enough time to boot!

// Teardown: Clean up resources
afterAll(async () => {
  await lynx.close();
});

test('Basic Navigation and Interaction', async () => {
  // 1. Navigate to the bundle (Will poll until the session is found)
  await page.goto('http://10.0.2.2:8080/dist/main.lynx.bundle');

  // 2. Locate an element by CSS Selector
  const button = await page.locator('#submit-btn');
  expect(button).toBeDefined();

  // 3. Read an attribute.
  // (Note: 'id' maps internally to Lynx's 'idSelector')
  const idValue = await button!.getAttribute('id');
  expect(idValue).toBe('submit-btn');

  // 4. Read computed CSS styles
  const styles = await button!.computedStyleMap();
  expect(styles.get('display')).toBe('flex');

  // 5. Simulate a native tap
  await button!.tap();

  // 6. Assert DOM changes (re-query the new element)
  const successText = await page.locator('.success-message');
  expect(successText).toBeDefined();
}, 30000);

⚠️ Known Gotchas & Pitfalls

If you are writing scripts and tests, memorize these rules:

  1. goto() implies a Session Change: After page.goto(), the old node IDs are dead. Always query elements after the navigation finishes.
  2. Timeouts: Android emulators take time to boot. The devtool ADB bridge takes time to synchronize. Always set high timeouts for setup hooks (beforeAll(..., 60000)).
  3. No App.openPage locally: Lynx Explorer 3.6.0 does not support App.openPage properly in some fallback layers. kitten-lynx falls back to a Custom OpenCard event automatically. You do not need to worry about this, but do not be alarmed by terminal warnings.
  4. Id Selector: Standard web writes <view id="test">. Lynx internally uses idSelector="test". The ElementNode.getAttribute('id') handles this mapping automatically for you. Do not query 'idSelector' directly.
  5. DOM Snapshots: You can call await page.content() to get a massive HTML-like string of the current Lynx DOM. This is extremely helpful for debugging what is actually rendering!

🛠️ Extending the Library

If you need to add a newly supported CDP command:

  1. Open src/CDPChannel.ts.
  2. Add the strictly-typed parameter and return shapes to the Protocol interface block at the top of the file.
  3. Call await this._channel.send('Domain.methodName', params) in KittenLynxView or ElementNode.
  4. Run pnpm run build && pnpm run test before committing.