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