Configure Oxygit Pages and add browser smoke test
OpenClaw Engineer committed 2026-09-04 03:17:37 +0000

Analyzing diff...

.oxygit/ci.yml+9 −0
new file mode 100644
index 0000000..2537275
--- /dev/null
+++ b/.oxygit/ci.yml
@@ -0,0 +1,9 @@
+stages: [deploy]
+
+pages:
+  stage: deploy
+  script:
+    - mkdir -p public
+    - cp index.html week1.html week2.html week3.html style.css app.js week.js .nojekyll public/
+  pages:
+    path: public
tests/smoke.mjs+34 −0
new file mode 100644
index 0000000..3357a1e
--- /dev/null
+++ b/tests/smoke.mjs
@@ -0,0 +1,34 @@
+const base=process.argv[2]||'http://127.0.0.1:8765';
+const port=process.argv[3]||'9223';
+const tabs=await (await fetch(`http://127.0.0.1:${port}/json`)).json();
+const ws=new WebSocket(tabs[0].webSocketDebuggerUrl);
+await new Promise((ok,no)=>{ws.onopen=ok;ws.onerror=no});
+let seq=0,pending=new Map(),events=[];
+ws.onmessage=({data})=>{const m=JSON.parse(data);if(m.id){pending.get(m.id)?.(m);pending.delete(m.id)}else events.push(m)};
+const send=(method,params={})=>new Promise((ok,no)=>{const id=++seq;pending.set(id,m=>m.error?no(m.error):ok(m.result));ws.send(JSON.stringify({id,method,params}))});
+const evaluate=async expression=>(await send('Runtime.evaluate',{expression,awaitPromise:true,returnByValue:true})).result.value;
+await send('Runtime.enable');await send('Page.enable');
+const results=[];
+for(const page of ['index.html','week1.html','week2.html','week3.html']){
+  events=[];
+  await send('Emulation.setDeviceMetricsOverride',{width:390,height:844,deviceScaleFactor:1,mobile:true});
+  await send('Page.navigate',{url:`${base}/${page}`});
+  await new Promise(r=>setTimeout(r,1200));
+  const data=await evaluate(`(()=>({
+    title:document.title,
+    pageErrors:performance.getEntriesByType('resource').filter(x=>x.name.includes('week.js')||x.name.includes('app.js')).map(x=>({url:x.name,status:x.responseStatus})),
+    overflow:document.documentElement.scrollWidth>document.documentElement.clientWidth,
+    iframes:document.querySelectorAll('iframe').length,
+    fallbacks:document.querySelectorAll('a.fallback').length,
+    days:document.querySelectorAll('.day').length
+  }))()`);
+  const exceptions=events.filter(x=>x.method==='Runtime.exceptionThrown').length;
+  results.push({page,...data,exceptions});
+}
+await send('Page.navigate',{url:`${base}/week1.html`});await new Promise(r=>setTimeout(r,700));
+const persistence=await evaluate(`(async()=>{const c=document.querySelector('.main-done');c.click();document.querySelector('.note').value='smoke';document.querySelector('.note').dispatchEvent(new Event('input',{bubbles:true}));return {checked:c.checked,saved:localStorage.getItem('sekta:nastenka:week1:d1-main'),note:localStorage.getItem('sekta:nastenka:week1:d1-note'),celebrate:document.querySelector('.celebrate').classList.contains('show')}})()`);
+await send('Page.reload');await new Promise(r=>setTimeout(r,700));
+const restored=await evaluate(`({checked:document.querySelector('.main-done').checked,note:document.querySelector('.note').value,progress:document.querySelector('.progress-value').textContent})`);
+console.log(JSON.stringify({results,persistence,restored},null,2));
+ws.close();
+if(results.some(x=>x.exceptions||x.overflow||!x.title)||results.slice(1).some(x=>x.iframes!==6||x.fallbacks!==6||x.days!==3)||!persistence.celebrate||!restored.checked||restored.note!=='smoke')process.exitCode=1;