|
| 1 | +{ |
| 2 | + "version": 1, |
| 3 | + "cases": [ |
| 4 | + { |
| 5 | + "id": "dense-form-submit", |
| 6 | + "description": "Fill 36 fields, submit the form, and verify every controlled value on each iteration.", |
| 7 | + "html": "<!doctype html><html><head><title>Dense Form</title><style>body{font:14px sans-serif}#fields{display:grid;grid-template-columns:repeat(4,1fr);gap:8px}label{display:flex;flex-direction:column}output{display:block;margin-top:16px;font-weight:bold}</style></head><body><main><h1>Account migration</h1><form id='bulk-form'><div id='fields'></div><button id='submit' type='button'>Submit migration</button><output id='status'>pending</output></form></main><script>const fields=document.querySelector('#fields');fields.innerHTML=Array.from({length:36},(_,index)=>'<label>Field '+String(index+1).padStart(2,'0')+'<input id=\\'field-'+String(index+1).padStart(2,'0')+'\\' name=\\'field-'+String(index+1).padStart(2,'0')+'\\'></label>').join('');document.querySelector('#submit').addEventListener('click',()=>{const values=Array.from(document.querySelectorAll('#fields input'),input=>input.value);document.querySelector('#status').textContent='submitted:'+values.filter(Boolean).length;document.body.dataset.submissions=String(Number(document.body.dataset.submissions||0)+1);});</script></body></html>", |
| 8 | + "repeat": 3, |
| 9 | + "steps": [ |
| 10 | + { "op": "goto", "useCaseHtml": true, "waitUntil": "load" }, |
| 11 | + { "op": "fill", "selector": "#field-01", "value": "value-01" }, |
| 12 | + { "op": "fill", "selector": "#field-02", "value": "value-02" }, |
| 13 | + { "op": "fill", "selector": "#field-03", "value": "value-03" }, |
| 14 | + { "op": "fill", "selector": "#field-04", "value": "value-04" }, |
| 15 | + { "op": "fill", "selector": "#field-05", "value": "value-05" }, |
| 16 | + { "op": "fill", "selector": "#field-06", "value": "value-06" }, |
| 17 | + { "op": "fill", "selector": "#field-07", "value": "value-07" }, |
| 18 | + { "op": "fill", "selector": "#field-08", "value": "value-08" }, |
| 19 | + { "op": "fill", "selector": "#field-09", "value": "value-09" }, |
| 20 | + { "op": "fill", "selector": "#field-10", "value": "value-10" }, |
| 21 | + { "op": "fill", "selector": "#field-11", "value": "value-11" }, |
| 22 | + { "op": "fill", "selector": "#field-12", "value": "value-12" }, |
| 23 | + { "op": "fill", "selector": "#field-13", "value": "value-13" }, |
| 24 | + { "op": "fill", "selector": "#field-14", "value": "value-14" }, |
| 25 | + { "op": "fill", "selector": "#field-15", "value": "value-15" }, |
| 26 | + { "op": "fill", "selector": "#field-16", "value": "value-16" }, |
| 27 | + { "op": "fill", "selector": "#field-17", "value": "value-17" }, |
| 28 | + { "op": "fill", "selector": "#field-18", "value": "value-18" }, |
| 29 | + { "op": "fill", "selector": "#field-19", "value": "value-19" }, |
| 30 | + { "op": "fill", "selector": "#field-20", "value": "value-20" }, |
| 31 | + { "op": "fill", "selector": "#field-21", "value": "value-21" }, |
| 32 | + { "op": "fill", "selector": "#field-22", "value": "value-22" }, |
| 33 | + { "op": "fill", "selector": "#field-23", "value": "value-23" }, |
| 34 | + { "op": "fill", "selector": "#field-24", "value": "value-24" }, |
| 35 | + { "op": "fill", "selector": "#field-25", "value": "value-25" }, |
| 36 | + { "op": "fill", "selector": "#field-26", "value": "value-26" }, |
| 37 | + { "op": "fill", "selector": "#field-27", "value": "value-27" }, |
| 38 | + { "op": "fill", "selector": "#field-28", "value": "value-28" }, |
| 39 | + { "op": "fill", "selector": "#field-29", "value": "value-29" }, |
| 40 | + { "op": "fill", "selector": "#field-30", "value": "value-30" }, |
| 41 | + { "op": "fill", "selector": "#field-31", "value": "value-31" }, |
| 42 | + { "op": "fill", "selector": "#field-32", "value": "value-32" }, |
| 43 | + { "op": "fill", "selector": "#field-33", "value": "value-33" }, |
| 44 | + { "op": "fill", "selector": "#field-34", "value": "value-34" }, |
| 45 | + { "op": "fill", "selector": "#field-35", "value": "value-35" }, |
| 46 | + { "op": "fill", "selector": "#field-36", "value": "value-36" }, |
| 47 | + { "op": "click", "selector": "#submit" }, |
| 48 | + { "op": "textContent", "selector": "#status", "capture": "status" }, |
| 49 | + { "op": "assertText", "selector": "#status", "equals": "submitted:36" }, |
| 50 | + { "op": "assertEval", "expression": "Array.from(document.querySelectorAll('#fields input')).every((input,index)=>input.value==='value-'+String(index+1).padStart(2,'0'))", "equals": true } |
| 51 | + ] |
| 52 | + }, |
| 53 | + { |
| 54 | + "id": "tab-navigation-loop", |
| 55 | + "description": "Navigate a large in-page tab workspace repeatedly and assert the selected panel.", |
| 56 | + "html": "<!doctype html><html><head><title>Tab Workspace</title><style>[role=tab]{padding:8px}.panel[hidden]{display:none}.panel{padding:16px;border:1px solid #888}</style></head><body><main><h1>Operations workspace</h1><nav id='tabs' role='tablist'></nav><div id='panels'></div><output id='active'></output></main><script>const tabs=document.querySelector('#tabs');const panels=document.querySelector('#panels');tabs.innerHTML=Array.from({length:8},(_,index)=>'<button id=\\'tab-'+index+'\\' role=\\'tab\\'>Section '+index+'</button>').join('');panels.innerHTML=Array.from({length:8},(_,index)=>'<section id=\\'panel-'+index+'\\' class=\\'panel\\'>'+Array.from({length:40},(_,row)=>'<p>Panel '+index+' deterministic content '+row+'</p>').join('')+'</section>').join('');function select(index){document.querySelectorAll('[role=tab]').forEach((tab,item)=>tab.setAttribute('aria-selected',String(item===index)));document.querySelectorAll('.panel').forEach((panel,item)=>panel.hidden=item!==index);document.querySelector('#active').textContent='active:panel-'+index;}tabs.addEventListener('click',event=>select(Number(event.target.id.split('-')[1])));select(0);</script></body></html>", |
| 57 | + "repeat": 3, |
| 58 | + "steps": [ |
| 59 | + { "op": "goto", "useCaseHtml": true }, |
| 60 | + { "op": "click", "selector": "#tab-1" }, |
| 61 | + { "op": "click", "selector": "#tab-4" }, |
| 62 | + { "op": "click", "selector": "#tab-2" }, |
| 63 | + { "op": "click", "selector": "#tab-7" }, |
| 64 | + { "op": "textContent", "selector": "#active", "capture": "activePanel" }, |
| 65 | + { "op": "assertText", "selector": "#active", "equals": "active:panel-7" }, |
| 66 | + { "op": "evaluate", "expression": "()=>({selected:document.querySelector('[aria-selected=true]').id,visible:document.querySelector('.panel:not([hidden])').id})", "capture": "tabState" }, |
| 67 | + { "op": "assertEval", "expression": "({selected:document.querySelector('[aria-selected=true]').id,visible:document.querySelector('.panel:not([hidden])').id})", "equals": { "selected": "tab-7", "visible": "panel-7" } } |
| 68 | + ] |
| 69 | + }, |
| 70 | + { |
| 71 | + "id": "large-table-evaluate", |
| 72 | + "description": "Run repeated aggregate computations over a deterministic 400-row ledger.", |
| 73 | + "html": "<!doctype html><html><head><title>Ledger Aggregate</title><style>table{border-collapse:collapse}td,th{padding:3px 8px;border:1px solid #ccc}</style></head><body><main><h1>Regional ledger</h1><table id='ledger'><thead><tr><th>ID</th><th>Region</th><th>Amount</th></tr></thead><tbody></tbody></table></main><script>document.querySelector('#ledger tbody').innerHTML=Array.from({length:400},(_,index)=>'<tr data-region=\\'r'+index%5+'\\'><td>TX-'+String(index).padStart(4,'0')+'</td><td>r'+index%5+'</td><td class=\\'amount\\'>'+((index%25)+1)+'</td></tr>').join('');</script></body></html>", |
| 74 | + "repeat": 3, |
| 75 | + "steps": [ |
| 76 | + { "op": "goto", "useCaseHtml": true }, |
| 77 | + { "op": "evaluate", "expression": "()=>{const rows=Array.from(document.querySelectorAll('#ledger tbody tr'));const amounts=rows.map(row=>Number(row.querySelector('.amount').textContent));return {rows:rows.length,total:amounts.reduce((sum,value)=>sum+value,0),high:amounts.filter(value=>value>=20).length};}", "capture": "aggregate" }, |
| 78 | + { "op": "evaluate", "expression": "()=>Object.fromEntries(Array.from({length:5},(_,index)=>['r'+index,document.querySelectorAll('tr[data-region=r'+index+']').length]))", "capture": "regions" }, |
| 79 | + { "op": "evaluate", "expression": "()=>Array.from(document.querySelectorAll('#ledger tbody tr')).reduce((sum,row,index)=>sum+Number(row.children[2].textContent)*(index+1),0)", "capture": "weightedChecksum" }, |
| 80 | + { "op": "assertEval", "expression": "(()=>{const rows=Array.from(document.querySelectorAll('#ledger tbody tr'));const amounts=rows.map(row=>Number(row.querySelector('.amount').textContent));return {rows:rows.length,total:amounts.reduce((sum,value)=>sum+value,0),high:amounts.filter(value=>value>=20).length};})()", "equals": { "rows": 400, "total": 5200, "high": 96 } }, |
| 81 | + { "op": "assertEval", "expression": "Object.fromEntries(Array.from({length:5},(_,index)=>['r'+index,document.querySelectorAll('tr[data-region=r'+index+']').length]))", "equals": { "r0": 80, "r1": 80, "r2": 80, "r3": 80, "r4": 80 } } |
| 82 | + ] |
| 83 | + } |
| 84 | + ] |
| 85 | +} |
0 commit comments