READ-ONLY PACKAGE PREVIEW

playwright-cli/examples/run_cli_fixture.py

Version b85c7a736bb4.bb1 · Apache-2.0. This preview displays packaged text and does not execute code. Treat the contents as untrusted instructions.

← Return to resource and package checksum

"""Native CLI fixture; no AI client is executed. Apache-2.0, BB Skills 2026."""
import argparse
import datetime as dt
import hashlib
import json
import pathlib
import platform
import re
import subprocess
from urllib.parse import urlsplit

parser = argparse.ArgumentParser()
parser.add_argument('--node', default='node')
parser.add_argument('--cli-script', required=True)
parser.add_argument('--session', required=True, help='An already open, authorized browser session')
parser.add_argument('--output-dir', default='output/playwright/fixture-v46')
parser.add_argument('--base-url', default='http://127.0.0.1:8767')
args = parser.parse_args()
assert urlsplit(args.base_url).hostname in {'127.0.0.1', 'localhost'}, 'Fixture must be local'
output = pathlib.Path(args.output_dir)
output.mkdir(parents=True, exist_ok=True)
cases = []
owned = []
route_installed = False
prefix = [args.node, args.cli_script, '-s=' + args.session]

def invoke(*command, expected_error=False):
    result = subprocess.run(prefix + list(command), capture_output=True, encoding='utf-8', errors='replace', timeout=35)
    error = '### Error' in result.stdout or result.returncode != 0
    if expected_error:
        assert error, 'Expected CLI error was not observed'
    else:
        assert not error, 'Native CLI failed: ' + command[0]
    # Never persist complete output: tab lists may include private user pages.
    return result.stdout, result.returncode

def result_value(stdout):
    match = re.search(r'### Result\r?\n', stdout)
    assert match, 'Missing native CLI result'
    return json.JSONDecoder().raw_decode(stdout[match.end():].lstrip())[0]

def evaluate(expression):
    return result_value(invoke('eval', expression)[0])

def tabs():
    text = invoke('tab-list')[0]
    return {int(index):url for index,url in re.findall(r'^- (\d+):(?: \(current\))? \[.*?\]\((.*?)\)$', text, re.M)}

def observe(name, **details):
    cases.append({'name':name, 'status':'passed', 'observations':details})

def snapshot(name):
    path = output / name
    invoke('snapshot', '--filename=' + str(path))
    return path.read_text(encoding='utf-8')

def reference(text, label):
    matches = re.findall(r'(?:textbox|combobox|checkbox|button) "' + re.escape(label) + r'" \[ref=([^\]]+)\]', text)
    assert len(matches) == 1, 'Ambiguous fixture reference: ' + label
    return matches[0]

before = tabs()
assert before, 'An authorized existing browser session is required; no fallback is opened'
cli_version = subprocess.check_output([args.node,args.cli_script,'--version'], encoding='utf-8').strip()
node_version = subprocess.check_output([args.node,'--version'], encoding='utf-8').strip()
try:
    invoke('tab-new', args.base_url + '/index.html')
    after = tabs()
    added = set(after) - set(before)
    assert len(added) == 1
    fixture_tab = added.pop()
    owned.append(fixture_tab)
    text = snapshot('initial.yml')
    assert 'Browser command fixture' in text
    initial_motion = evaluate("({reduced:matchMedia('(prefers-reduced-motion: reduce)').matches, animation:getComputedStyle(document.querySelector('.dot')).animationName})")
    browser_agent = evaluate('navigator.userAgent')
    observe('snapshot_accessible_refs', display_name_ref_found=bool(reference(text,'Display name')), checkbox_ref_found=bool(reference(text,'Use synthetic data only')))
    invoke('fill',reference(text,'Display name'),'Fixture Analyst')
    assert evaluate("document.getElementById('name').value") == 'Fixture Analyst'
    observe('fill_synthetic_text', value='Fixture Analyst')
    invoke('select',reference(text,'Review role'),'Reviewer')
    assert evaluate("document.getElementById('role').value") == 'Reviewer'
    observe('select_native_option', value='Reviewer')
    invoke('check',reference(text,'Use synthetic data only'))
    assert evaluate("document.getElementById('scope').checked") is True
    observe('check_synthetic_scope', checked=True)
    invoke('click',reference(text,'Save local example'))
    text = snapshot('saved.yml')
    assert 'Saved locally for Fixture Analyst (Reviewer).' in text
    observe('submit_local_form_status', status='Saved locally for Fixture Analyst (Reviewer).', external_submission=False)
    focus_script = output / 'focus.js'
    focus_script.write_text("async page => { await page.getByRole('textbox',{name:'Display name',exact:true}).focus(); return {focused:true}; }\n",encoding='utf-8')
    invoke('run-code','--filename=' + str(focus_script))
    invoke('press','Tab')
    assert evaluate('document.activeElement.id') == 'role'
    observe('keyboard_tab_focus', next_element='role')
    mocked = {'ideas':['synthetic mocked idea']}
    invoke('route',args.base_url + '/api/ideas','--body=' + json.dumps(mocked))
    route_installed = True
    text = snapshot('before-request.yml')
    invoke('click',reference(text,'Load ideas'))
    wait_script = output / 'wait-mock.js'
    wait_script.write_text("async page => { await page.locator('#ideas-result').filter({hasText:'synthetic mocked idea'}).waitFor(); return JSON.parse(await page.locator('#ideas-result').innerText()); }\n",encoding='utf-8')
    assert result_value(invoke('run-code','--filename=' + str(wait_script))[0]) == mocked
    observe('route_local_json_response', mocked=mocked, third_party_network=False)
    invoke('unroute',args.base_url + '/api/ideas')
    route_installed = False
    invoke('click',reference(text,'Load ideas'))
    default_script = output / 'wait-default.js'
    default_script.write_text("async page => { await page.locator('#ideas-result').filter({hasText:'local default'}).waitFor(); return JSON.parse(await page.locator('#ideas-result').innerText()); }\n",encoding='utf-8')
    assert result_value(invoke('run-code','--filename=' + str(default_script))[0]) == {'ideas':['local default']}
    observe('unroute_restores_local_server', actual={'ideas':['local default']})
    invoke('set-reduced-motion','reduce')
    assert evaluate("getComputedStyle(document.querySelector('.dot')).animationName") == 'none'
    observe('reduced_motion_css', animation='none')
    invoke('clear-reduced-motion')
    restored_motion = evaluate("({reduced:matchMedia('(prefers-reduced-motion: reduce)').matches, animation:getComputedStyle(document.querySelector('.dot')).animationName})")
    assert restored_motion == initial_motion
    observe('media_override_restored', baseline_restored=True)
    invoke('resize','390','844')
    dimensions = evaluate('({viewport:innerWidth,document:document.documentElement.scrollWidth})')
    assert dimensions['viewport'] == 390 and dimensions['document'] <= dimensions['viewport']
    observe('mobile_fixture_no_horizontal_overflow', **dimensions)
    invoke('screenshot','--filename=' + str(output / 'mobile.png'))
    assert (output / 'mobile.png').stat().st_size > 1000
    observe('fixture_screenshot_created', bytes=(output / 'mobile.png').stat().st_size)
    invoke('click','e999999',expected_error=True)
    observe('missing_reference_error_detected', expected_rejection=True)
    invoke('tab-new',args.base_url + '/other.html')
    latest = tabs()
    second = set(latest) - set(after)
    assert len(second) == 1
    second_tab = second.pop()
    owned.append(second_tab)
    assert evaluate('document.title') == 'Second local fixture page'
    invoke('tab-close',str(second_tab))
    owned.remove(second_tab)
    invoke('tab-select',str(fixture_tab))
    assert evaluate('document.title') == 'BB Skills browser command fixture'
    observe('second_fixture_tab_closed_individually', fixture_restored=True)
finally:
    # Cleanup only the tabs and exact route created by this runner.
    if route_installed:
        invoke('tab-select',str(fixture_tab))
        invoke('unroute',args.base_url + '/api/ideas')
    if owned:
        invoke('tab-select',str(fixture_tab))
        invoke('clear-reduced-motion')
        invoke('resize','1440','900')
    for index in sorted(owned, reverse=True):
        invoke('tab-close',str(index))
after_cleanup = tabs()
assert before == after_cleanup, 'Existing user tabs changed'
observe('existing_user_tabs_preserved', existing_tabs=len(before), remaining_tabs=len(after_cleanup))
root = pathlib.Path(__file__).parent
source_hashes = {name:hashlib.sha256((root / name).read_bytes()).hexdigest() for name in ['index.html','other.html','serve_fixture.py','run_cli_fixture.py']}
evidence = {
  'executed_at':dt.datetime.now(dt.timezone.utc).isoformat(),
  'native_browser_command_fixture_tested':True,
  'ai_client_executed':False,
  'runtime_tested':False,
  'production_tested':False,
  'live_account_login_tested':False,
  'cookies_exported':False,
  'profile_credentials_read':False,
  'browser_alternative_opened':False,
  'profile_mode':'Existing user-authorized persistent Chrome profile; no launch or alternate profile',
  'environment':{'cli':cli_version,'node':node_version,'python':platform.python_version(),'platform':platform.system(),'browser_user_agent':browser_agent},
  'fixture':{'loopback_only':True,'external_service':False,'synthetic_inputs':True,'third_party_requests_mocked':False},
  'source_hashes':source_hashes,
  'observations':len(cases),'cases':cases,
  'existing_user_tabs_preserved':True,
  'artifacts_contain_private_tab_urls':False,
  'cleanup_completed':True,
}
(root / 'native-browser-evidence.json').write_text(json.dumps(evidence,indent=2),encoding='utf-8',newline='\n')
print(json.dumps({'observations':len(cases),'cli':cli_version,'native_fixture':True,'full_skill_runtime':False,'existing_tabs_preserved':True,'evidence':str(root / 'native-browser-evidence.json')}))