From dd7c68c13a8a4a242b20fc20ef01ba0c4a6218b0 Mon Sep 17 00:00:00 2001 From: Cal Corum Date: Mon, 6 Apr 2026 02:00:38 -0500 Subject: [PATCH] =?UTF-8?q?docs:=20sync=20KB=20=E2=80=94=20discord-browser?= =?UTF-8?q?-testing-workflow.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../discord-browser-testing-workflow.md | 170 ++++++++++++++++++ 1 file changed, 170 insertions(+) create mode 100644 paper-dynasty/discord-browser-testing-workflow.md diff --git a/paper-dynasty/discord-browser-testing-workflow.md b/paper-dynasty/discord-browser-testing-workflow.md new file mode 100644 index 0000000..cff469f --- /dev/null +++ b/paper-dynasty/discord-browser-testing-workflow.md @@ -0,0 +1,170 @@ +--- +title: "Discord Bot Browser Testing via Playwright + CDP" +description: "Step-by-step workflow for automated Discord bot testing using Playwright connected to Brave browser via Chrome DevTools Protocol. Covers setup, slash command execution, and screenshot capture." +type: runbook +domain: paper-dynasty +tags: [paper-dynasty, discord, testing, playwright, automation] +--- + +# Discord Bot Browser Testing via Playwright + CDP + +Automated testing of Paper Dynasty Discord bot commands by connecting Playwright to a running Brave browser instance with Discord open. + +## Prerequisites + +- Brave browser installed (`brave-browser-stable`) +- Playwright installed (`pip install playwright && playwright install chromium`) +- Discord logged in via browser (not desktop app) +- Discord bot running (locally via docker-compose or on remote host) +- Bot's `API_TOKEN` must match the target API environment + +## Setup + +### 1. Launch Brave with CDP enabled + +Brave must be started with `--remote-debugging-port`. If Brave is already running, **kill it first** — otherwise the flag is ignored and the new process merges into the existing one. + +```bash +killall brave && sleep 2 && brave-browser-stable --remote-debugging-port=9222 & +``` + +### 2. Verify CDP is responding + +```bash +curl -s http://localhost:9222/json/version | python3 -m json.tool +``` + +Should return JSON with `Browser`, `webSocketDebuggerUrl`, etc. + +### 3. Open Discord in browser + +Navigate to `https://discord.com/channels//` in Brave. + +**Paper Dynasty test server:** +- Server: Cals Test Server (`669356687294988350`) +- Channel: #pd-game-test (`982850262903451658`) +- URL: `https://discord.com/channels/669356687294988350/982850262903451658` + +### 4. Verify bot is running with correct API token + +```bash +# Check docker-compose.yml has the right API_TOKEN for the target environment +grep API_TOKEN /mnt/NV2/Development/paper-dynasty/discord-app/docker-compose.yml + +# Dev API token lives on the dev host: +ssh pd-database "docker exec sba_postgres psql -U sba_admin -d paperdynasty_dev -c \"SELECT 1;\"" + +# Restart bot if token was changed: +cd /mnt/NV2/Development/paper-dynasty/discord-app && docker compose up -d +``` + +## Running Commands + +### Find the Discord tab + +```python +from playwright.sync_api import sync_playwright +import time + +with sync_playwright() as p: + browser = p.chromium.connect_over_cdp('http://localhost:9222') + for ctx in browser.contexts: + for page in ctx.pages: + if 'discord' in page.url.lower(): + print(f'Found: {page.url}') + break + browser.close() +``` + +### Execute a slash command and capture result + +```python +from playwright.sync_api import sync_playwright +import time + +def run_slash_command(command: str, wait_seconds: int = 5, screenshot_path: str = '/tmp/discord_result.png'): + """ + Type a slash command in Discord, select the top autocomplete option, + submit it, wait for the bot response, and take a screenshot. + """ + with sync_playwright() as p: + browser = p.chromium.connect_over_cdp('http://localhost:9222') + for ctx in browser.contexts: + for page in ctx.pages: + if 'discord' in page.url.lower(): + msg_box = page.locator('[role="textbox"][data-slate-editor="true"]') + msg_box.click() + time.sleep(0.3) + + # Type the command (delay simulates human typing for autocomplete) + msg_box.type(command, delay=80) + time.sleep(2) + + # Tab selects the top autocomplete option + page.keyboard.press('Tab') + time.sleep(1) + + # Enter submits the command + page.keyboard.press('Enter') + time.sleep(wait_seconds) + + page.screenshot(path=screenshot_path) + print(f'Screenshot saved to {screenshot_path}') + break + browser.close() + +# Example usage: +run_slash_command('/refractor status') +``` + +### Commands with parameters + +After pressing Tab to select the command, Discord shows an options panel. To fill parameters: + +1. The first parameter input is auto-focused after Tab +2. Type the value, then Tab to move to the next parameter +3. Press Enter when ready to submit + +```python +# Example: /refractor status with tier filter +msg_box.type('/refractor status', delay=80) +time.sleep(2) +page.keyboard.press('Tab') # Select command from autocomplete +time.sleep(1) +# Now fill parameters if needed, or just submit +page.keyboard.press('Enter') +``` + +## Key Selectors + +| Element | Selector | +|---------|----------| +| Message input box | `[role="textbox"][data-slate-editor="true"]` | +| Autocomplete popup | `[class*="autocomplete"]` | + +## Gotchas + +- **Brave must be killed before relaunch** — if an instance is already running, `--remote-debugging-port` is silently ignored +- **Bot token mismatch** — the bot's `API_TOKEN` in `docker-compose.yml` must match the target API (dev or prod). Symptoms: `{"detail":"Unauthorized"}` in bot logs +- **Viewport is None** — when connecting via CDP, `page.viewport_size` returns None. Use `page.evaluate('() => ({w: window.innerWidth, h: window.innerHeight})')` instead +- **Autocomplete timing** — typing too fast may not trigger Discord's autocomplete. The `delay=80` on `msg_box.type()` simulates human speed +- **Multiple bots** — if multiple bots register the same slash command (e.g. MantiTestBot and PucklTestBot), Tab selects the top option. Verify the correct bot name in the autocomplete popup before proceeding + +## Test Plan Reference + +The Refractor integration test plan is at: +`discord-app/tests/refractor-integration-test-plan.md` + +Key test case groups: +- REF-01 to REF-06: Tier badges and display +- REF-10 to REF-15: Progress bars and filtering +- REF-40 to REF-42: Cross-command badges (card, roster) +- REF-70 to REF-72: Cross-command badge propagation (the current priority) + +## Verified On + +- **Date:** 2026-04-06 +- **Browser:** Brave 146.0.7680.178 (Chromium-based) +- **Playwright:** Node.js driver via Python sync API +- **Bot:** MantiTestBot on Cals Test Server, #pd-game-test channel +- **API:** pddev.manticorum.com (dev environment)