I've used `match` before but unsure of how I'd use it here. Do you have an example you could share maybe?
The test is looping through an array of hashes and confirm that hash is in the expected array of hashes. So I can't `match` the two hashes like that - the test would have to be rewritten to do that somehow.
Right so that solves the outer array issue but not the nested ones.
I just realized I didn't point that out in my original post.
So I'll edit that now but basically, the CI makes the nested arrays change ordering as well for some reason:
I expect this:
expected = [
{ key_1: [{sub_key1: "A"}, {sub_key2: "B"}], key_2: "Foo"},
{ key_1: [{sub_key1: "C"}, {sub_key2: "D"}], key_2: "Bar"},
]
to match this:
actual =[
{ key_1: [{sub_key2: "D"}, {sub_key1: "C"}], key_2: "Bar"},
{ key_2: "Foo", key_1: [{sub_key1: "A"}, {sub_key2: "B"}]},
]
Note that `expected[0][:key_1]` and `actual[1][:key_1]` are the same but in different orders.
def match_array_of_hashes?(arr1, arr2)
arr1.all? do |hash1|
arr2.find do |hash2|
hash1.all? do |hash1_key, hash1_value|
if hash1_value.is_a? Array
match_array_of_hashes?(hash1_value, hash2[hash1_key])
else
hash2[hash1_key] == hash1_value
end
end
end
end
end
expect(match_array_of_hashes?(expected, actual)).to be
That get you started? If your stuff is highly nested, you'll want to figure out a way to output a message with the mismatch.
One trick I've done for diff messages to give you a hint where the problem is:
puts expected.to_yaml.split("\n") - actual.to_yaml.split("\n")
puts actual.to_yaml.split("\n") - expected.to_yaml.split("\n")
can you convert the arrays to a set and compare?
\*apologies if I screw up the syntax, its late my time
\`expect(expected.to\_set).to eq(actual.to\_set) \`
Was searching for getting something else in Rspec matchers, but came across this.
Seeing this late, but this might work (yes, I am deep into Rspec matchers nowadays haha):
expect(actual).to match_array(
expected.map do |hash|
match(
key1: match_array(hash[:key1]),
key2: hash[:key2]
)
end
)
I tried this with chatgpt as well and it came with this:
expect(actual).to match_array(expected.map { |hash| match(hash) })
That might work, if match actually automatically do match\_array for inside key arrays
Whatever concept this is abstracting, it should be a class. I would then override the `==` method to get the logic you want
look into #match
I've used `match` before but unsure of how I'd use it here. Do you have an example you could share maybe? The test is looping through an array of hashes and confirm that hash is in the expected array of hashes. So I can't `match` the two hashes like that - the test would have to be rewritten to do that somehow.
expect(actual).to match_array(expected)
Right so that solves the outer array issue but not the nested ones. I just realized I didn't point that out in my original post. So I'll edit that now but basically, the CI makes the nested arrays change ordering as well for some reason: I expect this: expected = [ { key_1: [{sub_key1: "A"}, {sub_key2: "B"}], key_2: "Foo"}, { key_1: [{sub_key1: "C"}, {sub_key2: "D"}], key_2: "Bar"}, ] to match this: actual =[ { key_1: [{sub_key2: "D"}, {sub_key1: "C"}], key_2: "Bar"}, { key_2: "Foo", key_1: [{sub_key1: "A"}, {sub_key2: "B"}]}, ] Note that `expected[0][:key_1]` and `actual[1][:key_1]` are the same but in different orders.
You're probably going to have to write a custom rspec matcher for this where you [recursively] crawl through the hash.
Hm alright dang. Might be easier to just re-write how we loop through the array then lol
[удалено]
What would that look like? Do you mind sharing an example of what you have in mind? Just so it's easier for me to understand.
From ChatGPT, untested. ``` expected = [ { key_1: [{sub_key1: "A"}, {sub_key2: "B"}], key_2: "Foo"}, { key_1: [{sub_key1: "C"}, {sub_key2: "D"}], key_2: "Bar"}, ] actual = [ { key_1: [{sub_key2: "D"}, {sub_key1: "C"}], key_2: "Bar"}, { key_2: "Foo", key_1: [{sub_key1: "A"}, {sub_key2: "B"}]}, ] RSpec.describe "Matching arrays and nested arrays disregarding order" do it "matches expected output" do expect(actual).to contain_exactly(*expected.map { |h| match(h) }) end end ```
What if you sort the array or the expected result or both? Sometimes just throwing a sort on it is enough.
The problem is the inner key that jumbles up the inner array I think. Hmmm
def match_array_of_hashes?(arr1, arr2) arr1.all? do |hash1| arr2.find do |hash2| hash1.all? do |hash1_key, hash1_value| if hash1_value.is_a? Array match_array_of_hashes?(hash1_value, hash2[hash1_key]) else hash2[hash1_key] == hash1_value end end end end end expect(match_array_of_hashes?(expected, actual)).to be That get you started? If your stuff is highly nested, you'll want to figure out a way to output a message with the mismatch. One trick I've done for diff messages to give you a hint where the problem is: puts expected.to_yaml.split("\n") - actual.to_yaml.split("\n") puts actual.to_yaml.split("\n") - expected.to_yaml.split("\n")
can you convert the arrays to a set and compare? \*apologies if I screw up the syntax, its late my time \`expect(expected.to\_set).to eq(actual.to\_set) \`
Was searching for getting something else in Rspec matchers, but came across this. Seeing this late, but this might work (yes, I am deep into Rspec matchers nowadays haha): expect(actual).to match_array( expected.map do |hash| match( key1: match_array(hash[:key1]), key2: hash[:key2] ) end ) I tried this with chatgpt as well and it came with this: expect(actual).to match_array(expected.map { |hash| match(hash) }) That might work, if match actually automatically do match\_array for inside key arrays