diff --git a/static/js/managers/import/RecipeDataManager.js b/static/js/managers/import/RecipeDataManager.js index 319d3419..bc49399c 100644 --- a/static/js/managers/import/RecipeDataManager.js +++ b/static/js/managers/import/RecipeDataManager.js @@ -17,6 +17,10 @@ export class RecipeDataManager { return; } + if (event.isComposing || event.keyCode === 229) { + return; + } + event.preventDefault(); this.addTag(); }); diff --git a/tests/frontend/managers/RecipeDataManager.tagInput.test.js b/tests/frontend/managers/RecipeDataManager.tagInput.test.js index 329def6d..9e0320ef 100644 --- a/tests/frontend/managers/RecipeDataManager.tagInput.test.js +++ b/tests/frontend/managers/RecipeDataManager.tagInput.test.js @@ -53,4 +53,54 @@ describe('RecipeDataManager tag input Enter behavior', () => { expect(importManager.recipeTags).toEqual(['anime']); }); + + it('ignores Enter while IME composition is active', async () => { + const { RecipeDataManager } = await import('../../../static/js/managers/import/RecipeDataManager.js'); + const importManager = { + recipeTags: [], + stepManager: { showStep: vi.fn() }, + }; + const manager = new RecipeDataManager(importManager); + + manager.setupTagInputEnterHandler(); + + const tagInput = document.getElementById('tagInput'); + tagInput.value = '未確定'; + const event = new KeyboardEvent('keydown', { + key: 'Enter', + bubbles: true, + cancelable: true, + }); + Object.defineProperty(event, 'isComposing', { value: true }); + tagInput.dispatchEvent(event); + + expect(importManager.recipeTags).toEqual([]); + expect(tagInput.value).toBe('未確定'); + expect(event.defaultPrevented).toBe(false); + }); + + it('ignores keyCode 229 fallback during composition', async () => { + const { RecipeDataManager } = await import('../../../static/js/managers/import/RecipeDataManager.js'); + const importManager = { + recipeTags: [], + stepManager: { showStep: vi.fn() }, + }; + const manager = new RecipeDataManager(importManager); + + manager.setupTagInputEnterHandler(); + + const tagInput = document.getElementById('tagInput'); + tagInput.value = '候補'; + const event = new KeyboardEvent('keydown', { + key: 'Enter', + bubbles: true, + cancelable: true, + }); + Object.defineProperty(event, 'keyCode', { value: 229 }); + tagInput.dispatchEvent(event); + + expect(importManager.recipeTags).toEqual([]); + expect(tagInput.value).toBe('候補'); + expect(event.defaultPrevented).toBe(false); + }); });