Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion internal/commands/device_claim.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,11 @@ import (
"net/http"
"strconv"
"strings"
"time"
)

var claimClient = &http.Client{Timeout: 90 * time.Second}

func DeviceClaim(arguments []string) error {
if len(arguments) != 2 && len(arguments) != 3 {
return errors.New("device claim takes an IMEI, a fleet id, and an optional name")
Expand Down Expand Up @@ -46,6 +49,8 @@ func DeviceClaim(arguments []string) error {
return errors.New("the fleet id is the number shown by fleet list")
}

fmt.Println("Press the button on the device to finish claiming it.")

payload := map[string]string{"imei": imei}

if len(arguments) == 3 {
Expand All @@ -67,7 +72,7 @@ func DeviceClaim(arguments []string) error {

request.Header.Set("Content-Type", "application/json")

response, err := apiClient.Do(request)
response, err := claimClient.Do(request)

if err != nil {
return fmt.Errorf("the server could not be reached: %w", err)
Expand Down
129 changes: 73 additions & 56 deletions internal/commands/device_claim_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,46 +9,81 @@ import (
)

func TestDeviceClaim(t *testing.T) {
claimedImei := ""
claimedName := ""

mux := http.NewServeMux()
mux.HandleFunc("GET /fleets", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, `[{"id":3,"name":"pilot","owner":true}]`)
})
mux.HandleFunc("POST /fleets/{id}/devices", func(w http.ResponseWriter, r *http.Request) {
body := struct {
Imei string `json:"imei"`
Name string `json:"name"`
}{}

json.NewDecoder(r.Body).Decode(&body)
claimedImei = body.Imei
claimedName = body.Name

if r.Header.Get("Content-Type") != "application/json" {
t.Errorf("Content-Type = %q, want application/json", r.Header.Get("Content-Type"))
}

w.WriteHeader(http.StatusNoContent)
})

loggedInTestServer(t, mux)

printed, err := captureStdout(t, func() error {
return DeviceClaim([]string{"354820091234567", "3", "roof sensor"})
})

if err != nil {
t.Fatal(err)
}

if claimedImei != "354820091234567" || claimedName != "roof sensor" {
t.Errorf("the server received IMEI %q and name %q", claimedImei, claimedName)
tests := []struct {
name string
statusCode int
message string
wantOutput string
wantError string
}{
{
name: "button pressed",
statusCode: http.StatusNoContent,
wantOutput: "Press the button on the device to finish claiming it.\nClaimed the device into \"pilot\".\n",
},
{
name: "button not pressed",
statusCode: http.StatusRequestTimeout,
message: "the button was not pressed in time",
wantOutput: "Press the button on the device to finish claiming it.\n",
wantError: "the server said: the button was not pressed in time",
},
}

if printed != "Claimed the device into \"pilot\".\n" {
t.Errorf("output = %q", printed)
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
claimedImei := ""
claimedName := ""

mux := http.NewServeMux()
mux.HandleFunc("GET /fleets", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, `[{"id":3,"name":"pilot","owner":true}]`)
})
mux.HandleFunc("POST /fleets/{id}/devices", func(w http.ResponseWriter, r *http.Request) {
body := struct {
Imei string `json:"imei"`
Name string `json:"name"`
}{}

json.NewDecoder(r.Body).Decode(&body)
claimedImei = body.Imei
claimedName = body.Name

if r.Header.Get("Content-Type") != "application/json" {
t.Errorf("Content-Type = %q, want application/json", r.Header.Get("Content-Type"))
}

if test.message != "" {
http.Error(w, test.message, test.statusCode)

return
}

w.WriteHeader(test.statusCode)
})

loggedInTestServer(t, mux)

printed, err := captureStdout(t, func() error {
return DeviceClaim([]string{"354820091234567", "3", "roof sensor"})
})

if test.wantError == "" && err != nil {
t.Fatal(err)
}

if test.wantError != "" && (err == nil || err.Error() != test.wantError) {
t.Fatalf("error = %v, want %q", err, test.wantError)
}

if claimedImei != "354820091234567" || claimedName != "roof sensor" {
t.Errorf("the server received IMEI %q and name %q", claimedImei, claimedName)
}

if printed != test.wantOutput {
t.Errorf("output = %q, want %q", printed, test.wantOutput)
}
})
}
}

Expand Down Expand Up @@ -79,24 +114,6 @@ func TestDeviceClaimOmitsAnAbsentName(t *testing.T) {
}
}

func TestDeviceClaimServerError(t *testing.T) {
mux := http.NewServeMux()
mux.HandleFunc("GET /fleets", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, `[{"id":3,"name":"pilot","owner":true}]`)
})
mux.HandleFunc("POST /fleets/{id}/devices", func(w http.ResponseWriter, r *http.Request) {
http.Error(w, "no unclaimed device with that IMEI", http.StatusNotFound)
})

loggedInTestServer(t, mux)

err := DeviceClaim([]string{"354820091234567", "3"})

if err == nil || err.Error() != "the server said: no unclaimed device with that IMEI" {
t.Fatalf("error = %v", err)
}
}

func TestDeviceClaimArguments(t *testing.T) {
tests := []struct {
name string
Expand Down