all repos

viye @ master

my shot at reimplementing xiki

viye/internal/plumbing/http/http_test.go (view raw)

Oleksandr Smirnov Oleksandr Smirnov
olexsmir@gmail.com
add sql tool, 1 month ago
1
package http
2
3
import (
4
	"io"
5
	"net/http"
6
	"net/http/httptest"
7
	"testing"
8
9
	"github.com/olexsmir/viye/internal/viye"
10
11
	"olexsmir.xyz/x/is"
12
)
13
14
func TestMatch(t *testing.T) {
15
	for _, tt := range []struct {
16
		cmd  string
17
		args []string
18
		want bool
19
	}{
20
		{"", nil, false},
21
		{"get", []string{"http://example.com"}, true},
22
		{"post", []string{"https://x.io"}, true},
23
		{"put", []string{"http://x.io/a"}, true},
24
		{"patch", []string{"https://x.io/a"}, true},
25
		{"delete", []string{"http://example.com"}, true},
26
		{"GET", []string{"http://example.com"}, false}, // case-sensitive
27
		{"get", nil, false},
28
		{"post", []string{"not-a-url"}, false},
29
		{"delete", nil, false},
30
		{"empty", nil, false},
31
	} {
32
		got := (Tool{}).Match(&viye.Context{Cmd: tt.cmd, Args: tt.args})
33
		is.Equal(t, tt.want, got)
34
	}
35
}
36
37
func TestExecute(t *testing.T) {
38
	t.Run("no args returns error", func(t *testing.T) {
39
		_, err := (Tool{}).Execute(&viye.Context{Cmd: "get", Args: []string{}})
40
		is.Err(t, err, "provide an url")
41
	})
42
43
	t.Run("invalid url returns error", func(t *testing.T) {
44
		_, err := (Tool{}).Execute(&viye.Context{Cmd: "get", Args: []string{"not-a-url"}})
45
		is.Err(t, err, "provide an url")
46
	})
47
48
	t.Run("successful GET request", func(t *testing.T) {
49
		server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
50
			is.Equal(t, "GET", r.Method)
51
			w.WriteHeader(http.StatusOK)
52
			io.WriteString(w, "response body")
53
		}))
54
		defer server.Close()
55
56
		got, err := (Tool{}).Execute(&viye.Context{
57
			Cmd:  "get",
58
			Args: []string{server.URL},
59
		})
60
		is.Err(t, err, nil)
61
		is.Equal(t, "| 200\tresponse body\n", got)
62
	})
63
64
	t.Run("POST request with body", func(t *testing.T) {
65
		server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
66
			is.Equal(t, "POST", r.Method)
67
			body, _ := io.ReadAll(r.Body)
68
			is.Equal(t, "test body", string(body))
69
			w.WriteHeader(http.StatusCreated)
70
			io.WriteString(w, "created")
71
		}))
72
		defer server.Close()
73
74
		got, err := (Tool{}).Execute(&viye.Context{
75
			Cmd:  "post",
76
			Args: []string{server.URL},
77
			Body: []string{"test body"},
78
		})
79
		is.Err(t, err, nil)
80
		is.Equal(t, "| 201\tcreated\n", got)
81
	})
82
83
	t.Run("request with headers", func(t *testing.T) {
84
		server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
85
			is.Equal(t, "application/json", r.Header.Get("Accept"))
86
			w.WriteHeader(http.StatusOK)
87
		}))
88
		defer server.Close()
89
90
		_, err := (Tool{}).Execute(&viye.Context{
91
			Cmd:  "get",
92
			Args: []string{server.URL},
93
			Body: []string{"Accept: application/json"},
94
		})
95
		is.Err(t, err, nil)
96
	})
97
98
	t.Run("nonexistent server returns error", func(t *testing.T) {
99
		_, err := (Tool{}).Execute(&viye.Context{
100
			Cmd:  "get",
101
			Args: []string{"http://localhost:1"},
102
		})
103
		is.Err(t, err, "failed to make a request:")
104
	})
105
}
106
107
func TestParseBody(t *testing.T) {
108
	tests := map[string]struct {
109
		inp         []string
110
		wantHeaders map[string]string
111
		wantBody    string
112
	}{
113
		"empty input": {
114
			inp:         []string{},
115
			wantHeaders: nil,
116
			wantBody:    "",
117
		},
118
		"headers only": {
119
			inp: []string{"Header: Value", "Content-Type: no"},
120
			wantHeaders: map[string]string{
121
				"Header":       "Value",
122
				"Content-Type": "no",
123
			},
124
		},
125
		"headers with body": {
126
			inp:      []string{"Header: Value", "Content-Type: no", "some input"},
127
			wantBody: "some input",
128
			wantHeaders: map[string]string{
129
				"Header":       "Value",
130
				"Content-Type": "no",
131
			},
132
		},
133
		"body with colon in value": {
134
			inp:         []string{"Accept: application/json", "plain text body"},
135
			wantHeaders: map[string]string{"Accept": "application/json"},
136
			wantBody:    "plain text body",
137
		},
138
	}
139
	for tname, tt := range tests {
140
		t.Run(tname, func(t *testing.T) {
141
			headers, body, err := parseBody(tt.inp)
142
			is.Err(t, err, nil)
143
			is.Equal(t, tt.wantHeaders, headers)
144
			is.Equal(t, tt.wantBody, body)
145
		})
146
	}
147
}