What is the library used to make external requests?

Hello,

from a backend controller, I need to make an HTTP GET request to an external service (KeyBase) to validate user input. What’s the library the Discourse uses to do this? I tried with Faraday, but I expect a json response and faraday_middleware is not an available gem.

Try ‘excon’ or ‘httparty’

1 Like

I was able to get Faraday to work, but the tests are failing with a very strange error, it looks like Faraday is not able to make a request in the test. Is that possible? Is there something I am expected to do to be able to make external requests in tests?

EDIT: to be more clear: the request works fine in the actual page, but not in the tests.

A great trick here that will save you tons of time is to look at existing specs (either for plugins or core)

The magic keyword you are looking for here is stub_request it is used lots of places in our spec tests, for example here:

https://github.com/discourse/discourse/blob/ecb2fd8222edf67b65c46362dc0b2361e3adf93a/spec/components/file_helper_spec.rb#L36-L48

We use https://github.com/bblimke/webmock so pretty much anything should work, if you simply need a simple HTTP get, this class has simple example of how we use FinalDestination class that wraps stuff for you.

https://github.com/discourse/discourse/blob/ecb2fd8222edf67b65c46362dc0b2361e3adf93a/lib/file_helper.rb#L39-L47

For a simple get excon may be overkill. We have been slowly winding down on our excon use in core due to strangeness with it. I would recommend avoiding faraday we don’t ever use it in core.

Regarding getting stuck with specs. A huge time saver is

bin/rake autospec

Once you run that, save you plugin.rb file and right away all the specs will run, same goes for specific controller specs.

4 Likes

Thank you :slight_smile: my struggle with this specific issue was that I couldn’t find a spec to learn from :smiley: I found stub_request and tried to use it, but I think I got into one of the strange issues with Faraday you mentioned because the spec kept failing :smiley:

One question: so I should keep bin/rake autospec running while I am working on the plug-in and it will automatically pick the changes and run the tests again?

Thanks for unblocking me :slight_smile:

1 Like

Yes, there is also a fantastic trick I use I highly recommend.

Say I am working on something_spec.rb in the plugin I will edit in:

it "I am working on this spec" do
   boom
end

Then I save it … and I am well focused on the broken specs. Then I improve the spec, leaving the “boom” at the end so autospec stays focused, saving other files and the spec file as I go. autospec stays focused and keeps running as needed.

4 Likes

It looks like bin/rake autospec is not checking plugin tests for me. If I use LOAD_PLUGINS=1 bin/rake autospec, then a ton of tests start failing (probably the ones related to other plugins).

I tried running bin/rake db:migrate to create the tables that the plugins need, but to no avail. Many tests keep failing…

EDIT: Ok, here’s the trick:

RAILS_ENV=test bin/rake db:migrate
LOAD_PLUGINS=1 bin/rake autospec

Running autospec right now, it should work as expected after the first run…

(Tagging @sam :smiley:)

So, I am running LOAD_PLUGINS=1 bin/rake autospec, but other specs fail, so my spec file is never picked. Is it normal that the first time it runs it takes more than 10 minutes?

This is the output:

Failures:

  1) UsersController#perform_account_activation valid token welcome message enqueues a welcome message if the user object indicates so
     Failure/Error: expect(Jobs::SendSystemMessage.jobs.size).to eq(1)

       expected: 1
            got: 0

       (compared using ==)
     # ./spec/requests/users_controller_spec.rb:34:in `block (5 levels) in <main>'

  2) User.enqueue_welcome_message enqueues the system message
     Failure/Error: Jobs.expects(:enqueue).with(:send_system_message, user_id: user.id, message_type: 'welcome_user')

     Mocha::ExpectationError:
       not all expectations were satisfied
       unsatisfied expectations:
       - expected exactly once, not yet invoked: Jobs.enqueue(:send_system_message, {:user_id => 3883, :message_type => "welcome_user"})
     # ./spec/models/user_spec.rb:152:in `block (3 levels) in <main>'

In total, 8 specs are failing (in addition to mine)…

EDIT: an update. bin/rake autospec (without LOAD_PLUGINS=1) fails too, with 4 failures instead of 8.

You should not need to add LOAD_PLUGINS=1 we handle this automatically here:

All you need to do is save a spec file (or plugin.rb) in your plugin directory.

Maybe somehow your test db is off?

Try creating it from scratch:

RAILS_ENV=test bin/rake db:drop
RAILS_ENV=test bin/rake db:create
RAILS_ENV=test bin/rake db:migrate
1 Like

I had already tried to recreate the database several times, to no avail.

Maybe the problem is that I am symlinking my plugin directory inside plugins/? But this is what the plugins guide tells me to do so I doubt…

Anyway, the only command that works for me so far to run tests is: bin/rake 'plugin:spec[keybase-proofs]'

Everything else fails :frowning:

1 Like

@daniel something here sounds off, can you help debug? The repo @emanuele is using is on GitHub

3 Likes

@sam, @daniel, it turns out that autospec doesn’t work with symlinked directories in plugins/, so I just checked out my repo directly in plugins/ instead of symlinking it.

Now it looks like it works fine :slight_smile: :partying_face:

3 Likes

I fixed something around symilinks a while back, can you have a look at the code? Maybe my fix is Linux only?

1 Like

Sure, I’ll give it a look :slight_smile:

I remember that the FS watching abstractions that macOS uses are quite different from the Linux ones, so I wouldn’t be surprised if that was the case.

2 Likes