Today I Learned

Joining multiple change expectations in rspec

To look for multiple changes on multiple objects, we could aggregate those changes and verify them en-masse, i.e.

expect { SyncReservations.call }.to \
  change { [property_1, property_2].map{ |p| p.reload.synced_at }.
    to([Time.new(2018, 1, 1, 16, 35), Time.new(2018, 1, 1, 16, 35)])

This will pick partial changes though (if only one value changes), so it is not recommended. Another way is nesting expectations, i.e.

expect {
  expect { SyncReservations.call }.to \
    change { property_1.reload.synced_at }.
      to(Time.new(2018, 1, 1, 16, 35))
}.to change { property_2.reload.synced_at }.
  to(Time.new(2018, 1, 1, 16, 35))

This will work, but you will get only one failure at a time. Still it is useful for joining conflicting expectations (i.e. to with not_to). For non conflicting ones, following syntax is recommended:

# using .and
expect { SyncReservations.call }.to \
  change { property_1.reload.synced_at }.
    to(Time.new(2018, 1, 1, 16, 35)).and \
  change { property_2.reload.synced_at }.
    to(Time.new(2018, 1, 1, 16, 35))

or

# using &
expect { SyncReservations.call }.to \
  change { property_1.reload.synced_at }.
  to(Time.new(2018, 1, 1, 16, 35)) &
  change { property_2.reload.synced_at }.
  to(Time.new(2018, 1, 1, 16, 35))