#!/usr/bin/env python3
"""Execute the actual offline room page in Chromium with bounded HTTP mocks."""
import html
import json
import os
from pathlib import Path
import re
import subprocess
import tempfile
import unittest
from test_webconfig_ui_runtime import BROWSER, run_browser
ROOT = Path(__file__).resolve().parents[1]
HEADER = ROOT / "src/helpers/esp32/RoomWebHtml.h"
BOUNDARY = ROOT / "test/fixtures/room_web_service/boundary.json"
COMMON = r'''
const boundary=__BOUNDARY__,calls=[];
localStorage.setItem('mc-room-token','01'.repeat(32));localStorage.setItem('mc-room-sequence','0');
window.attack=()=>document.body.dataset.testAttacked='yes';
window.addEventListener('error',e=>document.body.dataset.testJsError=e.message);
window.addEventListener('unhandledrejection',e=>document.body.dataset.testJsError=String(e.reason));
const response=(value,status=200)=>Promise.resolve({ok:status>=200&&status<300,status:status,json:()=>Promise.resolve(value)});
const until=async predicate=>{for(let i=0;i<500;i++){if(predicate())return;await new Promise(r=>setTimeout(r,10))}throw Error('test condition timed out')};
const submit=id=>document.getElementById(id).dispatchEvent(new Event('submit',{bubbles:true,cancelable:true}));
const record=(url,options)=>{let p=options.body?JSON.parse(options.body):null;calls.push({url:url,body:options.body||'',seq:options.headers['X-Room-Seq'],token:options.headers['X-Room-Token'],op:p?p.op:'result'});return p};
const mark=(key,value)=>document.body.setAttribute('data-test-'+key,String(value));
'''
ADMIN_COMMON = r'''
const radioKey='ab'.repeat(32),otherKey='ab'.repeat(6)+'cd'.repeat(26);
const radioUser=(key=radioKey,extra={})=>Object.assign({key:key,role:1,retained:true,active:true,heard_ago:12,pending_count:4,
delivery:'post',failures:0,outpath:'A1',altpath:'B1',observed:'A2',observed_pending:false,sync_since:100,
pending_post:101,topic_pending:0,ack_wait_ms:700,banned:false},extra);
const adminPage=(users,next=null)=>({users:users,next:next,total:3,active:2,backlog:6,pending:1,failed:1,boot:71});
const baseRoom=p=>p.op==='status'?response(Object.assign({},boundary.status,{role:3})):p.op==='posts'?response({post:null}):p.op==='board.index'?response({revision:0,articles:[],next:255}):null;
const joinedRoom=async()=>{submit('join');await until(()=>!$('room').hidden&&$('notices').textContent==='No notices published.')};
'''
class RoomWebUiTest(unittest.TestCase):
def run_page(self, scenario, virtual_time=7000):
if not BROWSER:
if os.environ.get("MESHCORE_REQUIRE_ROOM_BROWSER") == "1":
self.fail("Chromium is required for room browser validation")
self.skipTest("Chromium-family browser is unavailable")
source = HEADER.read_text().split('R"roomhtml(', 1)[1].split(')roomhtml";', 1)[0]
transform = getattr(self, "page_transform", None)
if transform:
source = transform(source)
fixture = json.loads(BOUNDARY.read_text())
prelude = ""
self.assertIn("