Skip to content

Commit b21446b

Browse files
improve handling of system-error submissions
1 parent c810c91 commit b21446b

4 files changed

Lines changed: 78 additions & 1 deletion

File tree

cmd/submit.go

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,14 +92,25 @@ func submissionHandler(cmd *cobra.Command, args []string) error {
9292
if err != nil {
9393
return err
9494
}
95-
checks.ApplySubmissionResults(data, submissionEvent.StructuredErrCLI, ch)
95+
submissionErr := applySubmissionEvent(data, submissionEvent, ch)
9696
finalise(submissionEvent)
97+
if submissionErr != nil {
98+
return submissionErr
99+
}
97100
} else {
98101
finalise(api.LessonSubmissionEvent{})
99102
}
100103
return nil
101104
}
102105

106+
func applySubmissionEvent(data api.CLIData, event api.LessonSubmissionEvent, ch chan tea.Msg) error {
107+
if event.ResultSlug == api.VerificationResultSlugSystemError {
108+
return errors.New("lesson verification failed due to a system error; please try again")
109+
}
110+
checks.ApplySubmissionResults(data, event.StructuredErrCLI, ch)
111+
return nil
112+
}
113+
103114
func reportDebugFileWrite(path string, err error) {
104115
if err != nil {
105116
fmt.Fprintf(os.Stderr, "warning: failed to write submission debug output: %v\n", err)

cmd/submit_test.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package cmd
2+
3+
import (
4+
"strings"
5+
"testing"
6+
7+
api "github.com/bootdotdev/bootdev/client"
8+
tea "github.com/charmbracelet/bubbletea"
9+
)
10+
11+
func TestApplySubmissionEventRejectsSystemErrorWithoutMarkingStepsPassed(t *testing.T) {
12+
data := api.CLIData{Steps: []api.CLIStep{{
13+
CLICommand: &api.CLIStepCLICommand{Tests: []api.CLICommandTest{{}}},
14+
}}}
15+
ch := make(chan tea.Msg, 1)
16+
17+
err := applySubmissionEvent(data, api.LessonSubmissionEvent{
18+
ResultSlug: api.VerificationResultSlugSystemError,
19+
}, ch)
20+
if err == nil || !strings.Contains(err.Error(), "system error") {
21+
t.Fatalf("applySubmissionEvent() error = %v, want system error", err)
22+
}
23+
24+
select {
25+
case msg := <-ch:
26+
t.Fatalf("system error unexpectedly emitted result message: %#v", msg)
27+
default:
28+
}
29+
}

render/view.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,17 @@ func (m rootModel) View() string {
168168
str.WriteString(green.Render("Return to your browser to continue with the next lesson."))
169169
str.WriteByte('\n')
170170
str.WriteByte('\n')
171+
} else if m.result == api.VerificationResultSlugSystemError {
172+
str.WriteByte('\n')
173+
str.WriteByte('\n')
174+
str.WriteString(red.Render("Unable to verify this lesson due to a system error."))
175+
if m.failure != nil && m.failure.ErrorMessage != "" {
176+
str.WriteString(red.Render(fmt.Sprintf("\nError: %s", m.failure.ErrorMessage)))
177+
}
178+
str.WriteByte('\n')
179+
str.WriteString(red.Render("Please try again."))
180+
str.WriteByte('\n')
181+
str.WriteByte('\n')
171182
} else if m.result == api.VerificationResultSlugNoop {
172183
str.WriteString("\n\nTests failed! ❌")
173184
fmt.Fprintf(&str, "\n\nFailed Step: %v", m.failure.FailedStepIndex+1)

render/view_test.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,32 @@ func TestVerboseViewStaysCompactUntilFinalized(t *testing.T) {
145145
}
146146
}
147147

148+
func TestSystemErrorViewDoesNotShowStepsAsPassed(t *testing.T) {
149+
m := initModel(true, false)
150+
m.finalized = true
151+
m.result = api.VerificationResultSlugSystemError
152+
m.steps = []stepModel{{
153+
description: "The command prints a greeting",
154+
finished: true,
155+
}}
156+
157+
view := m.View()
158+
for _, expected := range []string{
159+
"? The command prints a greeting",
160+
"Unable to verify this lesson due to a system error.",
161+
"Please try again.",
162+
} {
163+
if !strings.Contains(view, expected) {
164+
t.Errorf("view missing %q\n%s", expected, view)
165+
}
166+
}
167+
for _, unexpected := range []string{"✓ The command prints a greeting", "All tests passed!"} {
168+
if strings.Contains(view, unexpected) {
169+
t.Errorf("view unexpectedly contains %q\n%s", unexpected, view)
170+
}
171+
}
172+
}
173+
148174
func TestStartStepFallsBackToTechnicalDescription(t *testing.T) {
149175
m := initModel(true, false)
150176
updated, _ := m.Update(messages.StartStepMsg{CMD: "go test ./..."})

0 commit comments

Comments
 (0)