require 'spec_helper'
describe Rosemary::Node do
before do
WebMock.disable_net_connect!
end
let :osm do
Rosemary::Api.new
end
let :stub_changeset_lookup do
stub_request(:get, "http://www.openstreetmap.org/api/0.6/changesets?open=true&user=1234").to_return(:status => 200, :body => valid_fake_changeset, :headers => {'Content-Type' => 'application/xml'} )
end
let :stub_node_lookup do
stub_request(:get, "http://www.openstreetmap.org/api/0.6/node/123").to_return(:status => 200, :body => valid_fake_node, :headers => {'Content-Type' => 'application/xml'})
end
def valid_fake_node
node=<<-EOF
EOF
end
def valid_fake_user
user=<<-EOF
The description of your profile
de-DE
de
en-US
en
EOF
end
def valid_fake_changeset
changeset=<<-EOF
EOF
end
describe '#find:' do
let :request_url do
"http://www.openstreetmap.org/api/0.6/node/1234"
end
let :stubbed_request do
stub_request(:get, request_url)
end
it "should build a Node from API response via get_object" do
stubbed_request.to_return(:status => 200, :body => valid_fake_node, :headers => {'Content-Type' => 'application/xml'})
node = osm.find_node 1234
assert_requested :get, request_url, :times => 1
node.class.should eql Rosemary::Node
node.tags.size.should eql 3
node.tags['name'].should eql 'The rose'
node['name'].should eql 'The rose'
node.add_tags('wheelchair' => 'yes')
node['wheelchair'].should eql 'yes'
end
it "should raise a Unavailable, when api times out" do
stubbed_request.to_timeout
lambda {
node = osm.find_node(1234)
}.should raise_error(Rosemary::Unavailable)
end
it "should raise an Gone error, when a node has been deleted" do
stubbed_request.to_return(:status => 410, :body => '', :headers => {'Content-Type' => 'text/plain'})
lambda {
node = osm.find_node(1234)
}.should raise_error(Rosemary::Gone)
end
it "should raise an NotFound error, when a node cannot be found" do
stubbed_request.to_return(:status => 404, :body => '', :headers => {'Content-Type' => 'text/plain'})
lambda {
node = osm.find_node(1234)
}.should raise_error(Rosemary::NotFound)
end
end
describe 'with BasicAuthClient' do
let :osm do
Rosemary::Api.new(Rosemary::BasicAuthClient.new('a_username', 'a_password'))
end
let :stub_user_lookup do
stub_request(:get, "http://a_username:a_password@www.openstreetmap.org/api/0.6/user/details").to_return(:status => 200, :body => valid_fake_user, :headers => {'Content-Type' => 'application/xml'} )
end
describe '#create:' do
let :node do
Rosemary::Node.new
end
let :request_url do
"http://a_username:a_password@www.openstreetmap.org/api/0.6/node/create"
end
let :stubbed_request do
stub_request(:put, request_url)
end
before do
stub_changeset_lookup
stub_user_lookup
end
it "should create a new Node from given attributes" do
stubbed_request.to_return(:status => 200, :body => '123', :headers => {'Content-Type' => 'text/plain'})
node.id.should be_nil
new_id = osm.save(node)
end
it "should raise a Unavailable, when api times out" do
stubbed_request.to_timeout
lambda {
new_id = osm.save(node)
}.should raise_error(Rosemary::Unavailable)
end
it "should not create a Node with invalid xml but raise BadRequest" do
stubbed_request.to_return(:status => 400, :body => 'The given node is invalid', :headers => {'Content-Type' => 'text/plain'})
lambda {
new_id = osm.save(node)
}.should raise_error(Rosemary::BadRequest)
end
it "should not allow to create a node when a changeset has been closed" do
stubbed_request.to_return(:status => 409, :body => 'The given node is invalid', :headers => {'Content-Type' => 'text/plain'})
lambda {
new_id = osm.save(node)
}.should raise_error(Rosemary::Conflict)
end
it "should not allow to create a node when no authentication client is given" do
osm = Rosemary::Api.new
lambda {
osm.save(node)
}.should raise_error(Rosemary::CredentialsMissing)
end
end
describe '#update:' do
let :node do
osm.find_node 123
end
before do
stub_changeset_lookup
stub_user_lookup
stub_node_lookup
end
it "should save a edited node" do
stub_request(:put, "http://a_username:a_password@www.openstreetmap.org/api/0.6/node/123").to_return(:status => 200, :body => '43', :headers => {'Content-Type' => 'text/plain'})
node.tags['amenity'] = 'restaurant'
node.tags['name'] = 'Il Tramonto'
node.should_receive(:changeset=)
new_version = osm.save(node)
new_version.should eql 43
end
end
describe '#delete:' do
let :node do
osm.find_node 123
end
before do
stub_changeset_lookup
stub_user_lookup
stub_node_lookup
end
it "should not delete an node with missing id" do
node = Rosemary::Node.new
osm.destroy(node)
end
it "should delete an existing node" do
stub_request(:delete, "http://a_username:a_password@www.openstreetmap.org/api/0.6/node/123").to_return(:status => 200, :body => '43', :headers => {'Content-Type' => 'text/plain'})
node.should_receive(:changeset=)
new_version = osm.destroy(node)
new_version.should eql 43 # new version number
end
it "should raise an error if node to be deleted is still part of a way" do
stub_request(:delete, "http://a_username:a_password@www.openstreetmap.org/api/0.6/node/123").to_return(:status => 400, :body => 'Version does not match current database version', :headers => {'Content-Type' => 'text/plain'})
lambda {
response = osm.destroy(node)
response.should eql "Version does not match current database version"
}.should raise_error Rosemary::BadRequest
end
it "should raise an error if node cannot be found" do
stub_request(:delete, "http://a_username:a_password@www.openstreetmap.org/api/0.6/node/123").to_return(:status => 404, :body => 'Node cannot be found', :headers => {'Content-Type' => 'text/plain'})
lambda {
response = osm.destroy(node)
response.should eql "Node cannot be found"
}.should raise_error Rosemary::NotFound
end
it "should raise an error if there is a conflict" do
stub_request(:delete, "http://a_username:a_password@www.openstreetmap.org/api/0.6/node/123").to_return(:status => 409, :body => 'Node has been deleted in this changeset', :headers => {'Content-Type' => 'text/plain'})
lambda {
response = osm.destroy(node)
response.should eql "Node has been deleted in this changeset"
}.should raise_error Rosemary::Conflict
end
it "should raise an error if the node is already delted" do
stub_request(:delete, "http://a_username:a_password@www.openstreetmap.org/api/0.6/node/123").to_return(:status => 410, :body => 'Node has been deleted', :headers => {'Content-Type' => 'text/plain'})
lambda {
response = osm.destroy(node)
response.should eql "Node has been deleted"
}.should raise_error Rosemary::Gone
end
it "should raise an error if the node is part of a way" do
stub_request(:delete, "http://a_username:a_password@www.openstreetmap.org/api/0.6/node/123").to_return(:status => 412, :body => 'Node 123 is still used by way 456', :headers => {'Content-Type' => 'text/plain'})
lambda {
response = osm.destroy(node)
response.should eql "Node 123 is still used by way 456"
}.should raise_error Rosemary::Precondition
end
end
end
describe 'with OauthClient' do
let :consumer do
OAuth::Consumer.new( 'a_key', 'a_secret',
{
:site => 'http://www.openstreetmap.org',
:request_token_path => '/oauth/request_token',
:access_token_path => '/oauth/access_token',
:authorize_path => '/oauth/authorize'
}
)
end
let :access_token do
OAuth::AccessToken.new(consumer, 'a_token', 'a_secret')
end
let :osm do
Rosemary::Api.new(Rosemary::OauthClient.new(access_token))
end
let :stub_user_lookup do
stub_request(:get, "http://www.openstreetmap.org/api/0.6/user/details").to_return(:status => 200, :body => valid_fake_user, :headers => {'Content-Type' => 'application/xml'} )
end
describe '#create:' do
let :node do
Rosemary::Node.new
end
let :request_url do
"http://www.openstreetmap.org/api/0.6/node/create"
end
let :stubbed_request do
stub_request(:put, request_url)
end
before do
stub_changeset_lookup
stub_user_lookup
end
it "should create a new Node from given attributes" do
stubbed_request.to_return(:status => 200, :body => '123', :headers => {'Content-Type' => 'text/plain'})
node.id.should be_nil
new_id = osm.save(node)
end
it "should raise a Unavailable, when api times out" do
stubbed_request.to_timeout
lambda {
new_id = osm.save(node)
}.should raise_error(Rosemary::Unavailable)
end
it "should not create a Node with invalid xml but raise BadRequest" do
stubbed_request.to_return(:status => 400, :body => 'The given node is invalid', :headers => {'Content-Type' => 'text/plain'})
lambda {
new_id = osm.save(node)
}.should raise_error(Rosemary::BadRequest)
end
it "should not allow to create a node when a changeset has been closed" do
stubbed_request.to_return(:status => 409, :body => 'The given node is invalid', :headers => {'Content-Type' => 'text/plain'})
lambda {
new_id = osm.save(node)
}.should raise_error(Rosemary::Conflict)
end
it "should not allow to create a node when no authentication client is given" do
osm = Rosemary::Api.new
lambda {
osm.save(node)
}.should raise_error(Rosemary::CredentialsMissing)
end
end
describe '#update:' do
let :node do
osm.find_node 123
end
before do
stub_changeset_lookup
stub_user_lookup
stub_node_lookup
end
it "should save a edited node" do
stub_request(:put, "http://www.openstreetmap.org/api/0.6/node/123").to_return(:status => 200, :body => '43', :headers => {'Content-Type' => 'text/plain'})
node.tags['amenity'] = 'restaurant'
node.tags['name'] = 'Il Tramonto'
node.should_receive(:changeset=)
new_version = osm.save(node)
new_version.should eql 43
end
end
describe '#delete:' do
let :node do
osm.find_node 123
end
before do
stub_changeset_lookup
stub_user_lookup
stub_node_lookup
end
it "should delete an existing node" do
stub_request(:delete, "http://www.openstreetmap.org/api/0.6/node/123").to_return(:status => 200, :body => '43', :headers => {'Content-Type' => 'text/plain'})
node.should_receive(:changeset=)
lambda {
# Delete is not implemented using oauth
new_version = osm.destroy(node)
}.should raise_error(Rosemary::NotImplemented)
end
end
end
end