Skip to content

Commit 0f66c84

Browse files
committed
test implementation in the weatherapi package
1 parent 487d1a9 commit 0f66c84

File tree

5 files changed

+143
-5
lines changed

5 files changed

+143
-5
lines changed

go.mod

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,15 @@ module github.com/TuanKiri/weather-mcp-server
22

33
go 1.24.1
44

5-
require github.com/mark3labs/mcp-go v0.18.0
5+
require (
6+
github.com/mark3labs/mcp-go v0.18.0
7+
github.com/stretchr/testify v1.9.0
8+
)
69

710
require (
11+
github.com/davecgh/go-spew v1.1.1 // indirect
812
github.com/google/uuid v1.6.0 // indirect
13+
github.com/pmezard/go-difflib v1.0.0 // indirect
914
github.com/yosida95/uritemplate/v3 v3.0.2 // indirect
15+
gopkg.in/yaml.v3 v3.0.1 // indirect
1016
)

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,7 @@ github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsT
1010
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
1111
github.com/yosida95/uritemplate/v3 v3.0.2 h1:Ed3Oyj9yrmi9087+NczuL5BwkIc4wvTb5zIM+UJPGz4=
1212
github.com/yosida95/uritemplate/v3 v3.0.2/go.mod h1:ILOh0sOhIJR3+L/8afwt/kE++YT040gmv5BQTMR2HP4=
13+
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
14+
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
1315
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
1416
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

pkg/weatherapi/mock/current.json

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
{
2+
"location": {
3+
"name": "London",
4+
"region": "City of London, Greater London",
5+
"country": "United Kingdom",
6+
"lat": 51.5171,
7+
"lon": -0.1062,
8+
"tz_id": "Europe/London",
9+
"localtime_epoch": 1744373247,
10+
"localtime": "2025-04-11 13:07"
11+
},
12+
"current": {
13+
"last_updated_epoch": 1744372800,
14+
"last_updated": "2025-04-11 13:00",
15+
"temp_c": 18.4,
16+
"temp_f": 65.1,
17+
"is_day": 1,
18+
"condition": {
19+
"text": "Sunny",
20+
"icon": "//cdn.weatherapi.com/weather/64x64/day/113.png",
21+
"code": 1000
22+
},
23+
"wind_mph": 2.5,
24+
"wind_kph": 4.0,
25+
"wind_degree": 255,
26+
"wind_dir": "WSW",
27+
"pressure_mb": 1022.0,
28+
"pressure_in": 30.18,
29+
"precip_mm": 0.0,
30+
"precip_in": 0.0,
31+
"humidity": 45,
32+
"cloud": 0,
33+
"feelslike_c": 18.4,
34+
"feelslike_f": 65.1,
35+
"windchill_c": 19.8,
36+
"windchill_f": 67.6,
37+
"heatindex_c": 19.8,
38+
"heatindex_f": 67.6,
39+
"dewpoint_c": 1.4,
40+
"dewpoint_f": 34.5,
41+
"vis_km": 10.0,
42+
"vis_miles": 6.0,
43+
"uv": 4.2,
44+
"gust_mph": 2.8,
45+
"gust_kph": 4.6
46+
}
47+
}

pkg/weatherapi/weatherapi.go

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,15 @@ import (
1515
const baseURL = "http://api.weatherapi.com"
1616

1717
type WeatherAPI struct {
18-
key string
19-
client *http.Client
18+
key string
19+
baseURL string
20+
client *http.Client
2021
}
2122

2223
func New(key string, timeout time.Duration) *WeatherAPI {
2324
return &WeatherAPI{
24-
key: key,
25+
key: key,
26+
baseURL: baseURL,
2527
client: &http.Client{
2628
Timeout: timeout,
2729
},
@@ -36,7 +38,7 @@ func (w *WeatherAPI) Current(ctx context.Context, city string) (*models.CurrentR
3638

3739
request, err := http.NewRequestWithContext(ctx,
3840
http.MethodGet,
39-
baseURL+"/v1/current.json?"+query.Encode(),
41+
w.baseURL+"/v1/current.json?"+query.Encode(),
4042
nil,
4143
)
4244
if err != nil {

pkg/weatherapi/weatherapi_test.go

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
package weatherapi
2+
3+
import (
4+
"context"
5+
"net/http"
6+
"net/http/httptest"
7+
"os"
8+
"path/filepath"
9+
"testing"
10+
11+
"github.com/stretchr/testify/assert"
12+
13+
"github.com/TuanKiri/weather-mcp-server/pkg/weatherapi/models"
14+
)
15+
16+
func TestCurrentWeather(t *testing.T) {
17+
testCases := map[string]struct {
18+
city string
19+
errString string
20+
wait *models.CurrentResponse
21+
}{
22+
"success_request": {
23+
city: "London",
24+
wait: &models.CurrentResponse{
25+
Location: models.Location{
26+
Name: "London",
27+
Country: "United Kingdom",
28+
},
29+
Current: models.Current{
30+
TempC: 18.4,
31+
WindKph: 4,
32+
Humidity: 45,
33+
Condition: models.Condition{
34+
Text: "Sunny",
35+
Icon: "//cdn.weatherapi.com/weather/64x64/day/113.png",
36+
},
37+
},
38+
},
39+
},
40+
"bad_request": {
41+
errString: "weather API not available. Code: 400",
42+
},
43+
}
44+
45+
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
46+
q := r.URL.Query().Get("q")
47+
if q == "" {
48+
http.Error(w, "", http.StatusBadRequest)
49+
return
50+
}
51+
52+
path := filepath.Join("mock", "current.json")
53+
54+
data, err := os.ReadFile(path)
55+
if err != nil {
56+
http.Error(w, "", http.StatusInternalServerError)
57+
return
58+
}
59+
60+
w.Header().Set("Content-Type", "application/json")
61+
w.Write(data)
62+
}))
63+
defer server.Close()
64+
65+
weatherAPI := &WeatherAPI{
66+
key: "test-key",
67+
baseURL: server.URL,
68+
client: server.Client(),
69+
}
70+
71+
for name, tc := range testCases {
72+
t.Run(name, func(t *testing.T) {
73+
result, err := weatherAPI.Current(context.Background(), tc.city)
74+
if err != nil {
75+
assert.EqualError(t, err, tc.errString)
76+
}
77+
78+
assert.Equal(t, tc.wait, result)
79+
})
80+
}
81+
}

0 commit comments

Comments
 (0)