From 6d50c0042d2f9bbe340dea3b5b1f14013b1580f9 Mon Sep 17 00:00:00 2001 From: Caroline Date: Sat, 18 Apr 2026 22:14:49 +0800 Subject: [PATCH] solo-coder-phase4: 2b1e69fae-5b00-4c9e-a3e5-08fa6276051c / beta / round1 (.115908579437896:8eb0280d7bbd747b6bcf6ebc44354dbb_69e3912187d9eec1bd049513.69e3913f87d9eec1bd049517.6560e216e0604f3e898d6ee0:Trae CN.T(2026/4/18 22:12:15)) --- lib/todo-app.js | 11 +++++- test/todo-app.test.js | 84 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 94 insertions(+), 1 deletion(-) diff --git a/lib/todo-app.js b/lib/todo-app.js index 2b9c956..724c102 100644 --- a/lib/todo-app.js +++ b/lib/todo-app.js @@ -329,7 +329,16 @@ function subscriptions (signal) { } break; case ESCAPE_KEY: - signal('CANCEL')(); + var editing = document.getElementsByClassName('editing'); + if (editing && editing.length > 0) { + signal('CANCEL')(); + } else { + var new_todo = document.getElementById('new-todo'); + if (new_todo.value.length > 0) { + new_todo.value = ''; + new_todo.focus(); + } + } break; } }); diff --git a/test/todo-app.test.js b/test/todo-app.test.js index 5ec459c..c3c8001 100644 --- a/test/todo-app.test.js +++ b/test/todo-app.test.js @@ -547,6 +547,90 @@ test('5.5 CANCEL should cancel edits on escape', function (t) { t.end(); }); +test('5.6 ESCAPE in new-todo with content should clear input and keep focus', function (t) { + elmish.empty(document.getElementById(id)); + localStorage.removeItem('todos-elmish_' + id); + const model = { + todos: [ + { id: 0, title: "Make something people want.", done: false }, + { id: 1, title: "Let's solve our own problem", done: false } + ], + hash: '#/' + }; + elmish.mount(model, app.update, app.view, id, app.subscriptions); + + const new_todo = document.getElementById('new-todo'); + new_todo.value = 'This is a test todo'; + t.equal(new_todo.value, 'This is a test todo', 'new-todo has content before ESC'); + + document.dispatchEvent(new KeyboardEvent('keyup', {'keyCode': 27})); + + t.equal(new_todo.value, '', 'new-todo should be cleared after ESC'); + t.equal(document.activeElement, new_todo, 'new-todo should keep focus after ESC'); + t.equal(document.querySelectorAll('.editing').length, 0, 'not in editing mode'); + t.equal(document.querySelectorAll('.view').length, 2, 'todos remain unchanged'); + + elmish.empty(document.getElementById(id)); + localStorage.removeItem('todos-elmish_' + id); + t.end(); +}); + +test('5.7 ESCAPE in new-todo with empty content should do nothing', function (t) { + elmish.empty(document.getElementById(id)); + localStorage.removeItem('todos-elmish_' + id); + const model = { + todos: [ + { id: 0, title: "Make something people want.", done: false }, + { id: 1, title: "Let's solve our own problem", done: false } + ], + hash: '#/' + }; + elmish.mount(model, app.update, app.view, id, app.subscriptions); + + const new_todo = document.getElementById('new-todo'); + t.equal(new_todo.value, '', 'new-todo is empty before ESC'); + + document.dispatchEvent(new KeyboardEvent('keyup', {'keyCode': 27})); + + t.equal(new_todo.value, '', 'new-todo remains empty after ESC'); + t.equal(document.querySelectorAll('.view').length, 2, 'todos remain unchanged'); + + elmish.empty(document.getElementById(id)); + localStorage.removeItem('todos-elmish_' + id); + t.end(); +}); + +test('5.8 ESCAPE in editing mode should cancel edit and not affect new-todo', function (t) { + elmish.empty(document.getElementById(id)); + localStorage.removeItem('todos-elmish_' + id); + const model = { + todos: [ + { id: 0, title: "Make something people want.", done: false }, + { id: 1, title: "Let's solve our own problem", done: false } + ], + hash: '#/', + editing: 1 + }; + elmish.mount(model, app.update, app.view, id, app.subscriptions); + + const new_todo = document.getElementById('new-todo'); + new_todo.value = 'New todo content'; + + t.equal(document.querySelectorAll('.editing').length, 1, 'in editing mode'); + t.equal(new_todo.value, 'New todo content', 'new-todo has content'); + + document.dispatchEvent(new KeyboardEvent('keyup', {'keyCode': 27})); + + t.equal(document.querySelectorAll('.editing').length, 0, 'editing mode canceled'); + t.equal(document.querySelectorAll('.view > label')[1].textContent, + model.todos[1].title, 'todo item title unchanged'); + t.equal(new_todo.value, 'New todo content', 'new-todo content preserved'); + + elmish.empty(document.getElementById(id)); + localStorage.removeItem('todos-elmish_' + id); + t.end(); +}); + test('6. Counter > should display the current number of todo items', function (t) { elmish.empty(document.getElementById(id));