import asyncio,json,datetime,hashlib
from pathlib import Path
from playwright.async_api import async_playwright
from офлайн_стенд import ROOT,BROWSER,open_offline
E=ROOT/'доказательства/редакция-4.13.0'
HOLD="""const old=window.fetch;let release;const barrier=new Promise(r=>release=r);window.__releaseSchemas=release;window.fetch=async(u,o)=>{if(String(u).includes('профиль-схем-4.13.0'))await barrier;return old(u,o)};"""
async def main():
 rows=[]
 async with async_playwright() as p:
  b=await p.chromium.launch(executable_path=BROWSER,headless=True,args=['--no-sandbox']);page,errors,req=await open_offline(b,'переносимый-аудит.html',390,HOLD,wait_ready=False)
  rows.append({'сценарий':'Во время ожидания форма обозначена занятой','пройдено':await page.locator('main').get_attribute('aria-busy')=='true'})
  await page.locator('[data-action="экспорт-панели"]').click();rows.append({'сценарий':'Преждевременный экспорт не выполняется','пройдено':await page.evaluate('__saved.length')==0 and 'не подготовлена' in await page.locator('.методика-статус').inner_text()})
  await page.locator('#аудит-дата').focus();old=await page.evaluate('document.activeElement.id');await page.keyboard.press('Tab');new=await page.evaluate('document.activeElement.id');rows.append({'сценарий':'Tab не заперт окном подготовки','пройдено':old!=new,'до':old,'после':new})
  await page.evaluate('__releaseSchemas()');await page.wait_for_function("document.querySelector('main').getAttribute('aria-busy')==='false'",timeout=10000)
  rows.append({'сценарий':'После подготовки 20 полей прав и декоративные карточки сосуществуют без ошибки','пройдено':await page.locator('#права-аудита article').count()==20 and not errors and 'Форма готова' in await page.locator('.методика-статус').inner_text()})
  await page.close()
  bad="window.fetch=async()=>{throw Error('ИС: разрыв подготовки')};"
  page,errors,req=await open_offline(b,'переносимый-аудит.html',390,bad);rows.append({'сценарий':'Ошибка подготовки не означает готовую пустую форму','пройдено':'Инструмент не запущен' in await page.locator('.методика-статус').inner_text() and await page.locator('main').get_attribute('aria-busy')=='false'});await page.close()
  page,errors,req=await open_offline(b,'переносимый-аудит.html',390);rows.append({'сценарий':'Повтор в новом изолированном документе после отказа проходит','пройдено':'Форма готова' in await page.locator('.методика-статус').inner_text() and not errors});await page.close();await b.close()
 report={'редакция':'4.13.0-wip','UTC':datetime.datetime.now(datetime.timezone.utc).isoformat(),'команда':'python инструменты/испытать-окно-подготовки-4-13.py','риск':'Срабатывание до схем, немой отказ, декоративные карточки как поля, клавиатурная ловушка.','сценарий_SHA256':hashlib.sha256(Path(__file__).read_bytes()).hexdigest(),'результаты':rows,'всего':len(rows),'пройдено':sum(x['пройдено'] for x in rows),'предел':'Изолированный DOM с искусственным ожиданием и транспортом. Один Tab — не полный клавиатурный маршрут. Новый документ — не подтверждение системной перезагрузки или настоящих вкладок.'};(E/'окно-подготовки.json').write_text(json.dumps(report,ensure_ascii=False,indent=2));print(json.dumps(report,ensure_ascii=False));return all(x['пройдено'] for x in rows)
if __name__=='__main__':raise SystemExit(0 if asyncio.run(main()) else 1)
