Skip to content

Conversation

@deivid-rodriguez
Copy link
Contributor

What? Why?

This is a pretty deep rabbit hole.

It all started trying to fix the RSpec warnings that show up when running bundle exec rspec spec/lib/stripe/payment_intent_validator_spec.rb:

(...)

Stripe::PaymentIntentValidator
  #call
    as a guest
      when payment intent is valid
        valid non-3D credit cards are correctly handled
          behaves like payments intents
            from Visa
WARNING: Using `expect { }.not_to raise_error(SpecificErrorClass)` risks false positives, since literally any other error would cause the expectation to pass, including those raised by Ruby (e.g. `NoMethodError`, `NameError` and `ArgumentError`), meaning the code you are intending to test may not even get reached. Instead consider using `expect { }.not_to raise_error` or `expect { }.to raise_error(DifferentSpecificErrorClass)`. This message can be suppressed by setting: `RSpec::Expectations.configuration.on_potential_false_positives = :nothing`. Called from /Users/deivid/code/openfoodfoundation/openfoodnetwork/spec/lib/stripe/payment_intent_validator_spec.rb:53:in `block (7 levels) in <main>'.
              returns payment intent id and does not raise
              captures the payment
          behaves like payments intents
            from Visa (debit)
WARNING: Using `expect { }.not_to raise_error(SpecificErrorClass)` risks false positives, since literally any other error would cause the expectation to pass, including those raised by Ruby (e.g. `NoMethodError`, `NameError` and `ArgumentError`), meaning the code you are intending to test may not even get reached. Instead consider using `expect { }.not_to raise_error` or `expect { }.to raise_error(DifferentSpecificErrorClass)`. This message can be suppressed by setting: `RSpec::Expectations.configuration.on_potential_false_positives = :nothing`. Called from /Users/deivid/code/openfoodfoundation/openfoodnetwork/spec/lib/stripe/payment_intent_validator_spec.rb:53:in `block (7 levels) in <main>'.
              returns payment intent id and does not raise
              captures the payment
          behaves like payments intents
            from Mastercard
WARNING: Using `expect { }.not_to raise_error(SpecificErrorClass)` risks false positives, since literally any other error would cause the expectation to pass, including those raised by Ruby (e.g. `NoMethodError`, `NameError` and `ArgumentError`), meaning the code you are intending to test may not even get reached. Instead consider using `expect { }.not_to raise_error` or `expect { }.to raise_error(DifferentSpecificErrorClass)`. This message can be suppressed by setting: `RSpec::Expectations.configuration.on_potential_false_positives = :nothing`. Called from /Users/deivid/code/openfoodfoundation/openfoodnetwork/spec/lib/stripe/payment_intent_validator_spec.rb:53:in `block (7 levels) in <main>'.
              returns payment intent id and does not raise
(...)

The warning makes a lot of sense and I think the best solution is to completely remove the not_to raise_error(SpecificErrorClass) expectation: if an error happens, the spec should always fail.

Removing those expectations surfaced that the spec was failing a the very beginning when setup up the DB objects needed for it, so the expectations were not even running.

This PR fixes the successive errors I run into until getting the specs back to green without warnings. The different fixes are explained in the different commit messages.

What should we test?

I'd like a second opinion that the specs rewritten to not use raw credit card data still test what they are supposed to test.

Release notes

  • Technical changes only

@github-project-automation github-project-automation bot moved this to All the things 💤 in OFN Delivery board Oct 22, 2025
@sigmundpetersen sigmundpetersen moved this from All the things 💤 to Code review 🔎 in OFN Delivery board Oct 22, 2025
Copy link
Contributor

@filipefurtad0 filipefurtad0 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome work.
Thank you for fixing this @deivid-rodriguez 👏 👏 👏

@deivid-rodriguez
Copy link
Contributor Author

No problem @filipefurtad0 😄

Currently the commit history for this PR is a bit verbose because in each commit I was trying to highlight the successive errors I was getting. It has the gotcha that not every commit passes tests, which could affect bisecting the code base if ever needed, for example. I'm happy to squash commits a bit so that all of them pass tests if needed.

Also, the failing "linters" job is getting addressed through other reviewdog related PRs that I have opened 👍.

@filipefurtad0
Copy link
Contributor

filipefurtad0 commented Oct 23, 2025

commit history for this PR is a bit verbose because in each commit I was trying to highlight the successive errors I was getting

I find that's totally justified and helpful here, it makes it clearer to review, so no need to squash on my side - but let's see what others think :-)

@dacook dacook self-requested a review October 27, 2025 01:00
Copy link
Member

@dacook dacook left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work, thank you for going down into the rabbit hole. The result is better specs, hooray! 🎉
I just have a couple of suggestions to rename a variable and add a comment.

@github-project-automation github-project-automation bot moved this from Code review 🔎 to In Progress ⚙ in OFN Delivery board Oct 27, 2025
deivid-rodriguez and others added 6 commits October 27, 2025 09:08
They're always passing because an error (different from `StripeError`),
is actually making them pass.
Currently RSpec warns these specs like this:

```
WARNING: Using `expect { }.not_to raise_error(SpecificErrorClass)` risks false positives, since literally any other error would cause the
expectation to pass, including those raised by Ruby (e.g. `NoMethodError`, `NameError` and `ArgumentError`), meaning the code you are intending
to test may not even get reached. Instead consider using `expect { }.not_to raise_error` or `expect { }.to raise_error(DifferentSpecificErrorClass)`.
This message can be suppressed by setting: `RSpec::Expectations.configuration.on_potential_false_positives = :nothing`.
Called from /path/to/spec/lib/stripe/payment_intent_validator_spec.rb:53:in `block (7 levels) in <main>'.
```

The warnings are super accurate in this particular case: the inner
assertion is not actually getting reached due to a previous unrelated
error.

Since there's an inner assertion already, I think it's best to
completely remove to `raise_error` negative block, since it just hides
errors and buys us nothing.

By removing it, the underlying error surfaces:

```
  1) Stripe::PaymentIntentValidator#call as a guest when payment intent is valid valid non-3D credit cards are correctly handled behaves like payments intents from Visa returns payment intent id and does not raise
     Failure/Error:
       create(:payment, amount: payment_intent.amount, payment_method:,
                        response_code: payment_intent.id, source: pm_card)

     NoMethodError:
       undefined method `has_query_constraints?' for Stripe::PaymentMethod:Class

               elsif (klass || self.klass).has_query_constraints? || options[:query_constraints]
                                          ^^^^^^^^^^^^^^^^^^^^^^^
     Shared Example Group: "payments intents" called from ./spec/lib/stripe/payment_intent_validator_spec.rb:75
     # ./spec/lib/stripe/payment_intent_validator_spec.rb:16:in `block (3 levels) in <main>'
     # ./spec/lib/stripe/payment_intent_validator_spec.rb:19:in `block (3 levels) in <main>'
     # ./spec/lib/stripe/payment_intent_validator_spec.rb:53:in `block (7 levels) in <main>'
     # ./spec/base_spec_helper.rb:208:in `block (2 levels) in <main>'
     # ./spec/base_spec_helper.rb:155:in `block (3 levels) in <main>'
     # ./spec/base_spec_helper.rb:155:in `block (2 levels) in <main>'
     # -e:1:in `<main>'
```
Previous error is fixed, which allows the spec to proceed further, and
reveals that the current cassettes are missing some requests:

```
  1) Stripe::PaymentIntentValidator#call as a guest when payment intent is valid valid non-3D credit cards are correctly handled behaves like payments intents from Visa returns payment intent id and does not raise
     Failure/Error:
       payment_intent_response = Stripe::PaymentIntent.retrieve(
         payment_intent_id,
         stripe_account: stripe_account_id
       )

     VCR::Errors::UnhandledHTTPRequestError:

       ================================================================================
       An HTTP request has been made that VCR does not know how to handle:
         GET https://api.stripe.com/v1/payment_intents/pi_3P8hNGKuuB1fWySn0dvhu9lG

       VCR is currently using the following cassette:

       (...)
```
If I regenerate the VCR cassetes for
spec/lib/stripe/payment_intent_validator_spec.rb, I get a lot of errors
like this:

```
Stripe::CardError:

Sending credit card numbers directly to the Stripe API is generally
unsafe. We suggest you use test tokens that map to the test card you are
using, see https://stripe.com/docs/testing. To enable testing raw card
data APIs, see
https://support.stripe.com/questions/enabling-access-to-raw-card-data-apis.
```

It seems the sandbox environment associated to my developer API keys is
not allowed to send raw credit card data.

Instead of requesting Stripe support to enable that, or regenerate
cassettes with the API keys in Bitwarden, I figured we could migrate the
tests to not use raw credit card data.
And comment a bit on them.

Co-authored-by: David Cook <david@openfoodnetwork.org.au>
And also remove a couple of now unused `let`'s that were already using
this terminology.

Co-authored-by: David Cook <david@openfoodnetwork.org.au>
Copy link
Member

@dacook dacook left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice!

@dacook dacook moved this from In Progress ⚙ to Code review 🔎 in OFN Delivery board Oct 28, 2025
@dacook
Copy link
Member

dacook commented Oct 28, 2025

As this relates to payments, I'll await one more team member's review

@deivid-rodriguez
Copy link
Contributor Author

Thank you @dacook! If I could get some opinions on #13643 and #13645 and there's will to move those forward, it'd be nice to introduce them first and then rebase this one to prove that the linters check gets fixed. That said, it starts to be a pretty deep prerequisite chain, because we've already set this PR as a dependency of #13493 😅

@filipefurtad0 filipefurtad0 added the technical changes only These pull requests do not contain user facing changes and are grouped in release notes label Oct 28, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

technical changes only These pull requests do not contain user facing changes and are grouped in release notes

Projects

Status: Code review 🔎

Development

Successfully merging this pull request may close these issues.

3 participants