-
Notifications
You must be signed in to change notification settings - Fork 70
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'BIB-45-dual-boot-rails-6-1-and-7' into BIB-49-rails-7-p…
…roduction
- Loading branch information
Showing
45 changed files
with
707 additions
and
411 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,246 @@ | ||
# frozen_string_literal: true | ||
|
||
require "rails_helper" | ||
|
||
# Tests to define what this custom matcher should do | ||
# file is config/lib because if it was in support it would be required by rails_helper.rb | ||
RSpec.describe "custom match_hash_indifferently and RspecHashMatcher" do | ||
let(:options) { RspecHashMatcher::DEFAULT_OPTS } | ||
context "with two hashes" do | ||
describe "match_hash_indifferently" do | ||
let(:time) { Time.current } | ||
let(:hash_1) { {:something => 12, "else" => "party", :time => time} } | ||
let(:hash_2) { {"something" => 12.0, :else => :party, :time => time + 0.1} } | ||
|
||
it "matches indifferently" do | ||
expect(RspecHashMatcher.recursive_match_hashes_errors(hash_1, hash_2)).to eq([]) | ||
expect(hash_1).to match_hash_indifferently hash_2 | ||
end | ||
|
||
context "with hash_2 missing key" do | ||
let(:hash_2) { hash_1.except(:something) } | ||
let(:target_error) do | ||
[ | ||
{key: "keys", value: %w[else time], match_value: %w[else something time], | ||
match_with: "equal"} | ||
] | ||
end | ||
|
||
it "doesn't match" do | ||
expect(RspecHashMatcher.recursive_match_hashes_errors(hash_1, hash_2)).to eq(target_error) | ||
expect(hash_1).not_to match_hash_indifferently hash_2 | ||
end | ||
end | ||
|
||
context "with hash_1 missing key" do | ||
let(:hash_1) { hash_2.except(:else) } | ||
|
||
it "doesn't match" do | ||
expect(hash_1).not_to match_hash_indifferently hash_2 | ||
end | ||
end | ||
|
||
context "with nested hash" do | ||
let(:hash_1) { {something: {foo: "bar", bar: :foo}} } | ||
let(:hash_2) { {"something" => {bar: :foo, foo: :bar}}.as_json } | ||
|
||
it "matches" do | ||
expect(hash_1).to match_hash_indifferently hash_2 | ||
end | ||
|
||
context "with a non match" do | ||
let(:hash_2) { {"something" => {bar: :foo, foo: :bar, barfoo: :foobar}} } | ||
|
||
it "doesn't match" do | ||
expect(hash_1).not_to match_hash_indifferently hash_2 | ||
end | ||
end | ||
end | ||
|
||
context "with boolean" do | ||
let(:hash_1) { {bool: "1", bool_false: false} } | ||
let(:hash_2) { {bool: true, bool_false: ""} } | ||
|
||
it "matches" do | ||
expect(hash_1).to match_hash_indifferently hash_2 | ||
end | ||
end | ||
end | ||
|
||
context "with timezone" do | ||
let(:time) { Time.at(1657223244) } # 2022-07-07 14:47:24 | ||
let(:hash_1) { {updated_at: time.in_time_zone("Amsterdam")} } | ||
let(:hash_2) { {updated_at: time.utc.to_s, timezone: "UTC"} } | ||
it "matches" do | ||
expect(hash_1).to match_hash_indifferently(hash_2) | ||
end | ||
|
||
context "active record obj has timestamp stored" do | ||
# NOTE: This is hacky and weird, but I think it's useful to test - and this was easy to set up | ||
let(:obj) { User.new(email: "[email protected]", updated_at: time) } | ||
let(:hash) { {:email => "[email protected]", :updated_at => time.to_i, "timezone" => "UTC"} } | ||
it "matches" do | ||
expect(obj).to match_hash_indifferently hash | ||
end | ||
end | ||
end | ||
end | ||
|
||
context "with ActiveRecord model" do | ||
let(:time) { 1.hour.ago } | ||
let(:invoice) do | ||
Invoice.new(amount_due_cents: 2_000, subscription_start_at: time + 0.5) | ||
end | ||
let(:hash_1) { {amount_due_cents: "2000.0", subscription_start_at: time} } | ||
|
||
it "matches" do | ||
expect(RspecHashMatcher.send(:times_match?, invoice.subscription_start_at, | ||
hash_1[:subscription_start_at])).to be_truthy | ||
expect(invoice).to match_hash_indifferently(hash_1) | ||
end | ||
|
||
context "with non-matching" do | ||
let(:hash_2) { hash_1.merge(subscription_start_at: time + 3) } | ||
|
||
it "does not matches" do | ||
expect(invoice).not_to match_hash_indifferently(hash_2) | ||
end | ||
end | ||
end | ||
|
||
describe "validate_options!" do | ||
it "noops" do | ||
expect(RspecHashMatcher.send(:validate_options!, options)).to be_nil | ||
end | ||
context "with invalid match_number_types" do | ||
let(:options) { {coerce_values_to_json: true, match_number_types: true} } | ||
it "raises" do | ||
expect do | ||
RspecHashMatcher.send(:validate_options!, options) | ||
end.to raise_error(/invalid options/i) | ||
end | ||
end | ||
end | ||
|
||
describe "values_match?" do | ||
context "with number" do | ||
it "is truthy for matching Integer and Float" do | ||
expect(options[:match_number_types]).to be_falsey # Sanity check default options | ||
expect(RspecHashMatcher.send(:values_match?, 12, 12.0, options: options)).to be_truthy | ||
expect(RspecHashMatcher.send(:values_match?, 12.0, 12, options: options)).to be_truthy | ||
end | ||
it "is truthy for matching Float and BigDecimal" do | ||
expect(RspecHashMatcher.send(:values_match?, 12.0, BigDecimal("12"), options: options)).to be_truthy | ||
expect(RspecHashMatcher.send(:values_match?, BigDecimal("12"), 12, options: options)).to be_truthy | ||
end | ||
it "is truthy for matching Number and String" do | ||
expect(RspecHashMatcher.send(:values_match?, 12.0, "12", options: options)).to be_truthy | ||
expect(RspecHashMatcher.send(:values_match?, "12", 12.0, options: options)).to be_truthy | ||
expect(RspecHashMatcher.send(:values_match?, "12", BigDecimal("12.0"), options: options)).to be_truthy | ||
end | ||
it "is falsey if both are strings" do | ||
expect(RspecHashMatcher.send(:values_match?, "12.0", "12", options: options)).to be_falsey | ||
end | ||
context "with match_number_types: true" do | ||
let(:options) { RspecHashMatcher::DEFAULT_OPTS.merge(match_number_types: true) } | ||
it "is falsey" do | ||
expect(RspecHashMatcher.send(:values_match?, 12.0, BigDecimal("12"), options: options)).to be_truthy | ||
expect(RspecHashMatcher.send(:values_match?, 12.0, 12, options: options)).to be_truthy | ||
expect(RspecHashMatcher.send(:values_match?, 12, 12.00, options: options)).to be_truthy | ||
expect(RspecHashMatcher.send(:values_match?, 12.0, 12.00, options: options)).to be_truthy | ||
end | ||
end | ||
end | ||
context "with arrays" do | ||
it "is truthy for array with different order" do | ||
expect(options[:match_array_order]).to be_falsey # Sanity check default options | ||
expect(RspecHashMatcher.send(:values_match?, [1, 2], [2, 1], options: options)).to be_truthy | ||
expect(RspecHashMatcher.send(:values_match?, %w[a b c], %w[b a c], options: options)).to be_truthy | ||
end | ||
|
||
it "matches by strings" do | ||
expect(RspecHashMatcher.send(:values_match?, [2], ["2"], options: options)).to be_truthy | ||
expect(RspecHashMatcher.send(:values_match?, [2, "abc", 3], %w[2 abc 3], options: options)).to be_truthy | ||
end | ||
|
||
it "is falsey for different arrays" do | ||
expect(RspecHashMatcher.send(:values_match?, [], [2, 1], options: options)).to be_falsey | ||
expect(RspecHashMatcher.send(:values_match?, %w[a b c], %w[a c], options: options)).to be_falsey | ||
end | ||
|
||
context "with match_array_order" do | ||
let(:options) { RspecHashMatcher::DEFAULT_OPTS.merge(match_array_order: true) } | ||
it "matches based on array order" do | ||
expect(RspecHashMatcher.send(:values_match?, [1, 2], [2, 1], options: options)).to be_falsey | ||
expect(RspecHashMatcher.send(:values_match?, %w[a b c], %w[b a c], options: options)).to be_falsey | ||
end | ||
end | ||
end | ||
|
||
context "with times" do | ||
let(:time_1) { Time.at(1657223244) } # 2022-07-07 14:47:24 | ||
let(:time_2) { time_1.in_time_zone("Amsterdam") } # We | ||
|
||
it "is truthy for times" do | ||
expect(RspecHashMatcher.send(:values_match?, time_1, time_2, options: options)).to be_truthy | ||
expect(RspecHashMatcher.send(:values_match?, time_2, time_1, options: options)).to be_truthy | ||
end | ||
|
||
it "is truthy if a time is a timestamp" do | ||
expect(RspecHashMatcher.send(:values_match?, time_1.to_i, time_2, options: options)).to be_truthy | ||
expect(RspecHashMatcher.send(:values_match?, time_1, time_2.to_i, options: options)).to be_truthy | ||
end | ||
end | ||
|
||
context "blanks" do | ||
it "is truthy for blank vs nil" do | ||
expect(options[:match_blanks]).to be_falsey # Sanity check default options | ||
expect(RspecHashMatcher.send(:values_match?, "", nil, options: options)).to be_truthy | ||
expect(RspecHashMatcher.send(:values_match?, nil, " ", options: options)).to be_truthy | ||
expect(RspecHashMatcher.send(:values_match?, "", "\n", options: options)).to be_truthy | ||
end | ||
context "with match_blanks" do | ||
let(:options) { RspecHashMatcher::DEFAULT_OPTS.merge(match_blanks: true) } | ||
it "matches based on array order" do | ||
expect(RspecHashMatcher.send(:values_match?, "", nil, options: options)).to be_falsey | ||
end | ||
end | ||
end | ||
end | ||
|
||
describe "times_match?" do | ||
let(:time_1) { Time.at(1_718_123_393) } # 2024-06-11 16:29:53 | ||
let(:time_2) { time_1 - 0.2 } | ||
let(:round_time_1) { RspecHashMatcher.send(:round_time, time_1) } | ||
let(:round_time_2) { RspecHashMatcher.send(:round_time, time_2) } | ||
|
||
it "matches the time" do | ||
RspecHashMatcher.send(:values_match?, 12, 12.0, options: options) | ||
expect(RspecHashMatcher.send(:times_match?, time_1, time_2)).to be_truthy | ||
end | ||
|
||
context "with 1 second later" do | ||
let(:time_2) { time_1 + 1 } | ||
|
||
it "matches the time" do | ||
expect(RspecHashMatcher.send(:times_match?, time_1, time_2)).to be_truthy | ||
end | ||
end | ||
|
||
context "with 1 minute later" do | ||
let(:time_2) { time_1 + 1.minute } | ||
|
||
it "is falsey" do | ||
expect(RspecHashMatcher.send(:times_match?, time_1, time_2)).to be_falsey | ||
end | ||
|
||
context "with match_time_within 10.minutes" do | ||
it "is truthy" do | ||
result = RspecHashMatcher.send(:times_match?, time_1, time_2, | ||
match_time_within: 10.minutes) | ||
expect(result).to be_truthy | ||
end | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
# named 0_factories so it's loaded first, since it has | ||
FactoryBot.define do | ||
sequence :unique_email do |n| | ||
"user#{n}[email protected]" | ||
|
@@ -19,69 +20,6 @@ | |
"#{n}0" | ||
end | ||
|
||
factory :front_gear_type do | ||
sequence(:name) { |n| "Front Gear #{n}" } | ||
count { 1 } | ||
end | ||
|
||
factory :rear_gear_type do | ||
sequence(:name) { |n| "Rear Gear #{n}" } | ||
count { 1 } | ||
end | ||
|
||
factory :wheel_size do | ||
sequence(:name) { |n| "Wheel size #{n}" } | ||
iso_bsd { FactoryBot.generate(:unique_iso) } | ||
priority { 1 } | ||
sequence(:description) { |n| "Wheel Description #{n}" } | ||
end | ||
|
||
factory :paint do | ||
sequence(:name) { |n| "Paint #{n}" } | ||
end | ||
|
||
factory :cgroup do | ||
sequence(:name) { |n| "Cgroup #{n}" } | ||
end | ||
|
||
factory :ctype do | ||
sequence(:name) { |n| "Component type#{n}" } | ||
cgroup { FactoryBot.create(:cgroup) } | ||
end | ||
|
||
factory :component do | ||
bike { FactoryBot.create(:bike) } | ||
ctype { FactoryBot.create(:ctype) } | ||
end | ||
|
||
factory :lock_type do | ||
sequence(:name) { |n| "Lock type #{n}" } | ||
end | ||
|
||
factory :lock do | ||
user { FactoryBot.create(:user) } | ||
manufacturer { FactoryBot.create(:manufacturer) } | ||
lock_type { FactoryBot.create(:lock_type) } | ||
end | ||
|
||
factory :integration do | ||
access_token { "12345teststststs" } | ||
end | ||
|
||
factory :blog do | ||
user { FactoryBot.create(:user) } | ||
body { "Some sweet blog content that everyone loves" } | ||
sequence(:title) { |n| "Blog title #{n}" } | ||
|
||
trait :published do | ||
published { true } | ||
end | ||
|
||
trait :dutch do | ||
language { "nl" } | ||
end | ||
end | ||
|
||
# Location traits | ||
trait :in_amsterdam do | ||
latitude { 52.37403 } | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
# frozen_string_literal: true | ||
|
||
FactoryBot.define do | ||
factory :blog do | ||
user { FactoryBot.create(:user) } | ||
body { "Some sweet blog content that everyone loves" } | ||
sequence(:title) { |n| "Blog title #{n}" } | ||
|
||
trait :published do | ||
published { true } | ||
end | ||
|
||
trait :dutch do | ||
language { "nl" } | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
# frozen_string_literal: true | ||
|
||
FactoryBot.define do | ||
factory :cgroup do | ||
sequence(:name) { |n| "Cgroup #{n}" } | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
# frozen_string_literal: true | ||
|
||
FactoryBot.define do | ||
factory :component do | ||
bike { FactoryBot.create(:bike) } | ||
ctype { FactoryBot.create(:ctype) } | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
# frozen_string_literal: true | ||
|
||
FactoryBot.define do | ||
factory :ctype do | ||
sequence(:name) { |n| "Component type#{n}" } | ||
cgroup { FactoryBot.create(:cgroup) } | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
# frozen_string_literal: true | ||
|
||
FactoryBot.define do | ||
factory :front_gear_type do | ||
sequence(:name) { |n| "Front Gear #{n}" } | ||
count { 1 } | ||
end | ||
end |
Oops, something went wrong.