Spaces:
Running
Running
File size: 7,620 Bytes
85920d3 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 | import asyncio, json, pathlib, csv
from playwright.async_api import async_playwright
ROOT=pathlib.Path(__file__).parent
async def main():
async with async_playwright() as p:
browser=await p.chromium.launch(headless=True,executable_path='/usr/bin/chromium',args=['--no-sandbox'])
page=await browser.new_page(viewport={'width':1512,'height':1060},accept_downloads=True)
errors=[]
page.on('pageerror', lambda exc: errors.append(str(exc)))
source=(ROOT/'index.html').read_text()
# Set content, then add source scripts, intercept JSON responses using a fetch shim.
await page.set_content(source, wait_until='domcontentloaded')
await page.add_style_tag(content=(ROOT/'styles.css').read_text())
for script in (ROOT/'engine.js',): await page.add_script_tag(content=script.read_text())
source_json=(ROOT/'evaluation_snapshots.json').read_text()
manifest=(ROOT/'benchmark_manifest.json').read_text()
await page.evaluate('''({data,manifest}) => { const f = window.fetch; window.fetch = async (url) => {
if(String(url).includes('evaluation_snapshots.json')) return {ok:true,json:async()=>JSON.parse(data)};
if(String(url).includes('benchmark_manifest.json')) return {ok:true,json:async()=>JSON.parse(manifest)};
return f(url);
}}''',{'data':source_json,'manifest':manifest})
await page.add_script_tag(content=(ROOT/'app.js').read_text())
await page.locator('.metric').first.wait_for(timeout=10000)
checks=[]
async def ck(label,cond):
if not cond: raise AssertionError(label)
checks.append(label)
print('PASS',label)
await ck('initial overview page', await page.locator('h2').first.inner_text()=='Evaluation overview')
await ck('736 prediction records', '736' in await page.locator('#heroN').inner_text())
await ck('initial gate warning visible', 'release check' in (await page.locator('#panel').inner_text()).lower())
await ck('hybrid initial metrics 77.8', '77.8%' in await page.locator('#panel').inner_text())
await page.locator('#methodSelect').select_option('nb')
await ck('model selector updates to naive bayes', '74.1%' in await page.locator('#panel').inner_text())
await page.locator('#splitSelect').select_option('iid')
await ck('split selector 100 percent baseline', '100.0%' in await page.locator('#panel').inner_text())
await page.locator('[data-view="drift"]').click()
await ck('drift section shows PSI and JSD', 'Text-length PSI' in await page.locator('#panel').inner_text() and 'Language JSD' in await page.locator('#panel').inner_text())
await page.locator('[data-view="slices"]').click()
await ck('slice view has language controls', await page.locator('#sliceBy').count()==1)
await page.locator('#sliceBy').select_option('truth')
await ck('slice view label option', 'Six rhetorical classes' not in await page.locator('#panel').inner_text() and 'background' in await page.locator('#panel').inner_text())
await page.locator('[data-view="errors"]').click()
await ck('confusion matrix visible', 'CONFUSION MATRIX' in await page.locator('#panel').inner_text())
await page.locator('#splitSelect').select_option('challenge')
await ck('challenge examples show errors', await page.locator('span.tag.bad').count()>0)
await page.locator('#errorBy').select_option('limitation')
await ck('error filter changes view', 'Misclassifications' in await page.locator('#panel').inner_text())
await page.locator('[data-view="regression"]').click()
await ck('paired model compare n54', 'Matched example IDs' in await page.locator('#panel').inner_text())
await page.locator('#compareMethod').select_option('word')
await ck('paired method updates', 'Word TF-IDF' in await page.locator('#panel').inner_text())
await page.locator('[data-view="gates"]').click()
await ck('default release gates fail', 'CONFIGURED CHECKS FAIL' in await page.locator('#panel').inner_text())
await page.locator('#tPSI').fill('1.0')
await page.locator('#tGap').fill('30')
await page.locator('#tAccuracy').fill('70')
await page.locator('#applyGates').click()
await ck('thresholds change gate view without modifying data', 'CONFIGURED CHECKS PASS' in await page.locator('#panel').inner_text())
await page.locator('#resetGates').click()
await ck('reset restores research defaults', 'CONFIGURED CHECKS FAIL' in await page.locator('#panel').inner_text())
await page.locator('[data-view="registry"]').click()
await ck('registry lists SHA256', 'evaluationSha256' in await page.locator('#panel').inner_text())
await ck('registry shows lineage', 'Academic Rhetorical Intent Mini' in await page.locator('#panel').inner_text())
await page.locator('[data-view="export"]').click()
async with page.expect_download() as d:
await page.locator('[data-download="rows"]').click()
dl=await d.value
await ck('CSV export generated',dl.suggested_filename.endswith('.csv'))
async with page.expect_download() as d:
await page.locator('[data-download="session"]').click()
dl=await d.value
await ck('full JSON session downloaded',dl.suggested_filename.endswith('.json'))
async with page.expect_download() as d:
await page.locator('[data-download="report"]').click()
dl=await d.value
await ck('Markdown audit report downloaded',dl.suggested_filename.endswith('.md'))
async with page.expect_download() as d:
await page.locator('[data-download="template"]').click()
dl=await d.value
await ck('CSV import template downloaded', 'template' in dl.suggested_filename)
await page.locator('#inputFile').set_input_files(files={'name':'custom.json','mimeType':'application/json','buffer':json.dumps({'rows':[dict(id='custom1',split='challenge',method='nb',language='en',domain='test',truth='background',pred='background',tokenCount=4)]}).encode()})
await page.locator('#importBtn').click()
await page.wait_for_timeout(150);await ck('user import applied', '1' in await page.locator('#heroN').inner_text() and 'Imported 1 rows' in await page.locator('#notice').inner_text())
await page.locator('[data-view="export"]').click()
await page.locator('#restoreBtn').click()
await ck('restores original dataset', '736' in await page.locator('#heroN').inner_text())
await page.locator('#methodSelect').select_option('hybrid')
await page.locator('#notice').evaluate('(el)=>el.hidden=true')
await page.set_viewport_size({'width':390,'height':844})
await page.screenshot(path='/mnt/data/ModelGuard_Observatory_MOBILE_PREVIEW.png',full_page=True)
await ck('mobile viewport does not overflow', await page.evaluate('document.documentElement.scrollWidth <= window.innerWidth + 3'))
await ck('navigation persists on mobile', await page.locator('[data-view="drift"]').is_visible())
await page.set_viewport_size({'width':1512,'height':1050})
await page.locator('[data-view="overview"]').click()
await page.screenshot(path='/mnt/data/ModelGuard_Observatory_DESKTOP_PREVIEW.png',full_page=True)
await ck('no browser JavaScript errors', not errors)
print('BROWSER TESTS',len(checks),'PASS')
await browser.close()
asyncio.run(main())
|