Skip to content

Commit 106e689

Browse files
authored
unit tests for parseRequestURL function (#709)
* unit tests for the `PathParams`, `RawPathParams` and `QueryParams` added by client and request * unit tests for `client.HostURL` and `client.BaseURL` * use `client.BaseURL` by default and fallback to `client.HostURL` if empty
1 parent 1ae2aac commit 106e689

File tree

2 files changed

+235
-1
lines changed

2 files changed

+235
-1
lines changed

middleware.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,12 @@ func parseRequestURL(c *Client, r *Request) error {
6464
r.URL = "/" + r.URL
6565
}
6666

67-
reqURL, err = url.Parse(c.HostURL + r.URL)
67+
// TODO: change to use c.BaseURL only in v3.0.0
68+
baseURL := c.BaseURL
69+
if len(baseURL) == 0 {
70+
baseURL = c.HostURL
71+
}
72+
reqURL, err = url.Parse(baseURL + r.URL)
6873
if err != nil {
6974
return err
7075
}

middleware_test.go

Lines changed: 229 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,229 @@
1+
package resty
2+
3+
import (
4+
"net/url"
5+
"testing"
6+
)
7+
8+
func Test_parseRequestURL(t *testing.T) {
9+
for _, tt := range []struct {
10+
name string
11+
init func(c *Client, r *Request)
12+
expectedURL string
13+
}{
14+
{
15+
name: "apply client path parameters",
16+
init: func(c *Client, r *Request) {
17+
c.SetPathParams(map[string]string{
18+
"foo": "1",
19+
"bar": "2/3",
20+
})
21+
r.URL = "https://example.com/{foo}/{bar}"
22+
},
23+
expectedURL: "https://example.com/1/2%2F3",
24+
},
25+
{
26+
name: "apply request path parameters",
27+
init: func(c *Client, r *Request) {
28+
r.SetPathParams(map[string]string{
29+
"foo": "4",
30+
"bar": "5/6",
31+
})
32+
r.URL = "https://example.com/{foo}/{bar}"
33+
},
34+
expectedURL: "https://example.com/4/5%2F6",
35+
},
36+
{
37+
name: "apply request and client path parameters",
38+
init: func(c *Client, r *Request) {
39+
c.SetPathParams(map[string]string{
40+
"foo": "1", // ignored, because of the request's "foo"
41+
"bar": "2/3",
42+
})
43+
r.SetPathParams(map[string]string{
44+
"foo": "4/5",
45+
})
46+
r.URL = "https://example.com/{foo}/{bar}"
47+
},
48+
expectedURL: "https://example.com/4%2F5/2%2F3",
49+
},
50+
{
51+
name: "apply client raw path parameters",
52+
init: func(c *Client, r *Request) {
53+
c.SetRawPathParams(map[string]string{
54+
"foo": "1/2",
55+
"bar": "3",
56+
})
57+
r.URL = "https://example.com/{foo}/{bar}"
58+
},
59+
expectedURL: "https://example.com/1/2/3",
60+
},
61+
{
62+
name: "apply request raw path parameters",
63+
init: func(c *Client, r *Request) {
64+
r.SetRawPathParams(map[string]string{
65+
"foo": "4",
66+
"bar": "5/6",
67+
})
68+
r.URL = "https://example.com/{foo}/{bar}"
69+
},
70+
expectedURL: "https://example.com/4/5/6",
71+
},
72+
{
73+
name: "apply request and client raw path parameters",
74+
init: func(c *Client, r *Request) {
75+
c.SetRawPathParams(map[string]string{
76+
"foo": "1", // ignored, because of the request's "foo"
77+
"bar": "2/3",
78+
})
79+
r.SetRawPathParams(map[string]string{
80+
"foo": "4/5",
81+
})
82+
r.URL = "https://example.com/{foo}/{bar}"
83+
},
84+
expectedURL: "https://example.com/4/5/2/3",
85+
},
86+
{
87+
name: "apply request path and raw path parameters",
88+
init: func(c *Client, r *Request) {
89+
r.SetPathParams(map[string]string{
90+
"foo": "4/5",
91+
}).SetRawPathParams(map[string]string{
92+
"foo": "4/5", // ignored, because the PathParams takes precedence over the RawPathParams
93+
"bar": "6/7",
94+
})
95+
r.URL = "https://example.com/{foo}/{bar}"
96+
},
97+
expectedURL: "https://example.com/4%2F5/6/7",
98+
},
99+
{
100+
name: "using BaseURL with absolute URL in request",
101+
init: func(c *Client, r *Request) {
102+
c.SetBaseURL("https://foo.bar") // ignored
103+
r.URL = "https://example.com/"
104+
},
105+
expectedURL: "https://example.com/",
106+
},
107+
{
108+
name: "using BaseURL with relative path in request URL without leading slash",
109+
init: func(c *Client, r *Request) {
110+
c.SetBaseURL("https://example.com")
111+
r.URL = "foo/bar"
112+
},
113+
expectedURL: "https://example.com/foo/bar",
114+
},
115+
{
116+
name: "using BaseURL with relative path in request URL wit leading slash",
117+
init: func(c *Client, r *Request) {
118+
c.SetBaseURL("https://example.com")
119+
r.URL = "/foo/bar"
120+
},
121+
expectedURL: "https://example.com/foo/bar",
122+
},
123+
{
124+
name: "using deprecated HostURL with relative path in request URL",
125+
init: func(c *Client, r *Request) {
126+
c.HostURL = "https://example.com"
127+
r.URL = "foo/bar"
128+
},
129+
expectedURL: "https://example.com/foo/bar",
130+
},
131+
{
132+
name: "request URL without scheme",
133+
init: func(c *Client, r *Request) {
134+
r.URL = "example.com/foo/bar"
135+
},
136+
expectedURL: "/example.com/foo/bar",
137+
},
138+
{
139+
name: "BaseURL without scheme",
140+
init: func(c *Client, r *Request) {
141+
c.SetBaseURL("example.com")
142+
r.URL = "foo/bar"
143+
},
144+
expectedURL: "example.com/foo/bar",
145+
},
146+
{
147+
name: "using SetScheme and BaseURL without scheme",
148+
init: func(c *Client, r *Request) {
149+
c.SetBaseURL("example.com").SetScheme("https")
150+
r.URL = "foo/bar"
151+
},
152+
expectedURL: "https://example.com/foo/bar",
153+
},
154+
{
155+
name: "adding query parameters by client",
156+
init: func(c *Client, r *Request) {
157+
c.SetQueryParams(map[string]string{
158+
"foo": "1",
159+
"bar": "2",
160+
})
161+
r.URL = "https://example.com/"
162+
},
163+
expectedURL: "https://example.com/?foo=1&bar=2",
164+
},
165+
{
166+
name: "adding query parameters by request",
167+
init: func(c *Client, r *Request) {
168+
r.SetQueryParams(map[string]string{
169+
"foo": "1",
170+
"bar": "2",
171+
})
172+
r.URL = "https://example.com/"
173+
},
174+
expectedURL: "https://example.com/?foo=1&bar=2",
175+
},
176+
{
177+
name: "adding query parameters by client and request",
178+
init: func(c *Client, r *Request) {
179+
c.SetQueryParams(map[string]string{
180+
"foo": "1", // ignored, because of the "foo" parameter in request
181+
"bar": "2",
182+
})
183+
c.SetQueryParams(map[string]string{
184+
"foo": "3",
185+
})
186+
r.URL = "https://example.com/"
187+
},
188+
expectedURL: "https://example.com/?foo=3&bar=2",
189+
},
190+
} {
191+
t.Run(tt.name, func(t *testing.T) {
192+
c := New()
193+
r := c.R()
194+
tt.init(c, r)
195+
if err := parseRequestURL(c, r); err != nil {
196+
t.Errorf("parseRequestURL() error = %v", err)
197+
}
198+
199+
// compare URLs without query parameters first
200+
// then compare query parameters, because the order of the items in a map is not guarantied
201+
expectedURL, _ := url.Parse(tt.expectedURL)
202+
expectedQuery := expectedURL.Query()
203+
expectedURL.RawQuery = ""
204+
actualURL, _ := url.Parse(r.URL)
205+
actualQuery := actualURL.Query()
206+
actualURL.RawQuery = ""
207+
if expectedURL.String() != actualURL.String() {
208+
t.Errorf("r.URL = %q does not match expected %q", r.URL, tt.expectedURL)
209+
}
210+
if len(expectedQuery) != len(actualQuery) {
211+
t.Errorf("r.URL = %q does not match expected %q", r.URL, tt.expectedURL)
212+
}
213+
for name, expected := range expectedQuery {
214+
actual, ok := actualQuery[name]
215+
if !ok {
216+
t.Errorf("r.URL = %q does not match expected %q", r.URL, tt.expectedURL)
217+
}
218+
if len(expected) != len(actual) {
219+
t.Errorf("r.URL = %q does not match expected %q", r.URL, tt.expectedURL)
220+
}
221+
for i, v := range expected {
222+
if v != actual[i] {
223+
t.Errorf("r.URL = %q does not match expected %q", r.URL, tt.expectedURL)
224+
}
225+
}
226+
}
227+
})
228+
}
229+
}

0 commit comments

Comments
 (0)