Skip to content
Astera Technology

Keep composition Enter from submitting a form

Use the supplied composition flag before treating Enter as submission.

Download complete case notes and answer keys ↓

Set the decision and its input

The synthetic input contains 中文. The first Enter has isComposing=true and confirms the candidate; the next is false and may submit. A listener reacting to every Enter submits twice. The corrected listener submits once while preserving the complete text.

Filled local test worksheet
CaseInput JSON
Base test{"text":"中文","enterCompositionFlags":[true,false]}
Download editable CSV ↓

Run the supplied comparison

Actual DOM KeyboardEvents with the supplied flags exercise the handler. This does not claim that every physical input method or operating system has been tested.

Faulty and required outputs
PathOutput JSON
Faulty path{"submissions":2,"finalText":"中文"}
Required path{"submissions":1,"finalText":"中文"}
Download editable CSV ↓
Node24.14.1 programme; Playwright1.63 Chromium required
import assert from 'node:assert/strict';
import {createRequire} from 'node:module';
const htmlEscape=s=>String(s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/"/g,'&quot;');
async function withPage(action,options={}){
  const require=createRequire(import.meta.url);const {chromium}=require('playwright');
  const browser=await chromium.launch({headless:true});
  try{const context=await browser.newContext(options);const page=await context.newPage();
    const requests=[];await page.route('**/*',route=>{requests.push(route.request().url());return route.abort();});
    return await action(page,context,requests);
  }finally{await browser.close();}
}

const run=async function run(i,corrected=true){
    if(!i.enterCompositionFlags.every(v=>typeof v==='boolean'))return {held:true};
    return withPage(async page=>{await page.setContent('<label>Memo<input id="memo"></label><output id="count">0</output>');
      await page.evaluate(corrected=>{let count=0;document.querySelector('#memo').addEventListener('keydown',e=>{if(e.key==='Enter'&&(!corrected||!e.isComposing))document.querySelector('#count').textContent=String(++count);});},corrected);
      await page.fill('#memo',i.text);for(const composing of i.enterCompositionFlags)await page.dispatchEvent('#memo','keydown',{key:'Enter',isComposing:composing});
      return page.evaluate(()=>({submissions:Number(document.querySelector('#count').textContent),finalText:document.querySelector('#memo').value}));});
  };
const cases=[{"input":{"text":"中文","enterCompositionFlags":[true,false]},"corrected":false,"expected":{"submissions":2,"finalText":"中文"}},{"input":{"text":"中文","enterCompositionFlags":[true,false]},"corrected":true,"expected":{"submissions":1,"finalText":"中文"}},{"input":{"text":"你","enterCompositionFlags":[true]},"corrected":true,"expected":{"submissions":0,"finalText":"你"}},{"input":{"text":"Ada","enterCompositionFlags":[false]},"corrected":true,"expected":{"submissions":1,"finalText":"Ada"}}];
for(const test of cases){const actual=await run(test.input,test.corrected);assert.deepEqual(actual,test.expected);console.log(actual);}
Download runnable example ↓

Choose from the boundary evidence

Candidate confirmation alone gives zero submissions. Ordinary non-composing Enter gives one without clearing the field.

  1. Read the composition flag
  2. Permit the intended submit event
  3. Check count and retained text

Do not infer submission from candidate confirmation.

Editable boundary inputs and outputs
ConditionInput JSONExpected output JSON
candidate confirmation only{"text":"你","enterCompositionFlags":[true]}{"submissions":0,"finalText":"你"}
ordinary Enter{"text":"Ada","enterCompositionFlags":[false]}{"submissions":1,"finalText":"Ada"}
Download editable CSV ↓

How many submissions belong to the base sequence?

Show the worked answer

One, after the non-composing Enter. Confirming a candidate is a different action.

Related resources