build(deps): bump github.com/onsi/gomega from 1.40.0 to 1.42.1

Bumps [github.com/onsi/gomega](https://github.com/onsi/gomega) from 1.40.0 to 1.42.1.
- [Release notes](https://github.com/onsi/gomega/releases)
- [Changelog](https://github.com/onsi/gomega/blob/master/CHANGELOG.md)
- [Commits](https://github.com/onsi/gomega/compare/v1.40.0...v1.42.1)

---
updated-dependencies:
- dependency-name: github.com/onsi/gomega
  dependency-version: 1.42.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
This commit is contained in:
dependabot[bot]
2026-06-24 14:43:40 +00:00
committed by GitHub
parent c1278f4b99
commit 5abfaabae6
47 changed files with 1236 additions and 328 deletions

View File

@@ -1,3 +1,21 @@
## 1.42.1
Bump Dependencies
## 1.42.0
Add a set of Claude skill as a marketplace plugin
## 1.41.0
### Features
Add `BeASlice` and `BeAnArray` matchers
### Fixes
Object formatting now detects pointer cycles to avoid runaway formatting output.
## 1.40.0
We're adopting a new release strategy to minimize dependency bloat in projects that consume Gomega. It is a limitation of the go mod toolchain that _test_ subdependencies of your project's direct dependencies get pulled in as *indirect* dependencies. In the case of Gomega, this ends up pulling in all of Ginkgo into your `go.mod` even if you are only using Gomega (Gomega uses Ginkgo for its own tests).

View File

@@ -6,6 +6,19 @@ Jump straight to the [docs](http://onsi.github.io/gomega/) to learn about Gomega
If you have a question, comment, bug report, feature request, etc. please open a GitHub issue.
## Using Gomega with Claude Code
Gomega ships a set of [Claude Code](https://claude.com/claude-code) skills as a **plugin**, so an agent writing assertions in *your* suite has Gomega's idioms — the full matcher catalog, `Eventually`/`Consistently`, and the `gstruct`/`ghttp`/`gexec`/`gbytes`/`gleak`/`gmeasure` sub-libraries — on hand. The Gomega repo doubles as the plugin marketplace, so installation is two commands. From inside Claude Code:
```
/plugin marketplace add onsi/gomega
/plugin install gomega@gomega
```
(or non-interactively: `claude plugin marketplace add onsi/gomega` then `claude plugin install gomega@gomega`)
This installs a family of `gomega:*` skills that activate automatically while you write tests. See the [docs](http://onsi.github.io/gomega/#using-gomega-with-claude-code) for the full list.
## [Ginkgo](http://github.com/onsi/ginkgo): a BDD Testing Framework for Golang
Learn more about Ginkgo [here](http://onsi.github.io/ginkgo/)

View File

@@ -262,7 +262,7 @@ func Object(object any, indentation uint) string {
if err, ok := object.(error); ok && !isNilValue(value) { // isNilValue check needed here to avoid nil deref due to boxed nil
commonRepresentation += "\n" + IndentString(err.Error(), indentation) + "\n" + indent
}
return fmt.Sprintf("%s<%s>: %s%s", indent, formatType(value), commonRepresentation, formatValue(value, indentation, true))
return fmt.Sprintf("%s<%s>: %s%s", indent, formatType(value), commonRepresentation, formatValue(value, indentation, true, map[uintptr]struct{}{}))
}
/*
@@ -306,7 +306,7 @@ func formatType(v reflect.Value) string {
}
}
func formatValue(value reflect.Value, indentation uint, isTopLevel bool) string {
func formatValue(value reflect.Value, indentation uint, isTopLevel bool, visited map[uintptr]struct{}) string {
if indentation > MaxDepth {
return "..."
}
@@ -367,23 +367,28 @@ func formatValue(value reflect.Value, indentation uint, isTopLevel bool) string
case reflect.Func:
return fmt.Sprintf("0x%x", value.Pointer())
case reflect.Ptr:
return formatValue(value.Elem(), indentation, isTopLevel)
ptr := value.Pointer()
if _, ok := visited[ptr]; ok {
return fmt.Sprintf("0x%x (cyclic reference)", ptr)
}
visited[ptr] = struct{}{}
return formatValue(value.Elem(), indentation, isTopLevel, visited)
case reflect.Slice:
return truncateLongStrings(formatSlice(value, indentation))
return truncateLongStrings(formatSlice(value, indentation, visited))
case reflect.String:
return truncateLongStrings(formatString(value.String(), indentation, isTopLevel))
case reflect.Array:
return truncateLongStrings(formatSlice(value, indentation))
return truncateLongStrings(formatSlice(value, indentation, visited))
case reflect.Map:
return truncateLongStrings(formatMap(value, indentation))
return truncateLongStrings(formatMap(value, indentation, visited))
case reflect.Struct:
if value.Type() == timeType && value.CanInterface() {
t, _ := value.Interface().(time.Time)
return t.Format(time.RFC3339Nano)
}
return truncateLongStrings(formatStruct(value, indentation))
return truncateLongStrings(formatStruct(value, indentation, visited))
case reflect.Interface:
return formatInterface(value, indentation)
return formatInterface(value, indentation, visited)
default:
if value.CanInterface() {
return truncateLongStrings(fmt.Sprintf("%#v", value.Interface()))
@@ -414,7 +419,7 @@ func formatString(object any, indentation uint, isTopLevel bool) string {
}
}
func formatSlice(v reflect.Value, indentation uint) string {
func formatSlice(v reflect.Value, indentation uint, visited map[uintptr]struct{}) string {
if v.Kind() == reflect.Slice && v.Type().Elem().Kind() == reflect.Uint8 && isPrintableString(string(v.Bytes())) {
return formatString(v.Bytes(), indentation, false)
}
@@ -423,7 +428,7 @@ func formatSlice(v reflect.Value, indentation uint) string {
result := make([]string, l)
longest := 0
for i := range l {
result[i] = formatValue(v.Index(i), indentation+1, false)
result[i] = formatValue(v.Index(i), indentation+1, false, visited)
if len(result[i]) > longest {
longest = len(result[i])
}
@@ -436,14 +441,14 @@ func formatSlice(v reflect.Value, indentation uint) string {
return fmt.Sprintf("[%s]", strings.Join(result, ", "))
}
func formatMap(v reflect.Value, indentation uint) string {
func formatMap(v reflect.Value, indentation uint, visited map[uintptr]struct{}) string {
l := v.Len()
result := make([]string, l)
longest := 0
for i, key := range v.MapKeys() {
value := v.MapIndex(key)
result[i] = fmt.Sprintf("%s: %s", formatValue(key, indentation+1, false), formatValue(value, indentation+1, false))
result[i] = fmt.Sprintf("%s: %s", formatValue(key, indentation+1, false, visited), formatValue(value, indentation+1, false, visited))
if len(result[i]) > longest {
longest = len(result[i])
}
@@ -456,7 +461,7 @@ func formatMap(v reflect.Value, indentation uint) string {
return fmt.Sprintf("{%s}", strings.Join(result, ", "))
}
func formatStruct(v reflect.Value, indentation uint) string {
func formatStruct(v reflect.Value, indentation uint, visited map[uintptr]struct{}) string {
t := v.Type()
l := v.NumField()
@@ -465,7 +470,7 @@ func formatStruct(v reflect.Value, indentation uint) string {
for i := range l {
structField := t.Field(i)
fieldEntry := v.Field(i)
representation := fmt.Sprintf("%s: %s", structField.Name, formatValue(fieldEntry, indentation+1, false))
representation := fmt.Sprintf("%s: %s", structField.Name, formatValue(fieldEntry, indentation+1, false, visited))
result = append(result, representation)
if len(representation) > longest {
longest = len(representation)
@@ -478,8 +483,8 @@ func formatStruct(v reflect.Value, indentation uint) string {
return fmt.Sprintf("{%s}", strings.Join(result, ", "))
}
func formatInterface(v reflect.Value, indentation uint) string {
return fmt.Sprintf("<%s>%s", formatType(v.Elem()), formatValue(v.Elem(), indentation, false))
func formatInterface(v reflect.Value, indentation uint, visited map[uintptr]struct{}) string {
return fmt.Sprintf("<%s>%s", formatType(v.Elem()), formatValue(v.Elem(), indentation, false, visited))
}
func isNilValue(a reflect.Value) bool {

View File

@@ -22,7 +22,7 @@ import (
"github.com/onsi/gomega/types"
)
const GOMEGA_VERSION = "1.40.0"
const GOMEGA_VERSION = "1.42.1"
const nilGomegaPanic = `You are trying to make an assertion, but haven't registered Gomega's fail handler.
If you're using Ginkgo then you probably forgot to put your assertion in an It().

View File

@@ -621,6 +621,18 @@ func BeADirectory() types.GomegaMatcher {
return &matchers.BeADirectoryMatcher{}
}
// BeASlice succeeds if actual is a value of slice type.
// This is useful when actual has type any (interface{}) and you want to assert it is a slice.
func BeASlice() types.GomegaMatcher {
return &matchers.BeASliceMatcher{}
}
// BeAnArray succeeds if actual is a value of array type.
// This is useful when actual has type any (interface{}) and you want to assert it is an array.
func BeAnArray() types.GomegaMatcher {
return &matchers.BeAnArrayMatcher{}
}
// HaveHTTPStatus succeeds if the Status or StatusCode field of an HTTP response matches.
// Actual must be either a *http.Response or *httptest.ResponseRecorder.
// Expected must be either an int or a string.

View File

@@ -0,0 +1,28 @@
// untested sections: 1
package matchers
import (
"fmt"
"reflect"
"github.com/onsi/gomega/format"
)
type BeASliceMatcher struct {
}
func (matcher *BeASliceMatcher) Match(actual any) (success bool, err error) {
if actual == nil {
return false, fmt.Errorf("BeASlice matcher expects a value, got nil")
}
return reflect.TypeOf(actual).Kind() == reflect.Slice, nil
}
func (matcher *BeASliceMatcher) FailureMessage(actual any) (message string) {
return format.Message(actual, "to be a slice")
}
func (matcher *BeASliceMatcher) NegatedFailureMessage(actual any) (message string) {
return format.Message(actual, "not to be a slice")
}

View File

@@ -0,0 +1,28 @@
// untested sections: 1
package matchers
import (
"fmt"
"reflect"
"github.com/onsi/gomega/format"
)
type BeAnArrayMatcher struct {
}
func (matcher *BeAnArrayMatcher) Match(actual any) (success bool, err error) {
if actual == nil {
return false, fmt.Errorf("BeAnArray matcher expects a value, got nil")
}
return reflect.TypeOf(actual).Kind() == reflect.Array, nil
}
func (matcher *BeAnArrayMatcher) FailureMessage(actual any) (message string) {
return format.Message(actual, "to be an array")
}
func (matcher *BeAnArrayMatcher) NegatedFailureMessage(actual any) (message string) {
return format.Message(actual, "not to be an array")
}

View File

@@ -66,6 +66,12 @@ func MatchMayChangeInTheFuture(matcher GomegaMatcher, value any) bool {
// AsyncAssertions are returned by Eventually and Consistently and enable matchers to be polled repeatedly to ensure
// they are eventually satisfied
//
// The optional optionalDescription argument allows you to annotate the assertion with additional information.
// It is passed as the second argument and can be a format string followed by arguments, or a func() string.
// The description is included in failure messages to provide context.
//
// For details on annotating assertions, see: https://onsi.github.io/gomega/#annotating-assertions
type AsyncAssertion interface {
Should(matcher GomegaMatcher, optionalDescription ...any) bool
ShouldNot(matcher GomegaMatcher, optionalDescription ...any) bool
@@ -86,6 +92,12 @@ type AsyncAssertion interface {
}
// Assertions are returned by Ω and Expect and enable assertions against Gomega matchers
//
// The optional optionalDescription argument allows you to annotate the assertion with additional information.
// It is passed as the second argument and can be a format string followed by arguments, or a func() string.
// The description is included in failure messages to provide context.
//
// For details on annotating assertions, see: https://onsi.github.io/gomega/#annotating-assertions
type Assertion interface {
Should(matcher GomegaMatcher, optionalDescription ...any) bool
ShouldNot(matcher GomegaMatcher, optionalDescription ...any) bool