From 99929bd15edfffde4f1bbe3ee1bbbfaf18b9696d Mon Sep 17 00:00:00 2001 From: Michael Brooks Date: Mon, 11 Aug 2025 11:11:40 -0700 Subject: [PATCH] fix: url checker uses HEAD instead of GET --- internal/deputil/url.go | 2 +- internal/deputil/url_test.go | 6 +++--- internal/pkg/create/create_test.go | 16 ++++++++-------- internal/slackhttp/http.go | 1 + internal/slackhttp/http_mock.go | 13 +++++++++++++ 5 files changed, 26 insertions(+), 12 deletions(-) diff --git a/internal/deputil/url.go b/internal/deputil/url.go index 3d096365..0e065225 100644 --- a/internal/deputil/url.go +++ b/internal/deputil/url.go @@ -22,7 +22,7 @@ import ( // URLChecker returns url if its status code is 200, otherwise returns empty string func URLChecker(httpClient slackhttp.HTTPClient, url string) string { - resp, err := httpClient.Get(url) + resp, err := httpClient.Head(url) if err != nil { return "" } diff --git a/internal/deputil/url_test.go b/internal/deputil/url_test.go index f9a30334..b7a89f46 100644 --- a/internal/deputil/url_test.go +++ b/internal/deputil/url_test.go @@ -35,7 +35,7 @@ func Test_URLChecker(t *testing.T) { expectedURL: "https://github.com/slack-samples/deno-starter-template", setupHTTPClientMock: func(httpClientMock *slackhttp.HTTPClientMock) { resOK := slackhttp.MockHTTPResponse(http.StatusOK, "OK") - httpClientMock.On("Get", mock.Anything).Return(resOK, nil) + httpClientMock.On("Head", mock.Anything).Return(resOK, nil) }, }, "Returns an empty string when the HTTP status code is not 200": { @@ -43,14 +43,14 @@ func Test_URLChecker(t *testing.T) { expectedURL: "", setupHTTPClientMock: func(httpClientMock *slackhttp.HTTPClientMock) { resNotFound := slackhttp.MockHTTPResponse(http.StatusNotFound, "Not Found") - httpClientMock.On("Get", mock.Anything).Return(resNotFound, nil) + httpClientMock.On("Head", mock.Anything).Return(resNotFound, nil) }, }, "Returns an empty string when the HTTPClient has an error": { url: "invalid_url", expectedURL: "", setupHTTPClientMock: func(httpClientMock *slackhttp.HTTPClientMock) { - httpClientMock.On("Get", mock.Anything).Return(nil, fmt.Errorf("HTTPClient error")) + httpClientMock.On("Head", mock.Anything).Return(nil, fmt.Errorf("HTTPClient error")) }, }, } diff --git a/internal/pkg/create/create_test.go b/internal/pkg/create/create_test.go index 270acf6b..397db160 100644 --- a/internal/pkg/create/create_test.go +++ b/internal/pkg/create/create_test.go @@ -89,7 +89,7 @@ func Test_generateGitZipFileURL(t *testing.T) { expectedURL: "https://github.com/slack-samples/deno-starter-template/archive/refs/heads/main.zip", setupHTTPClientMock: func(httpClientMock *slackhttp.HTTPClientMock) { res := slackhttp.MockHTTPResponse(http.StatusOK, "OK") - httpClientMock.On("Get", mock.Anything).Return(res, nil) + httpClientMock.On("Head", mock.Anything).Return(res, nil) }, }, "Returns the zip URL using the master branch when no branch is provided and main branch doesn't exist": { @@ -98,8 +98,8 @@ func Test_generateGitZipFileURL(t *testing.T) { expectedURL: "https://github.com/slack-samples/deno-starter-template/archive/refs/heads/master.zip", setupHTTPClientMock: func(httpClientMock *slackhttp.HTTPClientMock) { res := slackhttp.MockHTTPResponse(http.StatusOK, "OK") - httpClientMock.On("Get", "https://github.com/slack-samples/deno-starter-template/archive/refs/heads/main.zip").Return(nil, fmt.Errorf("HttpClient error")) - httpClientMock.On("Get", "https://github.com/slack-samples/deno-starter-template/archive/refs/heads/master.zip").Return(res, nil) + httpClientMock.On("Head", "https://github.com/slack-samples/deno-starter-template/archive/refs/heads/main.zip").Return(nil, fmt.Errorf("HttpClient error")) + httpClientMock.On("Head", "https://github.com/slack-samples/deno-starter-template/archive/refs/heads/master.zip").Return(res, nil) }, }, "Returns the zip URL using the specified branch when a branch is provided": { @@ -108,7 +108,7 @@ func Test_generateGitZipFileURL(t *testing.T) { expectedURL: "https://github.com/slack-samples/deno-starter-template/archive/refs/heads/pre-release-0316.zip", setupHTTPClientMock: func(httpClientMock *slackhttp.HTTPClientMock) { res := slackhttp.MockHTTPResponse(http.StatusOK, "OK") - httpClientMock.On("Get", mock.Anything).Return(res, nil) + httpClientMock.On("Head", mock.Anything).Return(res, nil) }, }, "Returns an empty string when the HTTP status code is not 200": { @@ -117,7 +117,7 @@ func Test_generateGitZipFileURL(t *testing.T) { expectedURL: "", setupHTTPClientMock: func(httpClientMock *slackhttp.HTTPClientMock) { res := slackhttp.MockHTTPResponse(http.StatusNotFound, "Not Found") - httpClientMock.On("Get", mock.Anything).Return(res, nil) + httpClientMock.On("Head", mock.Anything).Return(res, nil) }, }, "Returns an empty string when the HTTPClient has an error": { @@ -125,7 +125,7 @@ func Test_generateGitZipFileURL(t *testing.T) { gitBranch: "", expectedURL: "", setupHTTPClientMock: func(httpClientMock *slackhttp.HTTPClientMock) { - httpClientMock.On("Get", mock.Anything).Return(nil, fmt.Errorf("HTTPClient error")) + httpClientMock.On("Head", mock.Anything).Return(nil, fmt.Errorf("HTTPClient error")) }, }, "Returns the zip URL with .git suffix removed": { @@ -134,7 +134,7 @@ func Test_generateGitZipFileURL(t *testing.T) { expectedURL: "https://github.com/slack-samples/deno-starter-template/archive/refs/heads/main.zip", setupHTTPClientMock: func(httpClientMock *slackhttp.HTTPClientMock) { res := slackhttp.MockHTTPResponse(http.StatusOK, "OK") - httpClientMock.On("Get", mock.Anything).Return(res, nil) + httpClientMock.On("Head", mock.Anything).Return(res, nil) }, }, "Returns the zip URL with .git inside URL preserved": { @@ -143,7 +143,7 @@ func Test_generateGitZipFileURL(t *testing.T) { expectedURL: "https://github.com/slack-samples/deno.git-starter-template/archive/refs/heads/main.zip", setupHTTPClientMock: func(httpClientMock *slackhttp.HTTPClientMock) { res := slackhttp.MockHTTPResponse(http.StatusOK, "OK") - httpClientMock.On("Get", mock.Anything).Return(res, nil) + httpClientMock.On("Head", mock.Anything).Return(res, nil) }, }, } diff --git a/internal/slackhttp/http.go b/internal/slackhttp/http.go index 3cf38b3b..4ff831ba 100644 --- a/internal/slackhttp/http.go +++ b/internal/slackhttp/http.go @@ -29,6 +29,7 @@ const ( type HTTPClient interface { Do(req *http.Request) (*http.Response, error) Get(url string) (*http.Response, error) + Head(url string) (*http.Response, error) } // HTTPClientOptions allows for the customization of a http.Client. diff --git a/internal/slackhttp/http_mock.go b/internal/slackhttp/http_mock.go index f6842f81..0b5f9aca 100644 --- a/internal/slackhttp/http_mock.go +++ b/internal/slackhttp/http_mock.go @@ -53,6 +53,19 @@ func (m *HTTPClientMock) Get(url string) (*http.Response, error) { return httpResp, args.Error(1) } +// Head is a mock that tracks the calls to Head and returns the mocked http.Response and error. +func (m *HTTPClientMock) Head(url string) (*http.Response, error) { + args := m.Called(url) + + // http.Response can be nil when an error is provided. + var httpResp *http.Response + if _httpResp, ok := args.Get(0).(*http.Response); ok { + httpResp = _httpResp + } + + return httpResp, args.Error(1) +} + // MockHTTPResponse is a helper that returns a mocked http.Response with the provided httpStatus and body. func MockHTTPResponse(httpStatus int, body string) *http.Response { resWriter := httptest.NewRecorder()