This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"title": "フォーム入力",
|
||||
"description": "入力を output/ に構造化保存",
|
||||
"entry": "index.html"
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"app": "form-input",
|
||||
"seed_files": [],
|
||||
"steps": [
|
||||
{ "type": "fill", "selector": "[data-testid=\"f-name\"]", "value": "alice" },
|
||||
{ "type": "fill", "selector": "[data-testid=\"f-note\"]", "value": "hello-e2e" },
|
||||
{ "type": "click", "selector": "[data-testid=\"submit\"]" },
|
||||
{ "type": "getText", "selector": "[data-testid=\"status\"]" }
|
||||
],
|
||||
"expect": [
|
||||
{ "kind": "text", "target": "[data-testid=\"status\"]", "contains": "保存" },
|
||||
{ "kind": "file", "target": "output/submissions.jsonl", "contains": "hello-e2e" }
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
<!doctype html><html lang="ja"><head><meta charset="utf-8" />
|
||||
<style>
|
||||
body{font:14px system-ui;margin:0;padding:16px}
|
||||
.row{display:flex;gap:8px;align-items:center;margin-bottom:8px}
|
||||
input[type="text"],textarea{border:1px solid #ccc;border-radius:4px;padding:6px 8px;width:100%;box-sizing:border-box}
|
||||
label{display:block;font-weight:bold;margin-bottom:4px;margin-top:12px}
|
||||
button{padding:6px 16px;border-radius:4px;border:none;background:#2563eb;color:#fff;cursor:pointer}
|
||||
button:hover{background:#1d4ed8}
|
||||
span[data-testid="status"]{font-size:12px;color:#555}
|
||||
</style></head>
|
||||
<body>
|
||||
<label for="f-name">名前</label>
|
||||
<input type="text" id="f-name" data-testid="f-name" placeholder="名前を入力" />
|
||||
<label for="f-note">メモ</label>
|
||||
<input type="text" id="f-note" data-testid="f-note" placeholder="メモを入力" />
|
||||
<div class="row" style="margin-top:16px">
|
||||
<button id="submitBtn" data-testid="submit">保存</button>
|
||||
<span id="status" data-testid="status"></span>
|
||||
</div>
|
||||
<script>
|
||||
let seq=0;const pending=new Map();
|
||||
function call(req){return new Promise((res,rej)=>{const id=++seq;pending.set(id,{res,rej});
|
||||
window.parent.postMessage({...req,id},'*');});}
|
||||
window.addEventListener('message',e=>{const r=e.data;const p=pending.get(r&&r.id);if(!p)return;
|
||||
pending.delete(r.id);r.ok?p.res(r.data):p.rej(new Error(r.error));});
|
||||
const $=id=>document.getElementById(id);
|
||||
|
||||
const DEST='output/submissions.jsonl';
|
||||
|
||||
async function submit(){
|
||||
const name=$('f-name').value.trim();
|
||||
const note=$('f-note').value.trim();
|
||||
if(!name&&!note){$('status').textContent='入力してください';return;}
|
||||
$('status').textContent='保存中…';
|
||||
try{
|
||||
let existing='';
|
||||
try{const d=await call({type:'readFile',path:DEST});existing=d.content||'';}catch(_){}
|
||||
const line=JSON.stringify({name,note,ts:new Date().toISOString()});
|
||||
const updated=(existing.endsWith('\n')||existing==='')
|
||||
?existing+line+'\n'
|
||||
:existing+'\n'+line+'\n';
|
||||
await call({type:'writeFile',path:DEST,content:updated});
|
||||
$('f-name').value='';$('f-note').value='';
|
||||
$('status').textContent='保存しました';
|
||||
}catch(err){$('status').textContent='保存失敗:'+err.message;}
|
||||
}
|
||||
|
||||
$('submitBtn').onclick=submit;
|
||||
</script></body></html>
|
||||
Reference in New Issue
Block a user