Skip to content

Instantly share code, notes, and snippets.

@metade
Created June 13, 2011 07:54
Show Gist options
  • Save metade/1022439 to your computer and use it in GitHub Desktop.
Save metade/1022439 to your computer and use it in GitHub Desktop.
require 'jsonpath'
require 'pp'
# TODO: is there a cleaner way of doing this?
class Capybara::Driver::Mechanize < Capybara::Driver::RackTest
def post_body(url, body, headers = {})
if remote?(url)
process_remote_request(:post, url, body, headers)
else
register_local_request
super
end
end
def put_body(url, body, headers = {})
if remote?(url)
process_remote_request(:put, url, body, { :headers => headers })
else
register_local_request
super
end
end
end
def expand_path(path)
if path =~ /(:\w+)/
field = $1
collection_path = path[0,path.index(field)]
response = RestClient.get "#{Capybara.app_host}#{collection_path}", :content_type => :json, :accept => :json
objects = JSON.parse(response.body).values.detect { |o| o.kind_of? Array }
url_key = objects.last[field.sub(':','')]
result = path.sub(field, url_key)
elsif path =~ /(@\w+)/
result = path.gsub(/@\w+/) { |i| instance_variable_get(i) }
else
result = path
end
# result += ".#{@content_type}" if @content_type
result
end
Given /^I send and accept XML$/ do
@content_type = 'xml'
page.driver.header 'Accept', 'text/xml'
page.driver.header 'Content-Type', 'text/xml'
end
Given /^I send and accept JSON$/ do
@content_type = 'json'
page.driver.header 'Accept', 'application/json'
page.driver.header 'Content-Type', 'application/json'
end
When /^I authenticate as the user "([^\"]*)" with the password "([^\"]*)"$/ do |user, pass|
page.driver.authorize(user, pass)
end
When /^I send a GET request (?:for|to) "([^\"]*)"$/ do |path|
page.driver.get(expand_path(path), {}, { 'Accept' => 'application/json', 'Content-Type' => 'application/json' })
end
When /^I send a POST request to "([^\"]*)"$/ do |path|
page.driver.post expand_path(path)
end
When /^I send a POST request to "([^\"]*)" with the following:$/ do |path, body|
page.driver.post_body(expand_path(path), body, { 'Accept' => 'application/json', 'Content-Type' => 'application/json' })
end
When /^I send a PUT request to "([^\"]*)" with the following:$/ do |path, body|
page.driver.put_body(expand_path(path), body, { 'Accept' => 'application/json', 'Content-Type' => 'application/json' })
end
When /^I send a DELETE request to "([^\"]*)"$/ do |path|
page.driver.delete(expand_path(path), {}, :headers => { 'Accept' => 'application/json', 'Content-Type' => 'application/json' })
end
Then /^show me the response$/ do
puts page.driver.response.body
end
Then /^the response status should be "([^\"]*)"$/ do |status|
if page.respond_to? :should
page.driver.response.status.should == status.to_i
else
assert_equal status.to_i, page.driver.response.status
end
end
Then /^the response should be empty$/ do
page.driver.response.body.should be_empty
end
Then /^the JSON response should have "([^\"]*)" with the text "([^\"]*)"$/ do |json_path, text|
json = JSON.parse(page.driver.response.body)
results = JsonPath.new(json_path).on(json).to_a.map(&:to_s)
if page.respond_to? :should
results.should include(text)
else
assert results.include?(text)
end
end
Then /^the JSON response should have "([^"]*)" as nil$/ do |json_path|
json = JSON.parse(page.driver.response.body)
results = JsonPath.new(json_path).on(json).to_a
results.should == []
end
Then /^the JSON response should not have "([^\"]*)" with the text "([^\"]*)"$/ do |json_path, text|
json = JSON.parse(page.driver.response.body)
results = JsonPath.new(json_path).on(json).to_a.map(&:to_s)
if page.respond_to? :should
results.should_not include(text)
else
assert !results.include?(text)
end
end
Then /^the JSON response should have the following:/ do |table|
json = JSON.parse(page.driver.response.body)
table.rows.each do |json_path, text|
results = JsonPath.new(json_path).on(json).to_a.map(&:to_s)
if page.respond_to? :should
results.should include(text)
else
assert results.include?(text)
end
end
end
Then /^the JSON response should not have the following:/ do |table|
json = JSON.parse(page.driver.response.body)
table.rows.each do |json_path, text|
results = JsonPath.new(json_path).on(json).to_a.map(&:to_s)
if page.respond_to? :should
results.should_not include(text)
else
assert !results.include?(text)
end
end
end
Then /^the JSON response should have (\d+) "([^"]*)"$/ do |count, json_path|
json = JSON.parse(page.driver.response.body)
results = JsonPath.new(json_path).on(json)
results.first.size.should == count.to_i
end
Then /^the XML response should have "([^\"]*)" with the text "([^\"]*)"$/ do |xpath, text|
parsed_response = Nokogiri::XML(response.body)
elements = parsed_response.xpath(xpath)
if page.respond_to? :should
elements.should_not be_empty, "could not find #{xpath} in:\n#{response.body}"
elements.find { |e| e.text == text }.should_not be_nil, "found elements but could not find #{text} in:\n#{elements.inspect}"
else
assert !elements.empty?, "could not find #{xpath} in:\n#{response.body}"
assert elements.find { |e| e.text == text }, "found elements but could not find #{text} in:\n#{elements.inspect}"
end
end
require 'ostruct'
require 'rest-client'
module Music
def self.destroy_all_users
users = Music::User.all.inject({}){ |h,u| h[u.username] ||= u; h }.values
users.each do |user|
user.collections.each do |collection|
collection.clips.each do |clip|
RestClient.delete "#{Music::HOST}/collections/#{collection.to_param}/clips/#{clip.pid}", :content_type => :json, :accept => :json
end
collection.destroy
end
user.playlists.each do |playlist|
playlist.playlists_tracks.each do |track|
RestClient.delete "#{Music::HOST}/playlists/#{playlist.to_param}/tracks/#{track['id']}", :content_type => :json, :accept => :json
end
playlist.destroy
end
user.destroy
end
end
class Base < OpenStruct
def self.all
response = RestClient.get "#{Music::HOST}/#{collection_name}", :content_type => :json, :accept => :json
data = JSON.parse(response.body)
return [] unless (data.kind_of? Hash and data[collection_name])
data[collection_name].map { |u| self.new(u) }
end
def self.find(what, params={})
path = params[:from] || "/#{collection_name}/#{what}"
response = RestClient.get "#{Music::HOST}#{path}", :content_type => :json, :accept => :json
if (what == :all)
JSON.parse(response.body)[collection_name].map { |h| self.new(h) }
else
self.new JSON.parse(response.body)[element_name]
end
end
def self.create(params)
response = RestClient.post "#{Music::HOST}/users", { :user => params }.to_json, :content_type => :json, :accept => :json
self.new(JSON.parse(response)['user'])
end
def destroy
RestClient.delete "#{Music::HOST}/#{self.class.collection_name}/#{to_param}", :content_type => :json, :accept => :json
end
protected
def self.collection_name
# TODO: use Rails Inflectors
self.element_name + 's'
end
def self.element_name
self.to_s.sub('Music::', '').downcase
end
end
class User < Base
def self.find_by_name(name)
self.find(name.gsub(/\W/,'').downcase)
end
def to_param
username
end
def collections
Collection.find(:all, :from => "/users/#{to_param}/collections")
end
def playlists
Playlist.find(:all, :from => "/users/#{to_param}/playlists")
end
end
class Collection < Base
def self.create(params)
user = params.delete(:user) || User.new(:username => 'testuser')
response = RestClient.post "#{Music::HOST}/users/#{user.to_param}/collections", { :collection => params }.to_json, :content_type => :json, :accept => :json
Collection.new(JSON.parse(response)['collection'])
end
def to_param
url_key
end
def clips
Clip.find(:all, :from => "/collections/#{to_param}/clips")
end
end
class Clip < Base
def self.create(params)
collection = params.delete(:collection)
response = RestClient.post "#{Music::HOST}/collections/#{collection.to_param}/clips", { :clip => params }.to_json, :content_type => :json, :accept => :json
Clip.new(JSON.parse(response)['clip'])
end
def to_param
url_key
end
end
class Playlist < Base
def self.create(params)
user = params.delete(:user) || User.new(:username => 'testuser')
response = RestClient.post "#{Music::HOST}/users/#{user.to_param}/playlists", { :playlist => params }.to_json, :content_type => :json, :accept => :json
Playlist.new(JSON.parse(response)['playlist'])
end
def to_param
url_key
end
end
class Track < Base
def self.create(params)
playlist = params.delete(:playlist)
response = RestClient.post "#{Music::HOST}/playlists/#{playlist.to_param}/tracks", { :playlists_track => params }.to_json, :content_type => :json, :accept => :json
Track.new(JSON.parse(response)['playlists_track'])
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment