rosemary 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +41 -0
- data/.rbenv-version +1 -0
- data/.rspec +2 -0
- data/.rvmrc +2 -0
- data/.travis.yml +7 -0
- data/CHANGELOG +1 -0
- data/Gemfile +3 -0
- data/LICENSE +7 -0
- data/Manifest +31 -0
- data/README.md +70 -0
- data/Rakefile +16 -0
- data/lib/changeset_callbacks.rb +31 -0
- data/lib/hash.rb +19 -0
- data/lib/rosemary/api.rb +214 -0
- data/lib/rosemary/basic_auth_client.rb +15 -0
- data/lib/rosemary/changeset.rb +93 -0
- data/lib/rosemary/element.rb +280 -0
- data/lib/rosemary/errors.rb +55 -0
- data/lib/rosemary/member.rb +39 -0
- data/lib/rosemary/node.rb +51 -0
- data/lib/rosemary/oauth_client.rb +31 -0
- data/lib/rosemary/parser.rb +123 -0
- data/lib/rosemary/relation.rb +52 -0
- data/lib/rosemary/tags.rb +26 -0
- data/lib/rosemary/user.rb +34 -0
- data/lib/rosemary/version.rb +3 -0
- data/lib/rosemary/way.rb +84 -0
- data/lib/rosemary.rb +33 -0
- data/rosemary.gemspec +58 -0
- data/spec/integration/changeset_spec.rb +132 -0
- data/spec/integration/node_spec.rb +384 -0
- data/spec/integration/way_spec.rb +52 -0
- data/spec/models/changeset_spec.rb +90 -0
- data/spec/models/node_spec.rb +87 -0
- data/spec/models/relation_spec.rb +26 -0
- data/spec/models/way_spec.rb +77 -0
- data/spec/spec_helper.rb +3 -0
- metadata +244 -0
data/lib/rosemary/way.rb
ADDED
@@ -0,0 +1,84 @@
|
|
1
|
+
module Rosemary
|
2
|
+
# OpenStreetMap Way.
|
3
|
+
#
|
4
|
+
# To create a new Rosemary::Way object:
|
5
|
+
# way = Rosemary::Way.new()
|
6
|
+
#
|
7
|
+
# To get a way from the API:
|
8
|
+
# way = Rosemary::Way.find_way(17)
|
9
|
+
#
|
10
|
+
class Way < Element
|
11
|
+
# Array of node IDs in this way.
|
12
|
+
attr_reader :nodes
|
13
|
+
|
14
|
+
# Create new Way object.
|
15
|
+
#
|
16
|
+
# id:: ID of this way. If +nil+ a new unique negative ID will be allocated.
|
17
|
+
# user:: Username
|
18
|
+
# timestamp:: Timestamp of last change
|
19
|
+
# nodes:: Array of Node objects and/or node IDs
|
20
|
+
def initialize(attrs = {})
|
21
|
+
attrs.stringify_keys!
|
22
|
+
@nodes = []
|
23
|
+
super(attrs)
|
24
|
+
end
|
25
|
+
|
26
|
+
def type
|
27
|
+
'Way'
|
28
|
+
end
|
29
|
+
|
30
|
+
# Add one or more tags or nodes to this way.
|
31
|
+
#
|
32
|
+
# The argument can be one of the following:
|
33
|
+
#
|
34
|
+
# * If the argument is a Hash or an OSM::Tags object, those tags are added.
|
35
|
+
# * If the argument is an OSM::Node object, its ID is added to the list of node IDs.
|
36
|
+
# * If the argument is an Integer or String containing an Integer, this ID is added to the list of node IDs.
|
37
|
+
# * If the argument is an Array the function is called recursively, i.e. all items in the Array are added.
|
38
|
+
#
|
39
|
+
# Returns the way to allow chaining.
|
40
|
+
#
|
41
|
+
# call-seq: way << something -> Way
|
42
|
+
#
|
43
|
+
def <<(stuff)
|
44
|
+
case stuff
|
45
|
+
when Array # call this method recursively
|
46
|
+
stuff.each do |item|
|
47
|
+
self << item
|
48
|
+
end
|
49
|
+
when Rosemary::Node
|
50
|
+
nodes << stuff.id
|
51
|
+
when String
|
52
|
+
nodes << stuff.to_i
|
53
|
+
when Integer
|
54
|
+
nodes << stuff
|
55
|
+
else
|
56
|
+
tags.merge!(stuff)
|
57
|
+
end
|
58
|
+
self # return self to allow chaining
|
59
|
+
end
|
60
|
+
|
61
|
+
|
62
|
+
# The list of attributes for this Way
|
63
|
+
def attribute_list # :nodoc:
|
64
|
+
[:id, :version, :uid, :user, :timestamp, :changeset]
|
65
|
+
end
|
66
|
+
|
67
|
+
def self.from_xml(xml_string)
|
68
|
+
Parser.call(xml_string, :xml)
|
69
|
+
end
|
70
|
+
|
71
|
+
def to_xml(options = {})
|
72
|
+
xml = options[:builder] ||= Builder::XmlMarkup.new
|
73
|
+
xml.instruct! unless options[:skip_instruct]
|
74
|
+
xml.osm do
|
75
|
+
xml.way(attributes) do
|
76
|
+
nodes.each do |node_id|
|
77
|
+
xml.nd(:ref => node_id)
|
78
|
+
end unless nodes.empty?
|
79
|
+
tags.to_xml(:builder => xml, :skip_instruct => true)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
data/lib/rosemary.rb
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
require "rosemary/version"
|
2
|
+
|
3
|
+
require 'hash'
|
4
|
+
require 'active_model'
|
5
|
+
require 'changeset_callbacks'
|
6
|
+
require 'rosemary/tags'
|
7
|
+
require 'rosemary/element'
|
8
|
+
require 'rosemary/node'
|
9
|
+
require 'rosemary/way'
|
10
|
+
require 'rosemary/changeset'
|
11
|
+
require 'rosemary/relation'
|
12
|
+
require 'rosemary/member'
|
13
|
+
require 'rosemary/user'
|
14
|
+
require 'rosemary/errors'
|
15
|
+
require 'rosemary/basic_auth_client'
|
16
|
+
require 'rosemary/oauth_client'
|
17
|
+
require 'rosemary/parser'
|
18
|
+
require 'rosemary/api'
|
19
|
+
require 'oauth'
|
20
|
+
|
21
|
+
# The Rosemary class handles all calls to the OpenStreetMap API.
|
22
|
+
#
|
23
|
+
# Usage:
|
24
|
+
# require 'osm'
|
25
|
+
# auth_client = Rosemary::BasicAuthClient.new(:user_name => 'user', :password => 'a_password')
|
26
|
+
# osm = Rosemary.new(auth_client)
|
27
|
+
# @node = osm.find_node(1234)
|
28
|
+
# @node.tags << {:wheelchair => 'no'}
|
29
|
+
# osm.save(@node)
|
30
|
+
#
|
31
|
+
module Rosemary
|
32
|
+
|
33
|
+
end
|
data/rosemary.gemspec
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "rosemary/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "rosemary"
|
7
|
+
s.version = Rosemary::VERSION
|
8
|
+
|
9
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
|
10
|
+
s.authors = ["Christoph B\u{fc}nte, Enno Brehm"]
|
11
|
+
s.date = "2012-03-22"
|
12
|
+
s.description = "OpenStreetMap API client for ruby"
|
13
|
+
s.email = ["info@christophbuente.de"]
|
14
|
+
s.extra_rdoc_files = ["CHANGELOG", "LICENSE", "README.md", "lib/changeset_callbacks.rb", "lib/hash.rb", "lib/rosemary/api.rb", "lib/rosemary/basic_auth_client.rb", "lib/rosemary/changeset.rb", "lib/rosemary/element.rb", "lib/rosemary/errors.rb", "lib/rosemary/member.rb", "lib/rosemary/node.rb", "lib/rosemary/oauth_client.rb", "lib/rosemary/parser.rb", "lib/rosemary/relation.rb", "lib/rosemary/tags.rb", "lib/rosemary/user.rb", "lib/rosemary/way.rb", "lib/rosemary.rb"]
|
15
|
+
s.homepage = "https://github.com/sozialhelden/openstreetmap"
|
16
|
+
s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "OpenStreetMap", "--main", "README.md"]
|
17
|
+
s.require_paths = ["lib"]
|
18
|
+
s.rubyforge_project = "rosemary"
|
19
|
+
s.rubygems_version = "1.8.10"
|
20
|
+
|
21
|
+
s.summary = "OpenStreetMap API client for ruby"
|
22
|
+
|
23
|
+
s.files = `git ls-files`.split("\n")
|
24
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
25
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
26
|
+
s.require_paths = ["lib"]
|
27
|
+
|
28
|
+
if s.respond_to? :specification_version then
|
29
|
+
s.specification_version = 3
|
30
|
+
|
31
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
32
|
+
s.add_runtime_dependency(%q<httparty>, [">= 0"])
|
33
|
+
s.add_runtime_dependency(%q<libxml-ruby>, [">= 0"])
|
34
|
+
s.add_runtime_dependency(%q<builder>, [">= 0"])
|
35
|
+
s.add_runtime_dependency(%q<oauth>, [">= 0"])
|
36
|
+
s.add_runtime_dependency(%q<activemodel>, [">= 0"])
|
37
|
+
s.add_development_dependency(%q<rspec>, [">= 0"])
|
38
|
+
s.add_development_dependency(%q<webmock>, [">= 0"])
|
39
|
+
s.add_development_dependency(%q<rake>, [">= 0"])
|
40
|
+
else
|
41
|
+
s.add_dependency(%q<httparty>, [">= 0"])
|
42
|
+
s.add_dependency(%q<libxml-ruby>, [">= 0"])
|
43
|
+
s.add_dependency(%q<builder>, [">= 0"])
|
44
|
+
s.add_dependency(%q<oauth>, [">= 0"])
|
45
|
+
s.add_dependency(%q<activemodel>, [">= 0"])
|
46
|
+
s.add_dependency(%q<rspec>, [">= 0"])
|
47
|
+
s.add_dependency(%q<webmock>, [">= 0"])
|
48
|
+
end
|
49
|
+
else
|
50
|
+
s.add_dependency(%q<httparty>, [">= 0"])
|
51
|
+
s.add_dependency(%q<libxml-ruby>, [">= 0"])
|
52
|
+
s.add_dependency(%q<builder>, [">= 0"])
|
53
|
+
s.add_dependency(%q<oauth>, [">= 0"])
|
54
|
+
s.add_dependency(%q<activemodel>, [">= 0"])
|
55
|
+
s.add_dependency(%q<rspec>, [">= 0"])
|
56
|
+
s.add_dependency(%q<webmock>, [">= 0"])
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,132 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Rosemary::Changeset do
|
4
|
+
|
5
|
+
before do
|
6
|
+
WebMock.disable_net_connect!
|
7
|
+
end
|
8
|
+
|
9
|
+
let :osm do
|
10
|
+
Rosemary::Api.new
|
11
|
+
end
|
12
|
+
|
13
|
+
def valid_fake_user
|
14
|
+
user=<<-EOF
|
15
|
+
<osm version="0.6" generator="OpenStreetMap server">
|
16
|
+
<user display_name="Max Muster" account_created="2006-07-21T19:28:26Z" id="1234">
|
17
|
+
<home lat="49.4733718952806" lon="8.89285988577866" zoom="3"/>
|
18
|
+
<description>The description of your profile</description>
|
19
|
+
<languages>
|
20
|
+
<lang>de-DE</lang>
|
21
|
+
<lang>de</lang>
|
22
|
+
<lang>en-US</lang>
|
23
|
+
<lang>en</lang>
|
24
|
+
</languages>
|
25
|
+
</user>
|
26
|
+
</osm>
|
27
|
+
EOF
|
28
|
+
end
|
29
|
+
|
30
|
+
def missing_changeset
|
31
|
+
changeset=<<-EOF
|
32
|
+
<osm version="0.6" generator="OpenStreetMap server"/>
|
33
|
+
EOF
|
34
|
+
end
|
35
|
+
|
36
|
+
def single_changeset
|
37
|
+
changeset=<<-EOF
|
38
|
+
<osm version="0.6" generator="OpenStreetMap server">
|
39
|
+
<changeset id="10" user="fred" uid="123" created_at="2008-11-08T19:07:39+01:00" open="true" min_lon="7.0191821" min_lat="49.2785426" max_lon="7.0197485" max_lat="49.2793101">
|
40
|
+
<tag k="created_by" v="JOSM 1.61"/>
|
41
|
+
<tag k="comment" v="Just adding some streetnames"/>
|
42
|
+
</changeset>
|
43
|
+
</osm>
|
44
|
+
EOF
|
45
|
+
end
|
46
|
+
|
47
|
+
def multiple_changeset
|
48
|
+
changeset=<<-EOF
|
49
|
+
<osm version="0.6" generator="OpenStreetMap server">
|
50
|
+
<changeset id="10" user="fred" uid="123" created_at="2008-11-08T19:07:39+01:00" open="true" min_lon="7.0191821" min_lat="49.2785426" max_lon="7.0197485" max_lat="49.2793101">
|
51
|
+
<tag k="created_by" v="JOSM 1.61"/>
|
52
|
+
<tag k="comment" v="Just adding some streetnames"/>
|
53
|
+
</changeset>
|
54
|
+
<changeset id="11" user="fred" uid="123" created_at="2008-11-08T19:07:39+01:00" open="true" min_lon="7.0191821" min_lat="49.2785426" max_lon="7.0197485" max_lat="49.2793101">
|
55
|
+
<tag k="created_by" v="JOSM 1.61"/>
|
56
|
+
<tag k="comment" v="Just adding some streetnames"/>
|
57
|
+
</changeset>
|
58
|
+
</osm>
|
59
|
+
EOF
|
60
|
+
end
|
61
|
+
|
62
|
+
describe '#find:' do
|
63
|
+
|
64
|
+
let :request_url do
|
65
|
+
"http://www.openstreetmap.org/api/0.6/changeset/10"
|
66
|
+
end
|
67
|
+
|
68
|
+
let :stubbed_request do
|
69
|
+
stub_request(:get, request_url)
|
70
|
+
end
|
71
|
+
|
72
|
+
it "should build a Change from API response via find_changeset_object" do
|
73
|
+
stubbed_request.to_return(:status => 200, :body => single_changeset, :headers => {'Content-Type' => 'application/xml'})
|
74
|
+
changeset = osm.find_changeset(10)
|
75
|
+
assert_requested :get, request_url, :times => 1
|
76
|
+
changeset.class.should eql Rosemary::Changeset
|
77
|
+
end
|
78
|
+
|
79
|
+
it "should raise an NotFound error, when a changeset cannot be found" do
|
80
|
+
stubbed_request.to_return(:status => 404, :body => '', :headers => {'Content-Type' => 'text/plain'})
|
81
|
+
lambda {
|
82
|
+
node = osm.find_changeset(10)
|
83
|
+
}.should raise_error(Rosemary::NotFound)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
describe '#find_for_user' do
|
88
|
+
|
89
|
+
let :osm do
|
90
|
+
Rosemary::Api.new(Rosemary::BasicAuthClient.new('a_username', 'a_password'))
|
91
|
+
end
|
92
|
+
|
93
|
+
let :request_url do
|
94
|
+
"http://www.openstreetmap.org/api/0.6/changesets?user=1234"
|
95
|
+
end
|
96
|
+
|
97
|
+
let :stubbed_request do
|
98
|
+
stub_request(:get, request_url)
|
99
|
+
end
|
100
|
+
|
101
|
+
let! :stub_user_lookup do
|
102
|
+
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'} )
|
103
|
+
end
|
104
|
+
|
105
|
+
it "should not find changeset for user if user has none" do
|
106
|
+
stubbed_request.to_return(:status => 200, :body => missing_changeset, :headers => {'Content-Type' => 'application/xml'})
|
107
|
+
changesets = osm.find_changesets_for_user
|
108
|
+
changesets.should be_empty
|
109
|
+
end
|
110
|
+
|
111
|
+
it "should find a single changeset for user" do
|
112
|
+
stubbed_request.to_return(:status => 200, :body => single_changeset, :headers => {'Content-Type' => 'application/xml'})
|
113
|
+
changesets = osm.find_changesets_for_user
|
114
|
+
changesets.size.should eql 1
|
115
|
+
changesets.first.class.should eql Rosemary::Changeset
|
116
|
+
end
|
117
|
+
|
118
|
+
it "should find a multiple changesets for a user" do
|
119
|
+
stubbed_request.to_return(:status => 200, :body => multiple_changeset, :headers => {'Content-Type' => 'application/xml'})
|
120
|
+
changesets = osm.find_changesets_for_user
|
121
|
+
changesets.size.should eql 2
|
122
|
+
changesets.first.class.should eql Rosemary::Changeset
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
describe '#update:' do
|
127
|
+
end
|
128
|
+
|
129
|
+
describe '#close' do
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
@@ -0,0 +1,384 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Rosemary::Node do
|
4
|
+
|
5
|
+
before do
|
6
|
+
WebMock.disable_net_connect!
|
7
|
+
end
|
8
|
+
|
9
|
+
let :osm do
|
10
|
+
Rosemary::Api.new
|
11
|
+
end
|
12
|
+
|
13
|
+
let :stub_changeset_lookup do
|
14
|
+
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'} )
|
15
|
+
end
|
16
|
+
|
17
|
+
let :stub_node_lookup do
|
18
|
+
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'})
|
19
|
+
end
|
20
|
+
|
21
|
+
def valid_fake_node
|
22
|
+
node=<<-EOF
|
23
|
+
<osm>
|
24
|
+
<node id="123" lat="51.2" lon="13.4" version="42" changeset="12" user="fred" uid="123" visible="true" timestamp="2005-07-30T14:27:12+01:00">
|
25
|
+
<tag k="note" v="Just a node"/>
|
26
|
+
<tag k="amenity" v="bar" />
|
27
|
+
<tag k="name" v="The rose" />
|
28
|
+
</node>
|
29
|
+
</osm>
|
30
|
+
EOF
|
31
|
+
end
|
32
|
+
|
33
|
+
def valid_fake_user
|
34
|
+
user=<<-EOF
|
35
|
+
<osm version="0.6" generator="OpenStreetMap server">
|
36
|
+
<user display_name="Max Muster" account_created="2006-07-21T19:28:26Z" id="1234">
|
37
|
+
<home lat="49.4733718952806" lon="8.89285988577866" zoom="3"/>
|
38
|
+
<description>The description of your profile</description>
|
39
|
+
<languages>
|
40
|
+
<lang>de-DE</lang>
|
41
|
+
<lang>de</lang>
|
42
|
+
<lang>en-US</lang>
|
43
|
+
<lang>en</lang>
|
44
|
+
</languages>
|
45
|
+
</user>
|
46
|
+
</osm>
|
47
|
+
EOF
|
48
|
+
end
|
49
|
+
|
50
|
+
def valid_fake_changeset
|
51
|
+
changeset=<<-EOF
|
52
|
+
<osm>
|
53
|
+
<changeset id="10" user="fred" uid="123" created_at="2008-11-08T19:07:39+01:00" open="true" min_lon="7.0191821" min_lat="49.2785426" max_lon="7.0197485" max_lat="49.2793101">
|
54
|
+
<tag k="created_by" v="JOSM 1.61"/>
|
55
|
+
<tag k="comment" v="Just adding some streetnames"/>
|
56
|
+
</changeset>
|
57
|
+
</osm>
|
58
|
+
EOF
|
59
|
+
end
|
60
|
+
|
61
|
+
describe '#find:' do
|
62
|
+
|
63
|
+
let :request_url do
|
64
|
+
"http://www.openstreetmap.org/api/0.6/node/1234"
|
65
|
+
end
|
66
|
+
|
67
|
+
let :stubbed_request do
|
68
|
+
stub_request(:get, request_url)
|
69
|
+
end
|
70
|
+
|
71
|
+
it "should build a Node from API response via get_object" do
|
72
|
+
stubbed_request.to_return(:status => 200, :body => valid_fake_node, :headers => {'Content-Type' => 'application/xml'})
|
73
|
+
node = osm.find_node 1234
|
74
|
+
assert_requested :get, request_url, :times => 1
|
75
|
+
node.class.should eql Rosemary::Node
|
76
|
+
node.tags.size.should eql 3
|
77
|
+
node.tags['name'].should eql 'The rose'
|
78
|
+
node['name'].should eql 'The rose'
|
79
|
+
node.add_tags('wheelchair' => 'yes')
|
80
|
+
node['wheelchair'].should eql 'yes'
|
81
|
+
end
|
82
|
+
|
83
|
+
it "should raise a Unavailable, when api times out" do
|
84
|
+
stubbed_request.to_timeout
|
85
|
+
lambda {
|
86
|
+
node = osm.find_node(1234)
|
87
|
+
}.should raise_error(Rosemary::Unavailable)
|
88
|
+
end
|
89
|
+
|
90
|
+
it "should raise an Gone error, when a node has been deleted" do
|
91
|
+
stubbed_request.to_return(:status => 410, :body => '', :headers => {'Content-Type' => 'text/plain'})
|
92
|
+
lambda {
|
93
|
+
node = osm.find_node(1234)
|
94
|
+
}.should raise_error(Rosemary::Gone)
|
95
|
+
end
|
96
|
+
|
97
|
+
it "should raise an NotFound error, when a node cannot be found" do
|
98
|
+
stubbed_request.to_return(:status => 404, :body => '', :headers => {'Content-Type' => 'text/plain'})
|
99
|
+
lambda {
|
100
|
+
node = osm.find_node(1234)
|
101
|
+
}.should raise_error(Rosemary::NotFound)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
describe 'with BasicAuthClient' do
|
106
|
+
|
107
|
+
let :osm do
|
108
|
+
Rosemary::Api.new(Rosemary::BasicAuthClient.new('a_username', 'a_password'))
|
109
|
+
end
|
110
|
+
|
111
|
+
let :stub_user_lookup do
|
112
|
+
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'} )
|
113
|
+
end
|
114
|
+
|
115
|
+
describe '#create:' do
|
116
|
+
|
117
|
+
let :node do
|
118
|
+
Rosemary::Node.new
|
119
|
+
end
|
120
|
+
|
121
|
+
let :request_url do
|
122
|
+
"http://a_username:a_password@www.openstreetmap.org/api/0.6/node/create"
|
123
|
+
end
|
124
|
+
|
125
|
+
let :stubbed_request do
|
126
|
+
stub_request(:put, request_url)
|
127
|
+
end
|
128
|
+
|
129
|
+
before do
|
130
|
+
stub_changeset_lookup
|
131
|
+
stub_user_lookup
|
132
|
+
end
|
133
|
+
|
134
|
+
it "should create a new Node from given attributes" do
|
135
|
+
stubbed_request.to_return(:status => 200, :body => '123', :headers => {'Content-Type' => 'text/plain'})
|
136
|
+
node.id.should be_nil
|
137
|
+
new_id = osm.save(node)
|
138
|
+
end
|
139
|
+
|
140
|
+
it "should raise a Unavailable, when api times out" do
|
141
|
+
stubbed_request.to_timeout
|
142
|
+
lambda {
|
143
|
+
new_id = osm.save(node)
|
144
|
+
}.should raise_error(Rosemary::Unavailable)
|
145
|
+
end
|
146
|
+
|
147
|
+
it "should not create a Node with invalid xml but raise BadRequest" do
|
148
|
+
stubbed_request.to_return(:status => 400, :body => 'The given node is invalid', :headers => {'Content-Type' => 'text/plain'})
|
149
|
+
lambda {
|
150
|
+
new_id = osm.save(node)
|
151
|
+
}.should raise_error(Rosemary::BadRequest)
|
152
|
+
end
|
153
|
+
|
154
|
+
it "should not allow to create a node when a changeset has been closed" do
|
155
|
+
stubbed_request.to_return(:status => 409, :body => 'The given node is invalid', :headers => {'Content-Type' => 'text/plain'})
|
156
|
+
lambda {
|
157
|
+
new_id = osm.save(node)
|
158
|
+
}.should raise_error(Rosemary::Conflict)
|
159
|
+
end
|
160
|
+
|
161
|
+
it "should not allow to create a node when no authentication client is given" do
|
162
|
+
osm = Rosemary::Api.new
|
163
|
+
lambda {
|
164
|
+
osm.save(node)
|
165
|
+
}.should raise_error(Rosemary::CredentialsMissing)
|
166
|
+
end
|
167
|
+
|
168
|
+
end
|
169
|
+
|
170
|
+
describe '#update:' do
|
171
|
+
|
172
|
+
let :node do
|
173
|
+
osm.find_node 123
|
174
|
+
end
|
175
|
+
|
176
|
+
before do
|
177
|
+
stub_changeset_lookup
|
178
|
+
stub_user_lookup
|
179
|
+
stub_node_lookup
|
180
|
+
end
|
181
|
+
|
182
|
+
it "should save a edited node" do
|
183
|
+
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'})
|
184
|
+
node.tags['amenity'] = 'restaurant'
|
185
|
+
node.tags['name'] = 'Il Tramonto'
|
186
|
+
node.should_receive(:changeset=)
|
187
|
+
new_version = osm.save(node)
|
188
|
+
new_version.should eql 43
|
189
|
+
end
|
190
|
+
|
191
|
+
end
|
192
|
+
|
193
|
+
describe '#delete:' do
|
194
|
+
|
195
|
+
let :node do
|
196
|
+
osm.find_node 123
|
197
|
+
end
|
198
|
+
|
199
|
+
before do
|
200
|
+
stub_changeset_lookup
|
201
|
+
stub_user_lookup
|
202
|
+
stub_node_lookup
|
203
|
+
end
|
204
|
+
|
205
|
+
it "should not delete an node with missing id" do
|
206
|
+
node = Rosemary::Node.new
|
207
|
+
osm.destroy(node)
|
208
|
+
end
|
209
|
+
|
210
|
+
it "should delete an existing node" do
|
211
|
+
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'})
|
212
|
+
node.should_receive(:changeset=)
|
213
|
+
new_version = osm.destroy(node)
|
214
|
+
new_version.should eql 43 # new version number
|
215
|
+
end
|
216
|
+
|
217
|
+
it "should raise an error if node to be deleted is still part of a way" do
|
218
|
+
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'})
|
219
|
+
lambda {
|
220
|
+
response = osm.destroy(node)
|
221
|
+
response.should eql "Version does not match current database version"
|
222
|
+
}.should raise_error Rosemary::BadRequest
|
223
|
+
end
|
224
|
+
|
225
|
+
it "should raise an error if node cannot be found" do
|
226
|
+
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'})
|
227
|
+
lambda {
|
228
|
+
response = osm.destroy(node)
|
229
|
+
response.should eql "Node cannot be found"
|
230
|
+
}.should raise_error Rosemary::NotFound
|
231
|
+
end
|
232
|
+
|
233
|
+
it "should raise an error if there is a conflict" do
|
234
|
+
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'})
|
235
|
+
lambda {
|
236
|
+
response = osm.destroy(node)
|
237
|
+
response.should eql "Node has been deleted in this changeset"
|
238
|
+
}.should raise_error Rosemary::Conflict
|
239
|
+
end
|
240
|
+
|
241
|
+
it "should raise an error if the node is already delted" do
|
242
|
+
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'})
|
243
|
+
lambda {
|
244
|
+
response = osm.destroy(node)
|
245
|
+
response.should eql "Node has been deleted"
|
246
|
+
}.should raise_error Rosemary::Gone
|
247
|
+
end
|
248
|
+
|
249
|
+
it "should raise an error if the node is part of a way" do
|
250
|
+
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'})
|
251
|
+
lambda {
|
252
|
+
response = osm.destroy(node)
|
253
|
+
response.should eql "Node 123 is still used by way 456"
|
254
|
+
}.should raise_error Rosemary::Precondition
|
255
|
+
end
|
256
|
+
|
257
|
+
end
|
258
|
+
end
|
259
|
+
|
260
|
+
describe 'with OauthClient' do
|
261
|
+
|
262
|
+
let :consumer do
|
263
|
+
OAuth::Consumer.new( 'a_key', 'a_secret',
|
264
|
+
{
|
265
|
+
:site => 'http://www.openstreetmap.org',
|
266
|
+
:request_token_path => '/oauth/request_token',
|
267
|
+
:access_token_path => '/oauth/access_token',
|
268
|
+
:authorize_path => '/oauth/authorize'
|
269
|
+
}
|
270
|
+
)
|
271
|
+
end
|
272
|
+
|
273
|
+
let :access_token do
|
274
|
+
OAuth::AccessToken.new(consumer, 'a_token', 'a_secret')
|
275
|
+
end
|
276
|
+
|
277
|
+
let :osm do
|
278
|
+
Rosemary::Api.new(Rosemary::OauthClient.new(access_token))
|
279
|
+
end
|
280
|
+
|
281
|
+
let :stub_user_lookup do
|
282
|
+
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'} )
|
283
|
+
end
|
284
|
+
|
285
|
+
describe '#create:' do
|
286
|
+
let :node do
|
287
|
+
Rosemary::Node.new
|
288
|
+
end
|
289
|
+
|
290
|
+
let :request_url do
|
291
|
+
"http://www.openstreetmap.org/api/0.6/node/create"
|
292
|
+
end
|
293
|
+
|
294
|
+
let :stubbed_request do
|
295
|
+
stub_request(:put, request_url)
|
296
|
+
end
|
297
|
+
|
298
|
+
before do
|
299
|
+
stub_changeset_lookup
|
300
|
+
stub_user_lookup
|
301
|
+
end
|
302
|
+
|
303
|
+
it "should create a new Node from given attributes" do
|
304
|
+
stubbed_request.to_return(:status => 200, :body => '123', :headers => {'Content-Type' => 'text/plain'})
|
305
|
+
node.id.should be_nil
|
306
|
+
new_id = osm.save(node)
|
307
|
+
end
|
308
|
+
|
309
|
+
it "should raise a Unavailable, when api times out" do
|
310
|
+
stubbed_request.to_timeout
|
311
|
+
lambda {
|
312
|
+
new_id = osm.save(node)
|
313
|
+
}.should raise_error(Rosemary::Unavailable)
|
314
|
+
end
|
315
|
+
|
316
|
+
|
317
|
+
it "should not create a Node with invalid xml but raise BadRequest" do
|
318
|
+
stubbed_request.to_return(:status => 400, :body => 'The given node is invalid', :headers => {'Content-Type' => 'text/plain'})
|
319
|
+
lambda {
|
320
|
+
new_id = osm.save(node)
|
321
|
+
}.should raise_error(Rosemary::BadRequest)
|
322
|
+
end
|
323
|
+
|
324
|
+
it "should not allow to create a node when a changeset has been closed" do
|
325
|
+
stubbed_request.to_return(:status => 409, :body => 'The given node is invalid', :headers => {'Content-Type' => 'text/plain'})
|
326
|
+
lambda {
|
327
|
+
new_id = osm.save(node)
|
328
|
+
}.should raise_error(Rosemary::Conflict)
|
329
|
+
end
|
330
|
+
|
331
|
+
it "should not allow to create a node when no authentication client is given" do
|
332
|
+
osm = Rosemary::Api.new
|
333
|
+
lambda {
|
334
|
+
osm.save(node)
|
335
|
+
}.should raise_error(Rosemary::CredentialsMissing)
|
336
|
+
end
|
337
|
+
|
338
|
+
end
|
339
|
+
|
340
|
+
describe '#update:' do
|
341
|
+
|
342
|
+
let :node do
|
343
|
+
osm.find_node 123
|
344
|
+
end
|
345
|
+
|
346
|
+
before do
|
347
|
+
stub_changeset_lookup
|
348
|
+
stub_user_lookup
|
349
|
+
stub_node_lookup
|
350
|
+
end
|
351
|
+
|
352
|
+
it "should save a edited node" do
|
353
|
+
stub_request(:put, "http://www.openstreetmap.org/api/0.6/node/123").to_return(:status => 200, :body => '43', :headers => {'Content-Type' => 'text/plain'})
|
354
|
+
node.tags['amenity'] = 'restaurant'
|
355
|
+
node.tags['name'] = 'Il Tramonto'
|
356
|
+
node.should_receive(:changeset=)
|
357
|
+
new_version = osm.save(node)
|
358
|
+
new_version.should eql 43
|
359
|
+
end
|
360
|
+
end
|
361
|
+
|
362
|
+
describe '#delete:' do
|
363
|
+
|
364
|
+
let :node do
|
365
|
+
osm.find_node 123
|
366
|
+
end
|
367
|
+
|
368
|
+
before do
|
369
|
+
stub_changeset_lookup
|
370
|
+
stub_user_lookup
|
371
|
+
stub_node_lookup
|
372
|
+
end
|
373
|
+
|
374
|
+
it "should delete an existing node" do
|
375
|
+
stub_request(:delete, "http://www.openstreetmap.org/api/0.6/node/123").to_return(:status => 200, :body => '43', :headers => {'Content-Type' => 'text/plain'})
|
376
|
+
node.should_receive(:changeset=)
|
377
|
+
lambda {
|
378
|
+
# Delete is not implemented using oauth
|
379
|
+
new_version = osm.destroy(node)
|
380
|
+
}.should raise_error(Rosemary::NotImplemented)
|
381
|
+
end
|
382
|
+
end
|
383
|
+
end
|
384
|
+
end
|