5

I have a rails 4 application using devise / omniauth to allow login via facebook. The application seems to work, and the tests seem to work too. However I have one test which checks for the situation where the user goes to login via facebook, but decides not to grant permission.

This test works correctly but sends an error message into the rspec output

$ rspec -fd --tag inspect 
Sign in with facebook
  new user
E, [2013-10-20T21:25:24.232573 #17137] ERROR -- omniauth: (facebook) Authentication failure! invalid_credentials encountered
    does not grant permission

Finished in 0.21152 seconds
1 example, 0 failures

Randomised with seed 52495

or

$ rspec 
....E, [2013-10-20T21:25:24.232573 #17137] ERROR -- omniauth: (facebook) Authentication failure! invalid_credentials encountered.
............................................................

Finished in 0.95531 seconds
74 examples, 0 failures

Randomized with seed 2946

Relevant test

require 'spec_helper.rb'

feature "sign in with facebook" do
  context "new user" do
    scenario "does not grant permission", inspect: true do
      dont_sign_in_with_facebook
      expect(notice_area).to have_content "Could not authenticate you from Facebook because \"Invalid credentials\""
    end
  end
end

and the authentication_helper

module Features
  module AuthenticationHelpers
    def dont_sign_in_with_facebook
      OmniAuth.config.test_mode = true
      OmniAuth.config.mock_auth[:facebook] = :invalid_credentials
      visit "/users/auth/facebook"
    end
  end
end

Is there something I can do to suppress the error message from the rspec output ?

Edit

I tried implementing the silence function described by @Shepmaster and that did not solve the issue. Then tried redirecting errors from the rspec command:

rspec -fd --tag inspect  2> /dev/null
Sign in with facebook
  new user
E, [2013-10-20T21:25:24.232573 #17137] ERROR -- omniauth: (facebook) Authentication failure! invalid_credentials encounterd
    does not grant permission

Finished in 0.21152 seconds
1 example, 0 failures

Randomised with seed 65190

and redirecting stdout

rspec -fd --tag inspect  > /dev/null

no output!

and finally using the output option

rspec -fd --tag inspect -o /tmp/rspec.out 2> /dev/null
cat /tmp/rspec.out 

Sign in with facebook
  new user
    does not grant permission

Finished in 0.21152 seconds
1 example, 0 failures

Randomised with seed 65190

ANSWER using the answer from @shepmaster

module Features
  module AuthenticationHelpers
    def dont_sign_in_with_facebook
      OmniAuth.config.test_mode = true
      OmniAuth.config.mock_auth[:facebook] = :invalid_credentials
      silence_omniauth {visit "/users/auth/facebook"}
    end
  end
end
Ian Kenney
  • 6,376
  • 1
  • 25
  • 44
  • Can you find the code that prints that error? I would start with a `git grep` of your source code. If it's not there, then I would search in your gems (`~/.rvm/gems` if you use rvm), and if it's not there, it must be coming from somewhere like another file or the network. Track down the source of this log and we can figure out how to disable it. – Shepmaster Oct 27 '13 at 17:47

2 Answers2

13

I had the same issue in a Rails 4.2 app. The fix was to set the OmniAuth logger to the Rails logger in an initializer per the README:

# config/initializers/omniauth.rb
OmniAuth.config.logger = Rails.logger
Abe Voelker
  • 30,124
  • 14
  • 81
  • 98
  • 6
    This should be the accepted answer - does exactly what the OP without a bunch of convoluted test setup. Plus setting the logger properly helps when debugging issues in development and production since errors actually end up in the logs and not in STDOUT or STDERR. – max Mar 25 '15 at 17:46
  • I tried this but solution but it seems omniauth is still logging to stdout. See my question http://stackoverflow.com/questions/32449040/puma-production-server-configuration-how-to-run-it-in-background – Junchao Gu Sep 09 '15 at 02:18
6

The best bet is to find the code that is printing that error, then you can figure out if there is a precise way of silencing that error.

That error message has a unique misspelling (encountererd) that does not seem to occur (or ever have occurred) in the devise source. Perhaps it is coming from your code or another gem? A quick github search didn't have any useful results.

Added

It appears that you didn't copy-and-paste the error exactly, so I was looking for a string that never occurs! This is the source of the error. You should be able to set the OmniAuth logger to something else for the duration of the test. This is the same style as silence below:

def silence_omniauth
  previous_logger = OmniAuth.config.logger
  OmniAuth.config.logger = Logger.new("/dev/null")
  yield
ensure
  OmniAuth.config.logger = previous_logger
end

Original

If you cannot find the source of the message, then there is always the nuclear option: completely disabling printing to the standard output streams during that test. This other SO question has an example of how to do it, which I'll modify and reproduce here:

def silence
  previous_stdout, $stdout = $stdout, StringIO.new
  previous_stderr, $stderr = $stderr, StringIO.new
  yield
ensure
  # Restore the previous values of stdout and stderr
  $stdout = previous_stdout
  $stderr = previous_stderr
end

# And in your test
it 'does whatever' do
  silence { code.that_causes.the_warning }
end

To reiterate, it is much better to find a narrower solution. Silencing stdout / stderr will undoubtedly confuse someone when they go to print out debugging information during the test and see nothing. I say this as it happened to me just this last week. :-)

Community
  • 1
  • 1
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
  • Thanks for the suggestion - the silence function seems to work great if I print to stderr in a test - but does not prevent the problem I am seeing - looks like the message is being put to stdout ( question updated with details ) – Ian Kenney Oct 27 '13 at 10:58
  • The same silencing technique works for stdout as well. I've updated the answer to include that. – Shepmaster Oct 27 '13 at 13:44
  • I had already tried with your answer modified to handle stdout as well, but that did not work either - I could get see silence function worked as if i wrapped a `puts` or `$stderrr.puts` in the function I could hide the output, however this did not hide the output from the running my existing test. Thanks again for your help though. – Ian Kenney Oct 27 '13 at 15:30
  • I've added a version that is specific to OmniAuth, perhaps that will narrow it down more. – Shepmaster Oct 27 '13 at 18:05
  • That did the trick, many thanks - not sure what happened with copying the error message – Ian Kenney Oct 28 '13 at 08:19