Skip to content

Commit b67390e

Browse files
committed
Fix smoke tests and add empty-value clear tests
Smoke tests: use todos update for --starts-on (create lacks it), match description as HTML substring (API wraps in <p> tags). Unit tests: add --starts-on "" and --description "" empty-value clearing coverage alongside the existing --due "" test.
1 parent 0742498 commit b67390e

2 files changed

Lines changed: 51 additions & 6 deletions

File tree

e2e/smoke/smoke_todos_write.bats

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -97,15 +97,19 @@ setup_file() {
9797
}
9898

9999
@test "todos update preserves fields when updating title only" {
100-
# Create a todo with description, due, and starts-on populated
100+
# Create a todo with description and due populated.
101+
# todos create lacks --starts-on, so set it via a follow-up update.
101102
run_smoke basecamp todos create "Field preservation test $(date +%s)" \
102103
--list "$QA_TODOLIST" -p "$QA_PROJECT" \
103-
--due "2026-06-15" --starts-on "2026-06-01" \
104+
--due "2026-06-15" \
104105
--description "Original description" --json
105106
assert_success
106107
local todo_id
107108
todo_id=$(echo "$output" | jq -r '.data.id')
108109

110+
run_smoke basecamp todos update "$todo_id" --starts-on "2026-06-01" --json
111+
assert_success
112+
109113
# Update only the title via the SDK typed path (no --no-* flags)
110114
run_smoke basecamp todos update "$todo_id" --title "Renamed title" --json
111115
assert_success
@@ -117,22 +121,29 @@ setup_file() {
117121
assert_json_value '.data.content' 'Renamed title'
118122
assert_json_value '.data.due_on' '2026-06-15'
119123
assert_json_value '.data.starts_on' '2026-06-01'
120-
assert_json_value '.data.description' 'Original description'
124+
# Description is returned as HTML (<p>...</p>)
125+
local desc
126+
desc=$(echo "$output" | jq -r '.data.description')
127+
[[ "$desc" == *"Original description"* ]] || { echo "description not preserved: $desc"; return 1; }
121128

122129
# Clean up
123130
run_smoke basecamp todos trash "$todo_id" -p "$QA_PROJECT" --json
124131
}
125132

126133
@test "todos update --no-due clears due and preserves other fields" {
127-
# Create a todo with all clearable fields populated
134+
# Create a todo with due and description populated.
135+
# todos create lacks --starts-on, so set it via a follow-up update.
128136
run_smoke basecamp todos create "Clear test $(date +%s)" \
129137
--list "$QA_TODOLIST" -p "$QA_PROJECT" \
130-
--due "2026-07-15" --starts-on "2026-07-01" \
138+
--due "2026-07-15" \
131139
--description "Keep this" --json
132140
assert_success
133141
local todo_id
134142
todo_id=$(echo "$output" | jq -r '.data.id')
135143

144+
run_smoke basecamp todos update "$todo_id" --starts-on "2026-07-01" --json
145+
assert_success
146+
136147
# Clear the due date (raw PUT path)
137148
run_smoke basecamp todos update "$todo_id" --no-due --json
138149
assert_success
@@ -154,7 +165,7 @@ setup_file() {
154165

155166
[[ "$due_on" == "null" ]] || { echo "due_on not cleared: $due_on"; return 1; }
156167
[[ "$starts_on" == "null" ]] || { echo "starts_on not cleared: $starts_on"; return 1; }
157-
[[ "$desc" == "Keep this" ]] || { echo "description not preserved: $desc"; return 1; }
168+
[[ "$desc" == *"Keep this"* ]] || { echo "description not preserved: $desc"; return 1; }
158169

159170
# Clean up
160171
run_smoke basecamp todos trash "$todo_id" -p "$QA_PROJECT" --json

internal/commands/todos_test.go

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1602,6 +1602,40 @@ func TestTodosUpdateEmptyDueClearsField(t *testing.T) {
16021602
assert.False(t, exists, "due_on must be omitted when --due is empty")
16031603
}
16041604

1605+
func TestTodosUpdateEmptyStartsOnClearsField(t *testing.T) {
1606+
transport := &mockTodoUpdateTransport{}
1607+
app := setupTodoUpdateApp(t, transport)
1608+
1609+
cmd := NewTodosCmd()
1610+
err := executeTodosCommand(cmd, app, "update", "999", "--starts-on", "")
1611+
require.NoError(t, err)
1612+
require.NotEmpty(t, transport.capturedBody)
1613+
1614+
var body map[string]any
1615+
err = json.Unmarshal(transport.capturedBody, &body)
1616+
require.NoError(t, err)
1617+
1618+
_, exists := body["starts_on"]
1619+
assert.False(t, exists, "starts_on must be omitted when --starts-on is empty")
1620+
}
1621+
1622+
func TestTodosUpdateEmptyDescriptionClearsField(t *testing.T) {
1623+
transport := &mockTodoUpdateTransport{}
1624+
app := setupTodoUpdateApp(t, transport)
1625+
1626+
cmd := NewTodosCmd()
1627+
err := executeTodosCommand(cmd, app, "update", "999", "--description", "")
1628+
require.NoError(t, err)
1629+
require.NotEmpty(t, transport.capturedBody)
1630+
1631+
var body map[string]any
1632+
err = json.Unmarshal(transport.capturedBody, &body)
1633+
require.NoError(t, err)
1634+
1635+
_, exists := body["description"]
1636+
assert.False(t, exists, "description must be omitted when --description is empty")
1637+
}
1638+
16051639
func TestTodosUpdateConflictingNoDueAndDue(t *testing.T) {
16061640
app, _ := setupTodosTestApp(t)
16071641

0 commit comments

Comments
 (0)