Compare commits

...

4 Commits

Author SHA1 Message Date
Abhiyan Khanal
567fb4dd96
Merge 3f607b8662710b3602b03817cfc2f171416f6591 into 5f4f9643258dc2a65e684b63f12c8d543c936c67 2026-05-15 04:14:45 +08:00
dependabot[bot]
5f4f964325
chore(deps): bump the actions group across 1 directory with 2 updates (#4640)
Bumps the actions group with 2 updates in the / directory: [codecov/codecov-action](https://github.com/codecov/codecov-action) and [aquasecurity/trivy-action](https://github.com/aquasecurity/trivy-action).


Updates `codecov/codecov-action` from 5 to 6
- [Release notes](https://github.com/codecov/codecov-action/releases)
- [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/codecov/codecov-action/compare/v5...v6)

Updates `aquasecurity/trivy-action` from 0.35.0 to 0.36.0
- [Release notes](https://github.com/aquasecurity/trivy-action/releases)
- [Commits](https://github.com/aquasecurity/trivy-action/compare/0.35.0...v0.36.0)

---
updated-dependencies:
- dependency-name: codecov/codecov-action
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: actions
- dependency-name: aquasecurity/trivy-action
  dependency-version: 0.36.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-09 10:20:32 +08:00
Abhiyan Khanal
3f607b8662 fix(test): use stdlib constants for HTTP methods in test helpers
Replace string literals with http.Method* constants to satisfy
the usestdlibvars linter.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 19:09:51 +05:45
Abhiyan Khanal
4a0302068c feat(test): add RunTestHandler to flush status in test contexts
When using CreateTestContext directly to test handlers, ctx.Status()
sets the status internally but it is not flushed to the underlying
httptest.ResponseRecorder. RunTestHandler creates a test context, runs
the handler chain, and calls WriteHeaderNow() so that the status code
is properly reflected in the ResponseWriter.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 19:09:51 +05:45
4 changed files with 128 additions and 3 deletions

View File

@ -78,6 +78,6 @@ jobs:
run: make test
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v5
uses: codecov/codecov-action@v6
with:
flags: ${{ matrix.os }},go-${{ matrix.go }},${{ matrix.test-tags }}

View File

@ -27,7 +27,7 @@ jobs:
fetch-depth: 0
- name: Run Trivy vulnerability scanner (source code)
uses: aquasecurity/trivy-action@0.35.0
uses: aquasecurity/trivy-action@v0.36.0
with:
scan-type: "fs"
scan-ref: "."
@ -44,7 +44,7 @@ jobs:
sarif_file: "trivy-results.sarif"
- name: Run Trivy scanner (table output for logs)
uses: aquasecurity/trivy-action@0.35.0
uses: aquasecurity/trivy-action@v0.36.0
if: always()
with:
scan-type: "fs"

View File

@ -34,6 +34,30 @@ func CreateTestContextOnly(w http.ResponseWriter, r *Engine) (c *Context) {
return
}
// RunTestHandler creates a test context, assigns the given request, executes
// the provided handler chain, and flushes the status code to the underlying
// ResponseWriter. This solves the problem where ctx.Status() sets the status
// internally but does not flush it to an httptest.ResponseRecorder when using
// CreateTestContext directly.
//
// Example usage:
//
// w := httptest.NewRecorder()
// req := httptest.NewRequest("POST", "/resource", nil)
// c := gin.RunTestHandler(w, req, func(c *gin.Context) {
// c.Status(http.StatusCreated)
// })
// // w.Code is now 201, not 200
func RunTestHandler(w http.ResponseWriter, req *http.Request, handlers ...HandlerFunc) *Context {
c, _ := CreateTestContext(w)
c.Request = req
c.handlers = handlers
c.index = -1
c.Next()
c.Writer.WriteHeaderNow()
return c
}
// waitForServerReady waits for a server to be ready by making HTTP requests
// with exponential backoff. This is more reliable than time.Sleep() for testing.
func waitForServerReady(url string, maxAttempts int) error {

101
test_helpers_test.go Normal file
View File

@ -0,0 +1,101 @@
// Copyright 2017 Manu Martinez-Almeida. All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.
package gin
import (
"net/http"
"net/http/httptest"
"testing"
"github.com/stretchr/testify/assert"
)
func TestRunTestHandlerFlushesStatusCode(t *testing.T) {
tests := []struct {
name string
statusCode int
}{
{"201 Created", http.StatusCreated},
{"204 No Content", http.StatusNoContent},
{"400 Bad Request", http.StatusBadRequest},
{"404 Not Found", http.StatusNotFound},
{"500 Internal Server Error", http.StatusInternalServerError},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
w := httptest.NewRecorder()
req := httptest.NewRequest(http.MethodGet, "/", nil)
code := tt.statusCode
c := RunTestHandler(w, req, func(c *Context) {
c.Status(code)
})
assert.Equal(t, code, w.Code)
assert.Equal(t, code, c.Writer.Status())
})
}
}
func TestRunTestHandlerMultipleHandlers(t *testing.T) {
w := httptest.NewRecorder()
req := httptest.NewRequest(http.MethodPost, "/resource", nil)
callOrder := []string{}
middleware := func(c *Context) {
callOrder = append(callOrder, "middleware")
c.Next()
}
handler := func(c *Context) {
callOrder = append(callOrder, "handler")
c.Status(http.StatusCreated)
}
c := RunTestHandler(w, req, middleware, handler)
assert.Equal(t, http.StatusCreated, w.Code)
assert.Equal(t, http.StatusCreated, c.Writer.Status())
assert.Equal(t, []string{"middleware", "handler"}, callOrder)
}
func TestRunTestHandlerDefaultStatus(t *testing.T) {
w := httptest.NewRecorder()
req := httptest.NewRequest(http.MethodGet, "/", nil)
RunTestHandler(w, req, func(c *Context) {
// Handler that does not set a status explicitly.
})
assert.Equal(t, http.StatusOK, w.Code)
}
func TestRunTestHandlerSetsRequest(t *testing.T) {
w := httptest.NewRecorder()
req := httptest.NewRequest(http.MethodPut, "/items/42", nil)
c := RunTestHandler(w, req, func(c *Context) {
c.Status(http.StatusOK)
})
assert.Equal(t, req, c.Request)
}
func TestCreateTestContextBackwardCompatible(t *testing.T) {
// Verify that CreateTestContext still behaves the same way:
// status is stored internally but NOT flushed to the ResponseRecorder.
w := httptest.NewRecorder()
c, _ := CreateTestContext(w)
c.Status(http.StatusCreated)
// The internal status should be set.
assert.Equal(t, http.StatusCreated, c.Writer.Status())
// But w.Code should still be the default 200 because WriteHeaderNow
// was never called. This confirms backward compatibility.
assert.Equal(t, http.StatusOK, w.Code)
}