# PaperTrench Chrome E2E Testing

> How to load and end-to-end test the PaperTrench Manifest V3 Chrome extension on Windows

- Skill: `onlyterp/papertrench-chrome-e2e-testing` (Agent Skill)
- Install (CLI): `npx skillmds@latest add onlyterp/papertrench-chrome-e2e-testing`
- Raw SKILL.md: https://api.skillmd.com/api/skills/onlyterp/papertrench-chrome-e2e-testing/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: OnlyTerp (https://skillmd.com/u/onlyterp)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/onlyterp/papertrench-chrome-e2e-testing

---


# PaperTrench Chrome E2E Testing

## Chrome binary
- Path: `C:\devin\chrome\chrome-win64\chrome.exe`

## Launch flags
```powershell
$chrome = 'C:\devin\chrome\chrome-win64\chrome.exe'
$ext = 'C:\Users\Administrator\repos\papertrench\extension'
$profile = 'C:\Users\Administrator\AppData\Local\Temp\ptchrome-profiles\test'

# On Windows, pass the flags as a single quoted string so `--load-extension` and
# `--user-data-dir` keep their values. Using an array can split the flag from
# the path and cause Chrome to open the extension directory as a file URL.
$argStr='--no-sandbox --disable-setuid-sandbox --disable-dev-shm-usage --disable-gpu --hide-crash-restore-bubble --no-first-run --disable-sync --remote-allow-origins=* --remote-debugging-port=9222 --load-extension="'+$ext+'" --user-data-dir="'+$profile+'" --window-size=1400,1050 --start-maximized'
Start-Process -FilePath $chrome -ArgumentList $argStr -WindowStyle Normal
```

## Avoid the "Restore pages?" bubble
Before launching, patch the profile so Chrome thinks it exited cleanly:
```powershell
$profileDir = 'C:\Users\Administrator\AppData\Local\Temp\ptchrome-profiles\test'
$localState = Join-Path $profileDir 'Local State'
$prefs = Join-Path $profileDir 'Default\Preferences'
if (Test-Path $localState) {
  $s = Get-Content $localState -Raw
  $s = $s -replace '"exited_cleanly"\s*:\s*false', '"exited_cleanly":true'
  Set-Content $localState $s -NoNewline
}
if (Test-Path $prefs) {
  $s = Get-Content $prefs -Raw
  $s = $s -replace '"exited_cleanly"\s*:\s*false', '"exited_cleanly":true'
  $s = $s -replace '"exit_type"\s*:\s*"[^"]*"', '"exit_type":"Normal"'
  Set-Content $prefs $s -NoNewline
}
```

## CDP helper
- List targets: `curl.exe -s http://127.0.0.1:9222/json`
- Open a new tab by URL: `curl.exe -s -X PUT 'http://127.0.0.1:9222/json/new?https://dexscreener.com/solana/<mint>'`
- The extension appears as a `service_worker` target with `chrome-extension://<id>/background.js`.

## Navigation workaround
Typing `chrome://` or `file://` URLs in the omnibox can be routed to Google search. Use a local redirect file or CDP `/json/new` instead.

## Verifying the loaded version
The extension does not render its version inside the popup or dashboard. The authoritative visible version is on `chrome://extensions`. Open the details page directly with the extension ID (from the `service_worker` target URL):

```powershell
curl.exe -s -X PUT 'http://127.0.0.1:9222/json/new?chrome://extensions/?id=<id>'
```

The details page shows the **Version** field from `manifest.json`. Do not click **Remove** by mistake; the buttons are adjacent.

## Checking the extension ID
Look at the `service_worker` target returned by `http://127.0.0.1:9222/json`. Its `url` is `chrome-extension://<id>/background.js`. Use `<id>` when opening `chrome://extensions/?id=<id>`.

If the service worker target is not present yet, you can also obtain the ID from the `chrome://extensions/` page by inspecting the `extensions-item` inside the `extensions-manager` shadow DOM, e.g.:
```js
const root = document.querySelector('extensions-manager');
const list = root && root.shadowRoot && root.shadowRoot.querySelector('extensions-item-list');
const item = list && list.shadowRoot && list.shadowRoot.querySelector('extensions-item');
const id = item && item.id;
```

## Token page to test
- Dexscreener: `https://dexscreener.com/solana/DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263`
- Birdeye: `https://birdeye.so/token/DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263?chain=solana`
- GMGN: `https://gmgn.ai/sol/token/DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263`
- Jupiter path URLs (`jup.ag/swap/SOL-<mint>`) may redirect to a `buy=...&sell=...` query form; the adapter now filters WSOL/USDC/USDT so it picks the requested output token instead of a stablecoin.

## Overlay selectors (Shadow DOM host: `#papertrench-host`)
- `#pt-token-name` — token name
- `#pt-price` — headline price (native price or market cap depending on token/site); the secondary unit is in `#pt-price-usd`
- `#pt-balance` — paper balance
- `#pt-buy-presets .pt-preset` — quick-buy amounts
- `#pt-buy` — primary buy button
- `#pt-position` — position card (includes `.pt-sell-row` sell buttons)
- `#pt-bar` — positions bar rail
- `#pt-dash` — open dashboard

## Driving the overlay from CDP
Create a `node` script using `ws` (`npm install ws` in a temp dir) and connect to the page target's `webSocketDebuggerUrl` to run `Runtime.evaluate` expressions such as:
```js
document.getElementById('papertrench-host').shadowRoot.getElementById('pt-buy').click()
```

For UI gestures that do not respond well to real mouse drags (e.g. the v1.2.3 positions-bar drag grip), use CDP `Input.dispatchMouseEvent`. The `x`/`y` coordinates are relative to the main frame's viewport, so derive them from `element.getBoundingClientRect()`.

## Windows-specific testing notes

- Screenshot and video artifacts are written to `C:\Users\Administrator\screenshots\` and `C:\tmp\devin-recordings\`. `upload_attachment` does not accept `C:\...` paths directly; copy files to `C:\tmp\...` and reference them with `/tmp/...` POSIX-style paths.
- The `computer` typing tool may mangle bracket/colon strings such as `http://[::]:8080/v1` or `http://localhost.:8765/v1`. For these cases use CDP `Runtime.evaluate` to set `document.getElementById('set-endpoint').value` and trigger `document.getElementById('test-ai').click()`, then read `document.getElementById('ai-test-result').textContent` for the visible outcome.

## Common gotchas
- Dexscreener/Birdeye/GMGN may show Cloudflare or login walls; the service worker still resolves the token via Dexscreener API because the overlay uses background price resolution, not the page DOM.
- The overlay is taller than the default 1024x768 capture area; drag the `#pt-drag` header up or maximize the browser to reveal buy/sell buttons.
- Dashboard `Rounds` and `Leaderboard` are the most fragile sections; check for `replay.checkpoints` and attestation-chain fee mismatches.
- To inspect globals that live in the extension's isolated content-script world (e.g. `window.PTChartMarkers`), enable `Runtime` and listen for `Runtime.executionContextCreated` events. The content-script context is usually named `PaperTrench`; pass its `contextId` to `Runtime.evaluate`.

