Testing a web API using RSpec and VCR - ruby

I'm writing an API wrapper as a gem, and I want to test API responses using RSpec.
The problem with this is that all API requests are made using GET, and contain an API key in the url:
e.g. game/metadata/{api_key}
This presents problems for testing, as I don't want to keep the API key in the git repository history. Is there any way I can do these spec tests, preferably with RSpec/VCR, and not store the API key in version control?
I've tried using environment variables, but VCR still stores the entire request, not just the response body.

VCR has a configuration option specifically for cases like these:
VCR.configure do |c|
c.filter_sensitive_data("<API_KEY>") { MyAPIClient.api_key }
end
See https://www.relishapp.com/myronmarston/vcr/docs/configuration/filter-sensitive-data for a larger example.

Related

How to mock OAuth2 authentication flow in RSpec?

I am quite new to using RSpec but would like to start testing the (thus far, quite basic) API that I have created, but I am absolutely stumped as to how I can go about mocking the authorization flow of OAuth2, using the oauth and quickbooks-ruby gems. I have researched into this quite extensively today, and am coming up empty handed on any results. Any resources or suggestions would be hugely appreciated.
I am unsure how to even begin approaching actually writing tests, so I don't have any RSpec stuff written yet, but below is shown the two endpoints that I would like to somehow mock, to give an idea of my aim.
get '/callback' do
redirect_uri = "http://localhost:4567/callback"
resp = qbo_client.auth_code.get_token(params[:code], redirect_uri: redirect_uri)
redirect to("/")
end
get '/auth' do
redirect_uri = 'http://localhost:4567/callback'
code_url = qbo_client.auth_code.authorize_url(redirect_uri: redirect_uri, response_type: "code", state: SecureRandom.hex(12), scope: "com.intuit.quickbooks.accounting")
redirect code_url
end
Basically, for a user to authenticate, they hit the /auth endpoint which redirects to Quickbooks for OAuth authorization, this sends the authorization code to the callback endpoint which is then traded for an access token.
I am unsure how to simulate obtaining and exchanging the authorization code, primarily. My best guess at this point is to use a fixture representing the auth-code, mock the exchange with webmock or some comparable tool, but I am very unsure if this is the right approach.
To test the OAuth2 flow in your API, you will need to simulate the responses from the authorization server and ensure that your code handles them correctly. One way to do this is by using a library like VCR or WebMock to record and replay HTTP interactions between your API and the authorization server.
Here is an example of how you could use VCR to record and replay requests to the Quickbooks API:
Install VCR gem() and configure VCR in your spec_helper.rb file:
require 'vcr'
VCR.configure do |config|
config.cassette_library_dir = 'spec/vcr_cassettes'
config.hook_into :webmock
end
RSpec.configure do |config|
config.around(:each) do |example|
VCR.use_cassette("#{example.full_description.parameterize.underscore}") do
example.run
end
end
end
Use the VCR.use_cassette block to wrap your API requests in your test:
describe 'GET /auth' do
it 'redirects to Quickbooks for OAuth authorization' do
VCR.use_cassette('quickbooks_oauth_authorize') do
get '/auth'
expect(last_response).to be_redirect
end
end
end
describe 'GET /callback' do
it 'trades the authorization code for an access token' do
VCR.use_cassette('quickbooks_oauth_token') do
get '/callback', code: '123456'
expect(last_response).to be_redirect
end
end
end
When you run your tests, VCR will record the HTTP interactions and save them to a YAML file in the spec/vcr_cassettes directory. On subsequent test runs, VCR will replay the interactions from the cassette file instead of making real HTTP requests to the authorization server. This allows you to test the OAuth2 flow in a predictable and repeatable way.
In the example above, I used quickbooks_oauth_authorize and quickbooks_oauth_token as the names of the cassette files, but you can use any name that makes sense for your test. You can also pass additional options to the VCR.use_cassette block to customize how VCR records and replays the interactions, such as record: :new_episodes to append new interactions to an existing cassette file.
I hope this helps you get started with testing the OAuth2 flow in your API using RSpec and VCR. Good luck!

How to use REST API with FaunaDB?

I have created a collection in my Fauna database. I also made an index that returns all the data in that collection. I want to know if there is a way to get JSON REST API to work with this data. What I mean by this is I want a URL that I can 'GET' using XMLHttpRequest and then parse into JSON.
You might say that Fauna is "HTTP native". All of the language drivers (JS, C#, Python, etc.) are built on top of http requests. That is, there are no special connections or connection-pools to maintain. You can get pretty far with using the JS driver in the browser, for example, without using a server.
But to answer your question more directly, there are many ways to serve a REST API, and it is going to depend on how you want to serve the API.
Examples
AWS
Here is a blog post on how to set up a REST API with AWS App Runner, for example.
https://fauna.com/blog/deploying-a-rest-api-with-aws-app-runner-and-fauna
Vercel and Netlify
There are also some example apps on github that demonstrate using a REST API with
Vercel:
https://github.com/vercel/next.js/tree/canary/examples/with-cookie-auth-fauna
Or Netlify:
https://github.com/netlify/netlify-faunadb-example
Both of which host serverless functions for you to create a REST API.

How can I stub a chain of calls to an AWS client object using AWS SDK V2 tests?

I am upgrading our implementation of AWS to V2. I would like to create an AWS client object in my tests, whose web requests are stubbed. The problem I have is getting this test client to correspond to the real client, such that I can test methods that may be called on the client in the code.
My test suite is RSpec. To give you an illustration of the problem:
aws_client = Aws::DynamoDB::Client.new(stub_responses: true)
is its own object. If created in the test, it won't correspond to the client in the code as an instance_double would:
let(:client) { instance_double(Aws::DynamoDB::Client) }
before do
allow(Aws::DynamoDB::Client).to receive(:new).and_return(client)
allow(client).to receive(<some_method>).with(<some parameters>)...
end
You can see that "client" is being used to test whether the code is communicating with the API in the desired way. The test depends on whether the code uses the correct methods with the correct parameters.
How can I get an object like aws_client (as opposed to an instance double) to correspond to client so there are no unauthorized calls to the API, and so I can test the methods that are called on the client in the code?
When I tried to globally or partially stub the AWS config responses in the spec_helper or the test file (Aws.config[:stub_responses] = true), I still see unauthorized API requests.
You may look at https://relishapp.com/rspec/rspec-mocks/docs/working-with-legacy-code/message-chains
(receive_message_chain)
allow(double).to receive_message_chain(:foo, :bar).and_return(:baz)

Mocking local api in cucumber tests

I am writing an app that access a local that lives on a separate path on my own server via ajax requests. However, I want to test the app with cucumber and mock out the backend. Is there something like artiface or sham_rack that would let me do this?
I'd recommend using VCR:
http://relishapp.com/myronmarston/vcr
It allows you to record the requests to the external service once, and then play back the recorded responses when running your tests.
I use MockJson to simulate the response:
MockJson website
How about something like http://fakeweb.rubyforge.org/?

Using the Google Custom Search API with Ruby google-api-client

As part of a people search project I'm currently participating in, I need to write a ruby script that can send search queries to the Google Custom Search API and store the search results for processing. I found the Ruby google-api-client gem (http://code.google.com/p/google-api-ruby-client/) and installed it, but, despite having thoroughly read the documentation, I am at a loss as to how to execute a Custom Search API call. This is my first attempt at using Google APIs and I'm finding the process a bit overwhelming, is there anyone out there with any experience that could provide some sample code for me to study? Thanks
While I haven't tested this, something like this should work:
require 'google/api_client'
# Creates an instance of the client.
client = Google::APIClient.new
# Authorization setup goes here.
# Fetch the discovery document and obtain a reference to the API we care about.
search = client.discovered_api('customsearch')
# Make an API call using a reference to a discovered method.
response = client.execute(
search.cse.list, 'q' => 'your query'
)
status, headers, body = response
Note that I've omitted all the setup code for authentication, which you can find in the docs for the Ruby client.
There's a few ins and outs with authentication when using an api key as opposed to OAuth thats outlined at the code abode.
You have to explicitly set the authorzation param to nil when constructing the client, otherwise the gem tries to use OAuth to authenticate, so if calling from a server using an api key only, you will always get a 401 Unauthorized. Full Code using the customsearch api is given (copy paste into irb). the code abode - google-api-client for ruby
https://developers.google.com/google-apps/calendar/firstapp
This walks you through getting setup to access the api and setting up keys in google's api console.
It has a tab for ruby - so this is what you need to get started.

Resources