Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
My awesome RSpec hacks
## Context + metadata
shared_context 'Logged as a user', role: true do
let(:user) { |example| create :user, example.metadata[:role] }
before { login_as user }
end
scenario "Login as a client", role: :client
scenario "Login as a customer", role: :customer
scenario "Login as an admin", role: :admin
## Running chrome headless by default and chrome on demand
Capybara.register_driver :headless_chrome do |app|
capabilities = Selenium::WebDriver::Remote::Capabilities.chrome(
chromeOptions: { args: %w(headless disable-gpu window-size=1200,720) }
)
Capybara::Selenium::Driver.new app, browser: :chrome, desired_capabilities: capabilities
end
Capybara.register_driver :chrome do |app|
Capybara::Selenium::Driver.new app, browser: :chrome
end
Capybara.default_driver = ENV['CHROME'] ? :chrome : :headless_chrome
# A common quite mode
`rspec`
# A debug mode
`CHROME=1 rspec`
## API specs sugar methods
module ApiSpecHelpers
# easy response navigation
def resp_json(*keys, &block)
payload = keys.reduce(JSON.parse(response.body)) { |acc, k| acc[k] }
yield payload if block_given?
payload
end
# a universal method to test json API
def fetch(url, options = {})
params = options.fetch(:params, {})
headers = options.fetch(:headers, {})
case options.fetch(:method, :get)
when :get then get(url, params: params, headers: headers)
when :post then post(url, params: params.to_json, headers: { 'content-type' => 'application/json' }.merge(headers))
when :put then put(url, params: params.to_json, headers: { 'content-type' => 'application/json' }.merge(headers))
else
raise NotImplementedError, "fetch doesn't support #{options.fetch(:method)}"
end
end
end
config.include(ApiSpecHelpers, type: :request)
it 'fetches a resent posts' do
expect(fetch('/api/posts')).to eq(200)
resp_json('data', 0, 'categories') do |categories|
expect(categories).to include('Fun RSpec')
expect(categories).not_to include('Boring JUnit')
end
end
it 'publish a new post' do
payload = { data: { name: "A new gist post", description: "A post in a gist way. Less words, more code!" } }
expect(fetch('/api/posts', { method: 'POST', body: payload })).to eq(201)
expect(resp_json('data', 'id')).to be_present
end
## Testing a different attribute sets
RSpec.describe 'A different behaviours' do
let(:params) { {} }
let(:form) { PostForm.new(params) }
subject(:publish_post) { form.save }
it 'rejects a post by missing fields' do
expect(publish_post).to be_falsy
expect(form.errors[:name]).to eq(["can't be blank"])
end
it 'rejects a post by not accepting GDPR' do
params.merge!(name: '10 reasons why mutation is awesome', description: 'Yes, it is. But use it carefully')
expect(publish_post).to be_falsy
expect(form.errors[:base]).to include("Please accept private policy first")
expect(form.errors[:name]).to eq(["can't be blank"])
end
it 'finally published a post' do
params.merge!(name: 'Coffee is a good start of a day', description: 'Some people say...', accept_policy: true)
expect(publish_post).to be_truthy
expect(form.record).to be_persisted
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.