111 lines
4.8 KiB
Python
111 lines
4.8 KiB
Python
#!/usr/bin/env python3
|
|
"""V136 E2E - Click banner, modal opens with broken URLs, Escape closes"""
|
|
import asyncio, json, os
|
|
from playwright.async_api import async_playwright
|
|
|
|
OUT = "/var/www/html/api/blade-tasks/v136-health-modal-proof"
|
|
os.makedirs(OUT, exist_ok=True)
|
|
|
|
async def main():
|
|
async with async_playwright() as p:
|
|
browser = await p.chromium.launch(headless=True, args=['--no-sandbox'])
|
|
ctx = await browser.new_context(viewport={'width':1920,'height':1080}, record_video_dir=OUT)
|
|
page = await ctx.new_page()
|
|
errs = []
|
|
page.on('pageerror', lambda e: errs.append(str(e)))
|
|
|
|
await page.goto("https://weval-consulting.com/all-ia-hub.html?v=v136", wait_until='load', timeout=30000)
|
|
await page.wait_for_timeout(3500) # wait for kpi fetch
|
|
|
|
# Initial: modal hidden
|
|
initial = await page.evaluate("""() => {
|
|
const modal = document.getElementById('v136-health-modal');
|
|
const banner = document.getElementById('v135-kpi-live');
|
|
return {
|
|
modal_exists: !!modal,
|
|
modal_display: modal?.style.display,
|
|
banner_cursor: banner ? getComputedStyle(banner).cursor : null,
|
|
banner_text: banner?.textContent
|
|
};
|
|
}""")
|
|
print("Initial:", json.dumps(initial, indent=2))
|
|
|
|
# Click banner
|
|
await page.click('#v135-kpi-live')
|
|
await page.wait_for_timeout(2000) # wait for fetch
|
|
|
|
after_click = await page.evaluate("""() => {
|
|
const modal = document.getElementById('v136-health-modal');
|
|
const summary = document.getElementById('v136-modal-summary');
|
|
const content = document.getElementById('v136-modal-content');
|
|
return {
|
|
modal_display: modal?.style.display,
|
|
summary_text: summary?.textContent,
|
|
content_html_preview: content?.innerHTML?.substring(0, 400),
|
|
broken_count: (content?.innerHTML?.match(/BROKEN/g) || []).length,
|
|
has_urls: content?.innerHTML?.includes('http')
|
|
};
|
|
}""")
|
|
print("After click:", json.dumps(after_click, indent=2))
|
|
await page.screenshot(path=f"{OUT}/01-modal-open.png", full_page=False)
|
|
|
|
# Press Escape
|
|
await page.keyboard.press('Escape')
|
|
await page.wait_for_timeout(500)
|
|
|
|
after_esc = await page.evaluate("""() => ({
|
|
modal_display: document.getElementById('v136-health-modal')?.style.display
|
|
})""")
|
|
print("After Escape:", json.dumps(after_esc))
|
|
|
|
# Click again to test reopen
|
|
await page.click('#v135-kpi-live')
|
|
await page.wait_for_timeout(1500)
|
|
reopen = await page.evaluate("""() => ({
|
|
modal_display: document.getElementById('v136-health-modal')?.style.display
|
|
})""")
|
|
print("Reopen:", json.dumps(reopen))
|
|
|
|
# Click outside to dismiss
|
|
await page.click('#v136-health-modal', position={'x': 10, 'y': 10})
|
|
await page.wait_for_timeout(500)
|
|
outside_click = await page.evaluate("""() => ({
|
|
modal_display: document.getElementById('v136-health-modal')?.style.display
|
|
})""")
|
|
print("Click outside:", json.dumps(outside_click))
|
|
|
|
await ctx.close()
|
|
await browser.close()
|
|
|
|
verdict = 'OK' if (
|
|
initial['modal_exists'] and
|
|
initial['modal_display'] == 'none' and
|
|
initial['banner_cursor'] == 'pointer' and
|
|
after_click['modal_display'] == 'flex' and
|
|
after_click['has_urls'] and
|
|
after_esc['modal_display'] == 'none' and
|
|
reopen['modal_display'] == 'flex' and
|
|
outside_click['modal_display'] == 'none' and
|
|
not errs
|
|
) else 'PARTIAL'
|
|
|
|
report = {
|
|
'v136': 'health-modal-drill-down',
|
|
'modal_exists': initial['modal_exists'],
|
|
'banner_clickable': initial['banner_cursor'] == 'pointer',
|
|
'hidden_initially': initial['modal_display'] == 'none',
|
|
'opens_on_click': after_click['modal_display'] == 'flex',
|
|
'fetches_broken_urls': after_click['has_urls'],
|
|
'content_preview': after_click['content_html_preview'][:200] if after_click['content_html_preview'] else '',
|
|
'escape_closes': after_esc['modal_display'] == 'none',
|
|
'reopen_works': reopen['modal_display'] == 'flex',
|
|
'click_outside_closes': outside_click['modal_display'] == 'none',
|
|
'js_errors': errs,
|
|
'VERDICT': verdict
|
|
}
|
|
with open(f"{OUT}/proof.json",'w') as f: json.dump(report, f, indent=2)
|
|
print("=== VERDICT:", verdict)
|
|
print(json.dumps(report, indent=2))
|
|
|
|
asyncio.run(main())
|