Jack,

I'd like a sneak peak into `subscription_cancelled_at`'s code.
Some lossy conversions may happen behind the scenes. See
https://github.com/rails/rails/issues/38831#issuecomment-606146664

I'd definitely not rely on micro- and milli-second precision in expectations.
To my best memory Rails opted to round to seconds in their
ActiveJob-related test helpers.

With RSpec, I'd suggest using be_within(1.second).of(future_date)

- Phil

On Thu, Feb 25, 2021 at 9:58 PM Jack Royal-Gordon <[email protected]> wrote:
>
> I have the following examples:
>
>   describe "#subscription_cancelled_at" do
>     let!(:user) { FactoryBot.create(:user, stripe_id: 'stripe') }
>     let!(:stripe_customer) { Stripe::Customer.new }
>     let!(:past_date) { 2.weeks.ago }
>     let!(:future_date) { 2.weeks.from_now }
>     let!(:subscription) { build_deep_struct(status: 'active', 
> cancel_at_period_end: false, canceled_at: nil, current_period_end: 
> future_date) }
>
>     it 'returns nil if there is no subscription' do
>       allow(user).to receive(:stripe_customer).and_return(nil)
>       expect(user).to receive(:stripe_customer)
>       expect(stripe_customer).to_not receive(:subscriptions)
>       expect(user.subscription_cancelled_at).to be_nil
>     end
>
>     it "returns canceled_at if it is populated" do
>       subscription.canceled_at = past_date
>       allow(user).to receive(:stripe_customer).and_return(stripe_customer)
>       allow(stripe_customer).to 
> receive(:subscriptions).and_return([subscription])
>       expect(user).to receive(:stripe_customer)
>       expect(stripe_customer).to receive(:subscriptions)
>       expect(user.subscription_cancelled_at.utc).to eq past_date
>     end
>
>     it "returns current_period_end if subscription will cancel at period end" 
> do
>       subscription.cancel_at_period_end = true
>       allow(user).to receive(:stripe_customer).and_return(stripe_customer)
>       allow(stripe_customer).to 
> receive(:subscriptions).and_return([subscription])
>       expect(user).to receive(:stripe_customer)
>       expect(stripe_customer).to receive(:subscriptions)
>       expect(user.subscription_cancelled_at).to eq future_date
>     end
>
>     it 'returns false otherwise' do
>       allow(user).to receive(:stripe_customer).and_return(stripe_customer)
>       allow(stripe_customer).to 
> receive(:subscriptions).and_return([subscription])
>       expect(user).to receive(:stripe_customer)
>       expect(stripe_customer).to receive(:subscriptions)
>       expect(user.subscription_cancelled_at).to be_nil
>     end
>   end
>
>
> All that’s really going on here is that I’m passing the dates through some 
> data structures and eventually returning the expected dates. There is no date 
> math (or conversion) involved behind the scenes. However, I get these results:
>
>   1) User::StripeCustomer#subscription_cancelled_at returns canceled_at if it 
> is populated
>      Failure/Error: expect(user.subscription_cancelled_at.utc).to eq 
> @@past_date
>
>
>
>        expected: 2021-02-11 18:48:06.455547000 +0000
>             got: 2021-02-11 18:48:06.455546855 +0000
>
>
>
>        (compared using ==)
>
>
>
>        Diff:
>        @@ -1 +1 @@
>        -Thu, 11 Feb 2021 18:48:06 UTC +00:00
>        +2021-02-11 18:48:06 UTC
>
>
>
>      # ./spec/models/user/stripe_customer_spec.rb:312:in `block (3 levels) in 
> <top (required)>'
>
>   2) User::StripeCustomer#subscription_cancelled_at returns 
> current_period_end if subscription will cancel at period end
>      Failure/Error: expect(user.subscription_cancelled_at).to eq @@future_date
>
>
>
>        expected: 2021-03-11 18:48:06.455753000 +0000
>             got: 2021-03-11 10:48:06.455752849 -0800
>
>
>
>        (compared using ==)
>
>
>
>        Diff:
>        @@ -1 +1 @@
>        -Thu, 11 Mar 2021 18:48:06 UTC +00:00
>        +2021-03-11 10:48:06 -0800
>
>
>
>      # ./spec/models/user/stripe_customer_spec.rb:321:in `block (3 levels) in 
> <top (required)>'
>
>
> Notice that the times being compared are off by very small amounts (< 1 sec). 
> I tried replacing the “let!” commands with assignments to class variables 
> (@@past_date, etc) in an attempt to ensure that the let! blocks were not 
> being re-evaluated each time they were referenced, but that was not the case.
>
> I can certainly change the test to check for a time “close” to the expected 
> time, but that is a hack. Can anyone explain why I’m getting these 
> differences?
>
> --
> You received this message because you are subscribed to the Google Groups 
> "rspec" group.
> To unsubscribe from this group and stop receiving emails from it, send an 
> email to [email protected].
> To view this discussion on the web visit 
> https://groups.google.com/d/msgid/rspec/E9584261-2BFC-49BB-AC53-21991545F39F%40pobox.com.

-- 
You received this message because you are subscribed to the Google Groups 
"rspec" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/rspec/CAAk5Ok-68sKasxG3O6jwG4FisKVC3Sfa9w_WRx5PYeQLxJjRgw%40mail.gmail.com.

Reply via email to