Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
79 commits
Select commit Hold shift + click to select a range
ddfc78c
test: add failing test for CDP video recording all pages
NiceCode666 Apr 8, 2026
eb8f856
refactor: remove CDP ownership guard from _start_page_video_recorder
NiceCode666 Apr 8, 2026
855676e
feat: record all CDP pages in start_video, not just bridgic-owned tabs
NiceCode666 Apr 8, 2026
27e3bd4
docs: update CDP_MODE.md — start_video now records all pages
NiceCode666 Apr 8, 2026
f89f512
refactor: remove _cdp_owned_pages, CDP close() now pure disconnect
NiceCode666 Apr 8, 2026
5d00349
refactor: remove dead _cdp_borrowed variable and update stale comments
NiceCode666 Apr 8, 2026
0816cc1
test: remove _cdp_owned_pages assertions and delete TestBrowserCdpOwn…
NiceCode666 Apr 8, 2026
56d7746
test: remove _cdp_owned_pages from helpers and update CDP borrowed-mo…
NiceCode666 Apr 8, 2026
bf26f67
docs: update CDP_MODE.md — close() is pure disconnect, all tabs visible
NiceCode666 Apr 8, 2026
61ee33c
perf: parallelize page.title() calls in get_all_page_descs with async…
NiceCode666 Apr 8, 2026
fe639b7
refactor: enhance CLI command descriptions and improve wait command f…
NiceCode666 Apr 10, 2026
e2246bf
feat: enhance search command with CDP connection option
NiceCode666 Apr 10, 2026
2d7fb87
fix: improve browser detection in test for CDP URL retrieval
NiceCode666 Apr 10, 2026
e5629f7
feat: add video recording functionality for active tab
NiceCode666 Apr 10, 2026
c3e5cb6
fix: update path handling and add OS-specific skips in tests
NiceCode666 Apr 10, 2026
909a21a
chore: update CI workflow and improve path handling in browser CLI
NiceCode666 Apr 10, 2026
84b00a1
docs: enhance README and CDP_MODE documentation for remote debugging …
NiceCode666 Apr 11, 2026
44ae8cf
fix(cli): address four CLI freeze/hang root causes from daemon.log
NiceCode666 Apr 14, 2026
874dec5
Merge remote-tracking branch 'origin/hotfix/interactive-snapshot-text…
NiceCode666 Apr 14, 2026
526ca31
perf(_snapshot): fix roleIndex rebuild regression on large pages via …
NiceCode666 Apr 14, 2026
8d022dc
feat(snapshot): implement background snapshot pre-warming for improve…
NiceCode666 Apr 14, 2026
457e9c3
Merge branch 'main' into feature/cdp-url-support
NiceCode666 Apr 16, 2026
9d8eb95
fix: harden CLI daemon, CDP detection, snapshot concurrency, and vide…
NiceCode666 Apr 16, 2026
b99b90e
refactor: enhance CDP handling and improve error management
NiceCode666 Apr 16, 2026
8039085
fix: silence false-positive unreachable warning in find_cdp_url
NiceCode666 Apr 16, 2026
4057d0f
refactor: rename cdp_url to cdp for consistency across SDK and CLI
NiceCode666 Apr 16, 2026
267cd1c
Merge pull request #24 from bitsky-tech/main
NiceCode666 Apr 16, 2026
6794ee4
test: skip non-executable binary test on Windows
NiceCode666 Apr 16, 2026
ca91e8e
fix: snapshot deadlock, download/video lifecycle, CDP URL redact
NiceCode666 Apr 17, 2026
a9d96ca
fix(dropdown): drop hidden shadow-<select> options for custom comboboxes
NiceCode666 Apr 17, 2026
fb51057
fix: harden config validation, CDP detection, CLI client, downloads a…
NiceCode666 Apr 19, 2026
10f236b
test: isolate Windows unit tests from host state
NiceCode666 Apr 19, 2026
2f6b8ff
test: accept BROWSER_CLOSED in snapshot-during-close race test
NiceCode666 Apr 19, 2026
fe3cb61
test: fall back to default tempdir on Windows in integration fixtures
NiceCode666 Apr 19, 2026
f2c7454
test: stop colliding with Node inspector port in CDP borrowed-mode fi…
NiceCode666 Apr 20, 2026
2cad94c
refactor: update _probe_cdp_alive to use TCP connection for liveness …
NiceCode666 Apr 20, 2026
cdc9ef1
chore: drop unused imports in test_find_cdp_url
NiceCode666 Apr 20, 2026
266ddf3
refactor: enhance _wait_for_chrome to capture Chrome's stderr
NiceCode666 Apr 20, 2026
c753b17
refactor: improve _free_port method to ensure reliable TCP port selec…
NiceCode666 Apr 20, 2026
d040fc2
refactor: remove _free_port method and mock socket connection in tests
NiceCode666 Apr 20, 2026
0f7a368
fix: address PR#21 HIGH-severity review findings
NiceCode666 Apr 20, 2026
ee5b663
feat: introduce CDP discovery and error handling utilities
NiceCode666 Apr 20, 2026
97b9229
Merge branch 'main' of github.com:bitsky-tech/bridgic-browser into fe…
NiceCode666 Apr 20, 2026
14412f3
feat: enhance viewport size resolution and browser binary detection
NiceCode666 Apr 20, 2026
67f7457
fix: review follow-ups for CDP/snapshot/click pathways
claude Apr 21, 2026
57220e8
Merge pull request #26 from bitsky-tech/feature/review-followups-pr21
NiceCode666 Apr 21, 2026
ae41645
test: comprehensive coverage for PR #21 CR follow-ups
claude Apr 21, 2026
f95e4f3
Merge pull request #27 from bitsky-tech/feature/test-coverage-pr21-cr
NiceCode666 Apr 21, 2026
4efb2ff
chore: ignore scripts/qa generated artifacts
NiceCode666 Apr 22, 2026
3d83124
fix: CDP auto-reconnect, click fallback budget, eval arrow-fn parity …
NiceCode666 Apr 22, 2026
3915995
test: cover disabled click, CDP close-reattach, go_back ref invalidat…
NiceCode666 Apr 22, 2026
b24b368
test: add 7-variant mode-matrix QA (CLI + SDK diff)
NiceCode666 Apr 22, 2026
0a53968
feat: split user_data_dir into headed/headless subdirs to avoid Singl…
NiceCode666 Apr 22, 2026
e7a71dd
test: add multi-origin storage state restore test
NiceCode666 Apr 22, 2026
c3c9a80
chore: bump version to 0.0.5.dev7
NiceCode666 Apr 22, 2026
5c30c77
feat: support BRIDGIC_HOME env var for multi-instance daemon isolation
NiceCode666 May 9, 2026
b44b4bb
fix: reset _closing flag on _start() and prevent recursion in _is_bro…
NiceCode666 May 9, 2026
1ffd815
fix: six CR follow-up bugs — eval exceptionDetails, go_back/forward N…
NiceCode666 May 9, 2026
3e0526b
docs: add BRIDGIC_HOME multi-instance isolation section to both READMEs
NiceCode666 May 9, 2026
22a3875
docs: unify remaining ~/.bridgic paths to $BRIDGIC_HOME in both READMEs
NiceCode666 May 9, 2026
0c82197
docs: add storage state cross-instance login sharing guide to both RE…
NiceCode666 May 9, 2026
49af155
docs: add SDK usage example for storage state export/import
NiceCode666 May 9, 2026
7d4cbff
fix: go_back/go_forward false positive on same-document navigation
NiceCode666 May 9, 2026
22d3f18
docs(skills): add CDP mode reference + opener API probe test
NiceCode666 May 12, 2026
c166bd2
feat(stealth): mode-aware anti-detection — race-proof workers, UA cle…
NiceCode666 May 12, 2026
8eec54e
feat(cdp): owned-pages tracking — privacy boundary in CDP borrowed mode
NiceCode666 May 12, 2026
7b7c2ca
feat(cdp): evaluate_javascript parity with page.evaluate in CDP mode
NiceCode666 May 13, 2026
01bd228
feat(cdp): silent downloads in CDP-borrowed mode via page-session rou…
NiceCode666 May 13, 2026
2350b6e
test(cdp): lifecycle contract scenarios I11-I15 for owned-page reap
NiceCode666 May 13, 2026
3c14349
chore: bump version to 0.0.5.dev15
NiceCode666 May 13, 2026
1cb0198
fix(cdp): run L3 download-behavior restore before page.close()
NiceCode666 May 18, 2026
7c9ec68
test(cdp): bump node subprocess timeout to 30s for Windows cold-start
NiceCode666 May 18, 2026
a411f57
docs: drop concrete Cloudflare test URL from stealth verification che…
NiceCode666 May 18, 2026
f16d503
test(cdp): skip wrap-js parity tests on Windows; revert timeout bump
NiceCode666 May 18, 2026
eaf2bf3
Merge pull request #21 from bitsky-tech/feature/cdp-url-support
NiceCode666 May 18, 2026
2589b5a
chore: bump version to 0.0.5
NiceCode666 May 18, 2026
7546195
fix: auto-switch to system Chrome in all headed launches
NiceCode666 May 18, 2026
dda26e3
chore: bump version to 0.0.5.post1 for testpypi fix
NiceCode666 May 18, 2026
db92a6a
chore: restore version to 0.0.5 for release
NiceCode666 May 18, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
323 changes: 305 additions & 18 deletions .github/workflows/windows-cli-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,65 @@ on:
workflow_dispatch:

jobs:
# ── Unit tests (pytest) on Windows ───────────────────────────────────────
unit-test-windows:
name: Unit Test (Windows, Python ${{ matrix.python-version }})
runs-on: windows-latest
strategy:
fail-fast: false
matrix:
python-version: ["3.10", "3.11", "3.12", "3.13"]

steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Setup Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}

- name: Install uv
uses: astral-sh/setup-uv@v4
with:
version: "latest"
enable-cache: true

- name: Cache uv dependencies
uses: actions/cache@v4
with:
path: |
~\AppData\Local\uv\cache
.venv
key: windows-unit-py${{ matrix.python-version }}-${{ hashFiles('uv.lock') }}
restore-keys: |
windows-unit-py${{ matrix.python-version }}-

- name: Install dependencies
run: uv sync --group dev

- name: Cache Playwright browsers
uses: actions/cache@v4
with:
path: ~\AppData\Local\ms-playwright
key: windows-playwright-${{ hashFiles('uv.lock') }}
restore-keys: |
windows-playwright-

- name: Install Playwright browsers
run: uv run playwright install chromium

- name: Run unit tests
run: uv run pytest tests/ --tb=short --verbose -m "not integration"

# ── CLI functional tests on Windows ──────────────────────────────────────
cli-windows:
name: CLI Test (Windows, Python ${{ matrix.python-version }})
runs-on: windows-latest
strategy:
fail-fast: false
matrix:
python-version: ["3.10", "3.11", "3.12"]

env:
BRIDGIC_HEADLESS: "1"
python-version: ["3.10", "3.11", "3.12", "3.13"]

steps:
- name: Checkout repository
Expand Down Expand Up @@ -77,6 +126,49 @@ jobs:
shell: pwsh
run: uv run bridgic-browser reload

# ── Verify ─────────────────────────────────────────────────────────────
- name: CLI — verify-url
shell: pwsh
run: |
$out = uv run bridgic-browser verify-url example.com
Write-Output $out
$outText = ($out | Out-String)
if ($outText -notmatch 'PASS') {
Write-Error "verify-url did not PASS"
exit 1
}

- name: CLI — verify-title
shell: pwsh
run: |
$out = uv run bridgic-browser verify-title Example
Write-Output $out
$outText = ($out | Out-String)
if ($outText -notmatch 'PASS') {
Write-Error "verify-title did not PASS"
exit 1
}

- name: CLI — verify-text
shell: pwsh
run: |
$out = uv run bridgic-browser verify-text "Example Domain"
Write-Output $out
$outText = ($out | Out-String)
if ($outText -notmatch 'PASS') {
Write-Error "verify-text did not PASS"
exit 1
}

# ── Wait ───────────────────────────────────────────────────────────────
- name: CLI — wait (text appears)
shell: pwsh
run: uv run bridgic-browser wait "Example Domain"

- name: CLI — wait (time)
shell: pwsh
run: uv run bridgic-browser wait 1

# ── Snapshot ───────────────────────────────────────────────────────────
- name: CLI — snapshot (full page)
shell: pwsh
Expand All @@ -100,6 +192,39 @@ jobs:
run: uv run bridgic-browser snapshot -F

# ── Element interaction via ref ────────────────────────────────────────
- name: CLI — hover first interactive ref
shell: pwsh
run: |
$snap = uv run bridgic-browser snapshot -i
$snapText = ($snap | Out-String)
$refMatch = [regex]::Match($snapText, '\[ref=([^\]\r\n]+)\]')
if ($refMatch.Success) {
$ref = $refMatch.Groups[1].Value
Write-Output "Hovering ref: $ref"
uv run bridgic-browser hover $ref
} else {
Write-Output "No interactive refs found, skipping hover"
}

- name: CLI — eval-on (ref)
shell: pwsh
run: |
$snap = uv run bridgic-browser snapshot -i
$snapText = ($snap | Out-String)
$refMatch = [regex]::Match($snapText, '\[ref=([^\]\r\n]+)\]')
if ($refMatch.Success) {
$ref = $refMatch.Groups[1].Value
Write-Output "eval-on ref: $ref"
$result = uv run bridgic-browser eval-on $ref "(el) => el.tagName"
Write-Output "Tag: $result"
if ([string]::IsNullOrWhiteSpace(($result | Out-String))) {
Write-Error "eval-on returned empty"
exit 1
}
} else {
Write-Output "No interactive refs found, skipping eval-on"
}

- name: CLI — click first link ref
shell: pwsh
run: |
Expand All @@ -115,6 +240,11 @@ jobs:
Write-Output "No interactive refs found, skipping click"
}

# ── Scroll ─────────────────────────────────────────────────────────────
- name: CLI — scroll
shell: pwsh
run: uv run bridgic-browser scroll --dy 300

# ── Navigation history ─────────────────────────────────────────────────
- name: CLI — back
shell: pwsh
Expand All @@ -124,10 +254,10 @@ jobs:
shell: pwsh
run: uv run bridgic-browser forward

# ── Wait ───────────────────────────────────────────────────────────────
- name: CLI — wait (time)
# ── Keyboard ───────────────────────────────────────────────────────────
- name: CLI — press (keyboard)
shell: pwsh
run: uv run bridgic-browser wait 1
run: uv run bridgic-browser press Tab

# ── JavaScript eval ────────────────────────────────────────────────────
- name: CLI — eval
Expand Down Expand Up @@ -166,20 +296,42 @@ jobs:
shell: pwsh
run: uv run bridgic-browser tabs

- name: CLI — new-tab and close-tab
- name: CLI — new-tab, switch-tab, close-tab
shell: pwsh
run: |
# Create a new tab
$out = uv run bridgic-browser new-tab https://example.com
Write-Output $out
# page_id is always an integer; allow page_id: 2, page_id=2, or "page_id": 2.
$outText = ($out | Out-String)
$pidMatch = [regex]::Match($outText, '(?m)\b"?page_id"?\b\s*[:=]\s*(\d+)')
if ($pidMatch.Success) {
$tabId = $pidMatch.Groups[1].Value
Write-Output "Closing tab: $tabId"
uv run bridgic-browser close-tab $tabId
Write-Output "new-tab: $out"

# List tabs and extract page_ids
$tabsOut = uv run bridgic-browser tabs
Write-Output "tabs: $tabsOut"
$tabsText = ($tabsOut | Out-String)

# Extract all page_ids
$allPids = [regex]::Matches($tabsText, '\bpage_(\d+)\b')
if ($allPids.Count -ge 2) {
# Switch to the first tab
$firstPid = $allPids[0].Value
Write-Output "Switching to: $firstPid"
uv run bridgic-browser switch-tab $firstPid

# Switch back to the second tab
$secondPid = $allPids[1].Value
Write-Output "Switching to: $secondPid"
uv run bridgic-browser switch-tab $secondPid

# Close the second tab
$pidMatch = [regex]::Match(($out | Out-String), '(?m)\b"?page_id"?\b\s*[:=]\s*(\d+)')
if ($pidMatch.Success) {
$tabId = $pidMatch.Groups[1].Value
Write-Output "Closing tab: $tabId"
uv run bridgic-browser close-tab $tabId
} else {
Write-Output "Could not extract page_id from new-tab output, skipping close-tab"
}
} else {
Write-Output "Could not extract page_id, skipping close-tab"
Write-Output "Less than 2 tabs found, skipping switch-tab"
}

# ── Storage ────────────────────────────────────────────────────────────
Expand All @@ -197,6 +349,62 @@ jobs:
}
uv run bridgic-browser storage-load state.json

# ── Form interaction (httpbin) ─────────────────────────────────────────
- name: CLI — open httpbin form
shell: pwsh
run: uv run bridgic-browser open https://httpbin.org/forms/post

- name: CLI — fill textbox on httpbin form
shell: pwsh
run: |
$snap = uv run bridgic-browser snapshot -i
Write-Output $snap
$snapText = ($snap | Out-String)
# Find a textbox ref
$textboxMatch = [regex]::Match($snapText, '(?i)textbox[^\[]*\[ref=([^\]\r\n]+)\]')
if ($textboxMatch.Success) {
$ref = $textboxMatch.Groups[1].Value
Write-Output "Filling textbox ref: $ref"
uv run bridgic-browser fill $ref "CI Test"
} else {
Write-Error "No textbox found in httpbin interactive snapshot"
exit 1
}

- name: CLI — type text (into focused field)
shell: pwsh
run: uv run bridgic-browser type " appended"

- name: CLI — focus textbox on httpbin form
shell: pwsh
run: |
$snap = uv run bridgic-browser snapshot -i
$snapText = ($snap | Out-String)
$textboxMatch = [regex]::Match($snapText, '(?i)textbox[^\[]*\[ref=([^\]\r\n]+)\]')
if ($textboxMatch.Success) {
$ref = $textboxMatch.Groups[1].Value
Write-Output "Focusing ref: $ref"
uv run bridgic-browser focus $ref
} else {
Write-Output "No textbox found, skipping focus"
}

- name: CLI — check and uncheck checkbox on httpbin form
shell: pwsh
run: |
$snap = uv run bridgic-browser snapshot -i
$snapText = ($snap | Out-String)
$checkMatch = [regex]::Match($snapText, '(?i)checkbox[^\[]*\[ref=([^\]\r\n]+)\]')
if ($checkMatch.Success) {
$ref = $checkMatch.Groups[1].Value
Write-Output "Checking ref: $ref"
uv run bridgic-browser check $ref
Write-Output "Unchecking ref: $ref"
uv run bridgic-browser uncheck $ref
} else {
Write-Output "No checkbox found in httpbin form, skipping check/uncheck"
}

# ── Shutdown ───────────────────────────────────────────────────────────
- name: CLI — close daemon
shell: pwsh
Expand All @@ -205,7 +413,8 @@ jobs:
- name: Verify — run-info cleaned up after close
shell: pwsh
run: |
$runInfo = "$env:USERPROFILE\.bridgic\bridgic-browser\run\daemon.json"
$bh = if ($env:BRIDGIC_HOME) { $env:BRIDGIC_HOME } else { "$env:USERPROFILE\.bridgic" }
$runInfo = "$bh\bridgic-browser\run\daemon.json"
# Daemon responds to close immediately but cleans up asynchronously;
# poll for up to 30 seconds before declaring failure.
$timeout = 30
Expand All @@ -219,3 +428,81 @@ jobs:
exit 1
}
Write-Output "OK: daemon cleaned up correctly (${elapsed}s)"

# ── Integration tests (pytest) on Windows ─────────────────────────────────
integration-test-windows:
name: Integration Test (Windows)
runs-on: windows-latest
needs: unit-test-windows

steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Setup Python 3.11
uses: actions/setup-python@v5
with:
python-version: "3.11"

- name: Install uv
uses: astral-sh/setup-uv@v4
with:
version: "latest"
enable-cache: true

- name: Cache uv dependencies
uses: actions/cache@v4
with:
path: |
~\AppData\Local\uv\cache
.venv
key: windows-integ-py3.11-${{ hashFiles('uv.lock') }}
restore-keys: |
windows-integ-py3.11-

- name: Cache Playwright browsers
uses: actions/cache@v4
with:
path: ~\AppData\Local\ms-playwright
key: windows-playwright-${{ hashFiles('uv.lock') }}
restore-keys: |
windows-playwright-

- name: Install dependencies
run: uv sync --group dev

- name: Install Playwright browsers
run: uv run playwright install chromium

- name: Run integration tests
run: uv run pytest tests/ --tb=short --verbose -m integration

# ── Summary ──────────────────────────────────────────────────────────────
windows-test-summary:
name: Windows Test Summary
runs-on: ubuntu-latest
needs: [unit-test-windows, cli-windows, integration-test-windows]
if: always()

steps:
- name: Check results
shell: pwsh
run: |
Write-Output "Unit tests: ${{ needs.unit-test-windows.result }}"
Write-Output "CLI tests: ${{ needs.cli-windows.result }}"
Write-Output "Integration tests: ${{ needs.integration-test-windows.result }}"

if ("${{ needs.unit-test-windows.result }}" -ne "success") {
Write-Error "Unit tests failed"
exit 1
}

if ("${{ needs.cli-windows.result }}" -ne "success") {
Write-Output "WARNING: CLI functional tests failed (non-blocking)"
}

if ("${{ needs.integration-test-windows.result }}" -ne "success") {
Write-Output "WARNING: Integration tests failed (non-blocking)"
}

Write-Output "All required Windows tests passed"
Loading
Loading