"""Явно изолированный DOM + тестовый транспорт Node; не native browser Web Crypto."""
import asyncio,datetime,hashlib,json,traceback
from pathlib import Path
from playwright.async_api import async_playwright
from офлайн_Node_мост import ROOT,BROWSER,open_offline
E=ROOT/'доказательства/редакция-4.10.0'; rows=[]
async def main():
 async with async_playwright() as p:
  b=await p.chromium.launch(executable_path=BROWSER,headless=True,args=['--no-sandbox']);page,errors,_=await open_offline(b,'пакет-обжалования.html',390);page.set_default_timeout(15000)
  async def test(name,fn):
   try:
    detail=await fn();rows.append({'проверка':name,'пройдено':True,'результат':detail})
   except Exception:rows.append({'проверка':name,'пройдено':False,'ошибка':traceback.format_exc()})
   print(name,rows[-1]['пройдено'],flush=True)
  async def imported():
   await page.locator('#импорт-дела').set_input_files({'name':'ИС-два-времени.json','mimeType':'application/json','buffer':(E/'ИС-дело-два-времени.json').read_bytes()})
   await page.wait_for_function("document.querySelector('#история-событий').textContent.includes('ИС-ПОЗДНОЕ')")
   await page.locator('#дело-дата').fill('2026-09-03');await page.locator('#дело-дата').dispatch_event('change')
   return 'Точная искусственная папка принята; выбран ранний день.'
  await test('Положительный импорт и выбор раннего среза',imported)
  old=await page.locator('#история-событий').inner_text()
  async def export():
   before=await page.evaluate('__saved.length');await page.locator('#объяснить-остатки').click();await page.wait_for_function(f"__saved.length>{before} || document.querySelector('#статус-дела').textContent.includes('Объяснение не сформировано')")
   assert 'Объяснение остатков подготовлено' in await page.locator('#статус-дела').inner_text(),await page.locator('#статус-дела').inner_text()
   return json.loads(await page.evaluate('async()=>await __saved.at(-1).blob.text()'))
  early=None
  async def ordinary():
   nonlocal early
   early=await export();assert 'позднее_внесение' not in early;assert old==await page.locator('#история-событий').inner_text();return 'Дополнительное знание не включается по умолчанию.'
  await test('Пустое позднее время не раскрывает поздние опоры',ordinary)
  async def late():
   await page.locator('#позднее-знание').fill('2026-09-04T12:00:00.000Z');out=await export();extra=out.pop('позднее_внесение');assert [e['идентификатор'] for e in extra['события']]==['ИС-ПОЗДНОЕ','ИС-ПОСЛЕ-СРЕЗА'];out.pop('ша256');base={k:v for k,v in early.items() if k!='ша256'};assert out==base;assert old==await page.locator('#история-событий').inner_text();assert all(e['источник'] and e['документ'] and e['причина'] for e in extra['события']);return 'Полный экспорт сохраняет ранние поля; поздние опоры добавлены отдельным разделом.'
  await test('Явное позднее знание меняет только дополнительный раздел и отпечаток',late)
  async def bad():
   before=await page.evaluate('__saved.length');await page.locator('#позднее-знание').fill('2026-09-02T12:00:00.000Z');await page.locator('#объяснить-остатки').click();await page.wait_for_function("document.querySelector('#статус-дела').textContent.includes('Объяснение не сформировано')");assert before==await page.evaluate('__saved.length');assert old==await page.locator('#история-событий').inner_text();await page.locator('#позднее-знание').fill('');await export();return 'Отказ не добавил передачу; повтор без позднего контекста успешен.'
  await test('Неверный порядок времён, сохранность истории и повтор',bad)
  await page.locator('#позднее-знание').scroll_into_view_if_needed();await page.screenshot(path=str(E/'два-времени-интерфейс-390.png'));await b.close()
 report={'редакция':'4.10.0-wip','UTC':datetime.datetime.now(datetime.timezone.utc).isoformat(),'всего':len(rows),'пройдено':sum(x['пройдено'] for x in rows),'проверки':rows,'ошибки_страницы':errors,'сценарий_SHA256':hashlib.sha256(Path(__file__).read_bytes()).hexdigest(),'команда':'python инструменты/испытать-позднее-знание-интерфейса-4-10.py','предел':'Изолированный DOM с подменами fetch/digest/storage/Blob и тестовым мостом к настоящему Node Worker. Мост не подтверждает время стадий, native Worker/Crypto, реальное скачивание или печать.'}
 (E/'позднее-знание-интерфейса.json').write_text(json.dumps(report,ensure_ascii=False,indent=2)+'\n');return report['всего']==report['пройдено'] and not errors
if __name__=='__main__':raise SystemExit(0 if asyncio.run(main()) else 1)
