Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Is there any support for matching the rest of the key for map? #633

Open
rickyson96 opened this issue Feb 1, 2023 · 2 comments
Open

Is there any support for matching the rest of the key for map? #633

rickyson96 opened this issue Feb 1, 2023 · 2 comments

Comments

@rickyson96
Copy link
Contributor

Hi!

My usecase for this is to have a default matching value for map's key.

tc := map[string][]string{
  "test_key":  {"aaa"},
  "other_key": {},
  "ignore":    {},
}

Expect(tc).To(HaveKeyWithValue("test_key", "aaa"))

Now, the test case is that, other than test_key, it should be empty or not exists.
if I try something like this Expect(tc).To(HaveKeyWithValue(Not(Equal("test_key")), BeEmpty())), it will not match if there is no other key than the test key.

Currently I'm using this matcher for that case

Expect(tc).To(WithTransform(
  func(m map[string]string) map[string]string {
    delete(m, "test_key")
    return m
  },
  Or(BeEmpty(), HaveEach(BeEmpty())),
))

Currently, I'm doing this for a composed matcher, so, that solution seems good enough. But I think I'll ask anyway to see if there is anything I miss or that might be a possible improvement.

Thanks!

@onsi
Copy link
Owner

onsi commented Feb 1, 2023

hey is this a one-off? or are you wanting a reusable matcher that will allow you to make this assertion all over the place?

If it's a one off I'd keep it simple:

Expect(tc).To(HaveKeyWithValue("test_key", "aaa"))
for k, v := range tc {
    if k != "test_key" {
        Expect(tc).To(HaveKeyWithValue(k, BeEmpty()))
    }
}

If you want something reusable I can share a few ideas. There are lots of options, including a simple helper function:

func MapHasKeyWithValueAndOthersEmpty(tc map[string][]string, key string, value, string) {
    GinkgoHelper()
    Expect(tc).To(HaveKeyWithValue(key, value))
    for k, v := range tc {
        if k != key {
            Expect(tc).To(HaveKeyWithValue(k, BeEmpty()))
        }
    }
}

which lets you just write

MapHasKeyWithValueAndOthersEmpty(tc, "test_key", "aaa")

in your specs.

Can also show you what it looks like to make a custom matcher for this using gcustom, or to have a matcher that wraps gstruct.

@rickyson96
Copy link
Contributor Author

Actually, I'm writing custom matcher so that I can abstract away the matcher's details.

type MyStruct struct {
	ValuesMap map[string][]string
}

func HavePendingValue(key string, pendingValues []string) types.GomegaMatcher {
	return WithTransform(
		func(s MyStruct) map[string][]string {
			return s.ValuesMap
		},
		SatisfyAll(
			HaveKeyWithValue(key, ConsistOf(pendingValues)),
			WithTransform(func(pv map[string][]string) map[string][]string {
				delete(pv, key)
				return pv
			}, Or(BeEmpty(), HaveEach(BeEmpty()))),
		),
	)
}

// and on the test case
Expect(myStruct).To(HavePendingValue("test_key", []string{"abc"}))

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants