PaperTrench Chrome E2E Testing
Chrome binary
- Path:
C:\devin\chrome\chrome-win64\chrome.exe
Launch flags
$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:
$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_workertarget withchrome-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):
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.:
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 abuy=...&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-rowsell 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:
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\andC:\tmp\devin-recordings\.upload_attachmentdoes not acceptC:\...paths directly; copy files toC:\tmp\...and reference them with/tmp/...POSIX-style paths. - The
computertyping tool may mangle bracket/colon strings such ashttp://[::]:8080/v1orhttp://localhost.:8765/v1. For these cases use CDPRuntime.evaluateto setdocument.getElementById('set-endpoint').valueand triggerdocument.getElementById('test-ai').click(), then readdocument.getElementById('ai-test-result').textContentfor 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-dragheader up or maximize the browser to reveal buy/sell buttons. - Dashboard
RoundsandLeaderboardare the most fragile sections; check forreplay.checkpointsand attestation-chain fee mismatches. - To inspect globals that live in the extension's isolated content-script world (e.g.
window.PTChartMarkers), enableRuntimeand listen forRuntime.executionContextCreatedevents. The content-script context is usually namedPaperTrench; pass itscontextIdtoRuntime.evaluate.