Reorganise tests to match modern rails test layout

This commit is contained in:
Tom Hughes 2014-02-26 00:13:19 +00:00
parent 1ea64ea977
commit 98184dfb9c
74 changed files with 78 additions and 73 deletions

View file

@ -0,0 +1,649 @@
require 'test_helper'
require 'stringio'
include Potlatch
class AmfControllerTest < ActionController::TestCase
api_fixtures
##
# test all routes which lead to this controller
def test_routes
assert_routing(
{ :path => "/api/0.6/amf/read", :method => :post },
{ :controller => "amf", :action => "amf_read" }
)
assert_routing(
{ :path => "/api/0.6/amf/write", :method => :post },
{ :controller => "amf", :action => "amf_write" }
)
end
def test_getway
# check a visible way
id = current_ways(:visible_way).id
amf_content "getway", "/1", [id]
post :amf_read
assert_response :success
amf_parse_response
way = amf_result("/1")
assert_equal way[0], 0
assert_equal way[2], id
end
def test_getway_invisible
# check an invisible way
id = current_ways(:invisible_way).id
amf_content "getway", "/1", [id]
post :amf_read
assert_response :success
amf_parse_response
way = amf_result("/1")
assert_equal way[0], -4
assert_equal way[1], "way"
assert_equal way[2], id
assert way[3].nil? and way[4].nil?
end
def test_getway_nonexistent
# check chat a non-existent way is not returned
amf_content "getway", "/1", [0]
post :amf_read
assert_response :success
amf_parse_response
way = amf_result("/1")
assert_equal way[0], -4
assert_equal way[1], "way"
assert_equal way[2], 0
assert way[3].nil? and way[4].nil?
end
def test_whichways
node = current_nodes(:used_node_1)
minlon = node.lon-0.1
minlat = node.lat-0.1
maxlon = node.lon+0.1
maxlat = node.lat+0.1
amf_content "whichways", "/1", [minlon, minlat, maxlon, maxlat]
post :amf_read
assert_response :success
amf_parse_response
# check contents of message
map = amf_result "/1"
assert_equal 0, map[0], 'map error code should be 0'
assert_equal "", map[1], 'map error text should be empty'
# check the formatting of the message
assert_equal 5, map.length, 'map should have length 5'
assert_equal Array, map[2].class, 'map "ways" element should be an array'
assert_equal Array, map[3].class, 'map "nodes" element should be an array'
assert_equal Array, map[4].class, 'map "relations" element should be an array'
map[2].each do |w|
assert_equal 2, w.length, 'way should be (id, version) pair'
assert w[0] == w[0].floor, 'way ID should be an integer'
assert w[1] == w[1].floor, 'way version should be an integer'
end
map[3].each do |n|
assert_equal 5, w.length, 'node should be (id, lat, lon, [tags], version) tuple'
assert n[0] == n[0].floor, 'node ID should be an integer'
assert n[1] >= minlat - 0.01, 'node lat should be greater than min'
assert n[1] <= maxlat - 0.01, 'node lat should be less than max'
assert n[2] >= minlon - 0.01, 'node lon should be greater than min'
assert n[2] <= maxlon - 0.01, 'node lon should be less than max'
assert_equal Array, a[3].class, 'node tags should be array'
assert n[4] == n[4].floor, 'node version should be an integer'
end
map[4].each do |r|
assert_equal 2, r.length, 'relation should be (id, version) pair'
assert r[0] == r[0].floor, 'relation ID should be an integer'
assert r[1] == r[1].floor, 'relation version should be an integer'
end
# TODO: looks like amf_controller changed since this test was written
# so someone who knows what they're doing should check this!
ways = map[2].collect { |x| x[0] }
assert ways.include?(current_ways(:used_way).id),
"map should include used way"
assert !ways.include?(current_ways(:invisible_way).id),
'map should not include deleted way'
end
##
# checks that too-large a bounding box will not be served.
def test_whichways_toobig
bbox = [-0.1,-0.1,1.1,1.1]
check_bboxes_are_bad [bbox] do |map,bbox|
assert_boundary_error map, " The server said: The maximum bbox size is 0.25, and your request was too large. Either request a smaller area, or use planet.osm"
end
end
##
# checks that an invalid bounding box will not be served. in this case
# one with max < min latitudes.
#
# NOTE: the controller expands the bbox by 0.01 in each direction!
def test_whichways_badlat
bboxes = [[0,0.1,0.1,0], [-0.1,80,0.1,70], [0.24,54.35,0.25,54.33]]
check_bboxes_are_bad bboxes do |map, bbox|
assert_boundary_error map, " The server said: The minimum latitude must be less than the maximum latitude, but it wasn't", bbox.inspect
end
end
##
# same as test_whichways_badlat, but for longitudes
#
# NOTE: the controller expands the bbox by 0.01 in each direction!
def test_whichways_badlon
bboxes = [[80,-0.1,70,0.1], [54.35,0.24,54.33,0.25]]
check_bboxes_are_bad bboxes do |map, bbox|
assert_boundary_error map, " The server said: The minimum longitude must be less than the maximum longitude, but it wasn't", bbox.inspect
end
end
def test_whichways_deleted
node = current_nodes(:used_node_1)
minlon = node.lon-0.1
minlat = node.lat-0.1
maxlon = node.lon+0.1
maxlat = node.lat+0.1
amf_content "whichways_deleted", "/1", [minlon, minlat, maxlon, maxlat]
post :amf_read
assert_response :success
amf_parse_response
# check contents of message
map = amf_result "/1"
assert_equal 0, map[0], 'first map element should be 0'
assert_equal "", map[1], 'second map element should be an empty string'
assert_equal Array, map[2].class, 'third map element should be an array'
# TODO: looks like amf_controller changed since this test was written
# so someone who knows what they're doing should check this!
assert !map[2].include?(current_ways(:used_way).id),
"map should not include used way"
assert map[2].include?(current_ways(:invisible_way).id),
'map should include deleted way'
end
def test_whichways_deleted_toobig
bbox = [-0.1,-0.1,1.1,1.1]
amf_content "whichways_deleted", "/1", bbox
post :amf_read
assert_response :success
amf_parse_response
map = amf_result "/1"
assert_deleted_boundary_error map, " The server said: The maximum bbox size is 0.25, and your request was too large. Either request a smaller area, or use planet.osm"
end
def test_getrelation
id = current_relations(:visible_relation).id
amf_content "getrelation", "/1", [id]
post :amf_read
assert_response :success
amf_parse_response
rel = amf_result("/1")
assert_equal rel[0], 0
assert_equal rel[2], id
end
def test_getrelation_invisible
id = current_relations(:invisible_relation).id
amf_content "getrelation", "/1", [id]
post :amf_read
assert_response :success
amf_parse_response
rel = amf_result("/1")
assert_equal rel[0], -4
assert_equal rel[1], "relation"
assert_equal rel[2], id
assert rel[3].nil? and rel[4].nil?
end
def test_getrelation_nonexistent
id = 0
amf_content "getrelation", "/1", [id]
post :amf_read
assert_response :success
amf_parse_response
rel = amf_result("/1")
assert_equal rel[0], -4
assert_equal rel[1], "relation"
assert_equal rel[2], id
assert rel[3].nil? and rel[4].nil?
end
def test_getway_old
# try to get the last visible version (specified by <0) (should be current version)
latest = current_ways(:way_with_versions)
# NOTE: looks from the API changes that this now expects a timestamp
# instead of a version number...
# try to get version 1
v1 = ways(:way_with_versions_v1)
{ latest.id => '',
v1.way_id => v1.timestamp.strftime("%d %b %Y, %H:%M:%S")
}.each do |id, t|
amf_content "getway_old", "/1", [id, t]
post :amf_read
assert_response :success
amf_parse_response
returned_way = amf_result("/1")
assert_equal 0, returned_way[0]
assert_equal id, returned_way[2]
# API returns the *latest* version, even for old ways...
assert_equal latest.version, returned_way[5]
end
end
##
# test that the server doesn't fall over when rubbish is passed
# into the method args.
def test_getway_old_invalid
way_id = current_ways(:way_with_versions).id
{ "foo" => "bar",
way_id => "not a date",
way_id => "2009-03-25 00:00:00", # <- wrong format
way_id => "0 Jan 2009 00:00:00", # <- invalid date
-1 => "1 Jan 2009 00:00:00" # <- invalid ID
}.each do |id, t|
amf_content "getway_old", "/1", [id, t]
post :amf_read
assert_response :success
amf_parse_response
returned_way = amf_result("/1")
assert_equal -1, returned_way[0]
assert returned_way[3].nil?
assert returned_way[4].nil?
assert returned_way[5].nil?
end
end
def test_getway_old_nonexistent
# try to get the last version+10 (shoudn't exist)
v1 = ways(:way_with_versions_v1)
# try to get last visible version of non-existent way
# try to get specific version of non-existent way
[[0, ''],
[0, '1 Jan 1970, 00:00:00'],
[v1.way_id, (v1.timestamp - 10).strftime("%d %b %Y, %H:%M:%S")]
].each do |id, t|
amf_content "getway_old", "/1", [id, t]
post :amf_read
assert_response :success
amf_parse_response
returned_way = amf_result("/1")
assert_equal -1, returned_way[0]
assert returned_way[3].nil?
assert returned_way[4].nil?
assert returned_way[5].nil?
end
end
def test_getway_history
latest = current_ways(:way_with_versions)
oldest = ways(:way_with_versions_v1)
amf_content "getway_history", "/1", [latest.id]
post :amf_read
assert_response :success
amf_parse_response
history = amf_result("/1")
# ['way',wayid,history]
assert_equal 'way', history[0]
assert_equal latest.id, history[1]
# We use dates rather than version numbers here, because you might
# have moved a node within a way (i.e. way version not incremented).
# The timestamp is +1 because we say "give me the revision of 15:33:02",
# but that might actually include changes at 15:33:02.457.
assert_equal (latest.timestamp + 1).strftime("%d %b %Y, %H:%M:%S"), history[2].first[0]
assert_equal (oldest.timestamp + 1).strftime("%d %b %Y, %H:%M:%S"), history[2].last[0]
end
def test_getway_history_nonexistent
amf_content "getway_history", "/1", [0]
post :amf_read
assert_response :success
amf_parse_response
history = amf_result("/1")
# ['way',wayid,history]
assert_equal history[0], 'way'
assert_equal history[1], 0
assert history[2].empty?
end
def test_getnode_history
latest = current_nodes(:node_with_versions)
amf_content "getnode_history", "/1", [latest.id]
post :amf_read
assert_response :success
amf_parse_response
history = amf_result("/1")
# ['node',nodeid,history]
# note that (as per getway_history) we actually round up
# to the next second
assert_equal history[0], 'node',
'first element should be "node"'
assert_equal history[1], latest.id,
'second element should be the input node ID'
assert_equal history[2].first[0],
(latest.timestamp + 1).strftime("%d %b %Y, %H:%M:%S"),
'first element in third element (array) should be the latest version'
assert_equal history[2].last[0],
(nodes(:node_with_versions_v1).timestamp + 1).strftime("%d %b %Y, %H:%M:%S"),
'last element in third element (array) should be the initial version'
end
def test_getnode_history_nonexistent
amf_content "getnode_history", "/1", [0]
post :amf_read
assert_response :success
amf_parse_response
history = amf_result("/1")
# ['node',nodeid,history]
assert_equal history[0], 'node'
assert_equal history[1], 0
assert history[2].empty?
end
# ************************************************************
# AMF Write tests
def test_putpoi_update_valid
nd = current_nodes(:visible_node)
cs_id = changesets(:public_user_first_change).id
amf_content "putpoi", "/1", ["test@example.com:test", cs_id, nd.version, nd.id, nd.lon, nd.lat, nd.tags, nd.visible]
post :amf_write
assert_response :success
amf_parse_response
result = amf_result("/1")
assert_equal 0, result[0]
assert_equal "", result[1]
assert_equal nd.id, result[2]
assert_equal nd.id, result[3]
assert_equal nd.version+1, result[4]
# Now try to update again, with a different lat/lon, using the updated version number
lat = nd.lat+0.1
lon = nd.lon-0.1
amf_content "putpoi", "/2", ["test@example.com:test", cs_id, nd.version+1, nd.id, lon, lat, nd.tags, nd.visible]
post :amf_write
assert_response :success
amf_parse_response
result = amf_result("/2")
assert_equal 0, result[0]
assert_equal "", result[1]
assert_equal nd.id, result[2]
assert_equal nd.id, result[3]
assert_equal nd.version+2, result[4]
end
# Check that we can create a no valid poi
# Using similar method for the node controller test
def test_putpoi_create_valid
# This node has no tags
nd = Node.new
# create a node with random lat/lon
lat = rand(100)-50 + rand
lon = rand(100)-50 + rand
# normal user has a changeset open
changeset = changesets(:public_user_first_change)
amf_content "putpoi", "/1", ["test@example.com:test", changeset.id, nil, nil, lon, lat, {}, nil]
post :amf_write
assert_response :success
amf_parse_response
result = amf_result("/1")
# check the array returned by the amf
assert_equal 5, result.size
assert_equal 0, result[0], "expected to get the status ok from the amf"
assert_equal 0, result[2], "The old id should be 0"
assert result[3] > 0, "The new id should be greater than 0"
assert_equal 1, result[4], "The new version should be 1"
# Finally check that the node that was saved has saved the data correctly
# in both the current and history tables
# First check the current table
current_node = Node.find(result[3].to_i)
assert_in_delta lat, current_node.lat, 0.00001, "The latitude was not retreieved correctly"
assert_in_delta lon, current_node.lon, 0.00001, "The longitude was not retreived correctly"
assert_equal 0, current_node.tags.size, "There seems to be a tag that has been added to the node"
assert_equal result[4], current_node.version, "The version returned, is different to the one returned by the amf"
# Now check the history table
historic_nodes = Node.where(:id => result[3])
assert_equal 1, historic_nodes.size, "There should only be one historic node created"
first_historic_node = historic_nodes.first
assert_in_delta lat, first_historic_node.lat, 0.00001, "The latitude was not retreived correctly"
assert_in_delta lon, first_historic_node.lon, 0.00001, "The longitude was not retreuved correctly"
assert_equal 0, first_historic_node.tags.size, "There seems to be a tag that have been attached to this node"
assert_equal result[4], first_historic_node.version, "The version returned, is different to the one returned by the amf"
####
# This node has some tags
tnd = Node.new
# create a node with random lat/lon
lat = rand(100)-50 + rand
lon = rand(100)-50 + rand
# normal user has a changeset open
changeset = changesets(:public_user_first_change)
amf_content "putpoi", "/2", ["test@example.com:test", changeset.id, nil, nil, lon, lat, { "key" => "value", "ping" => "pong" }, nil]
post :amf_write
assert_response :success
amf_parse_response
result = amf_result("/2")
# check the array returned by the amf
assert_equal 5, result.size
assert_equal 0, result[0], "Expected to get the status ok in the amf"
assert_equal 0, result[2], "The old id should be 0"
assert result[3] > 0, "The new id should be greater than 0"
assert_equal 1, result[4], "The new version should be 1"
# Finally check that the node that was saved has saved the data correctly
# in both the current and history tables
# First check the current table
current_node = Node.find(result[3].to_i)
assert_in_delta lat, current_node.lat, 0.00001, "The latitude was not retreieved correctly"
assert_in_delta lon, current_node.lon, 0.00001, "The longitude was not retreived correctly"
assert_equal 2, current_node.tags.size, "There seems to be a tag that has been added to the node"
assert_equal({ "key" => "value", "ping" => "pong" }, current_node.tags, "tags are different")
assert_equal result[4], current_node.version, "The version returned, is different to the one returned by the amf"
# Now check the history table
historic_nodes = Node.where(:id => result[3])
assert_equal 1, historic_nodes.size, "There should only be one historic node created"
first_historic_node = historic_nodes.first
assert_in_delta lat, first_historic_node.lat, 0.00001, "The latitude was not retreived correctly"
assert_in_delta lon, first_historic_node.lon, 0.00001, "The longitude was not retreuved correctly"
assert_equal 2, first_historic_node.tags.size, "There seems to be a tag that have been attached to this node"
assert_equal({ "key" => "value", "ping" => "pong" }, first_historic_node.tags, "tags are different")
assert_equal result[4], first_historic_node.version, "The version returned, is different to the one returned by the amf"
end
# try creating a POI with rubbish in the tags
def test_putpoi_create_with_control_chars
# This node has no tags
nd = Node.new
# create a node with random lat/lon
lat = rand(100)-50 + rand
lon = rand(100)-50 + rand
# normal user has a changeset open
changeset = changesets(:public_user_first_change)
mostly_invalid = (0..31).to_a.map {|i| i.chr}.join
tags = { "something" => "foo#{mostly_invalid}bar" }
amf_content "putpoi", "/1", ["test@example.com:test", changeset.id, nil, nil, lon, lat, tags, nil]
post :amf_write
assert_response :success
amf_parse_response
result = amf_result("/1")
# check the array returned by the amf
assert_equal 5, result.size
assert_equal 0, result[0], "Expected to get the status ok in the amf"
assert_equal 0, result[2], "The old id should be 0"
assert result[3] > 0, "The new id should be greater than 0"
assert_equal 1, result[4], "The new version should be 1"
# Finally check that the node that was saved has saved the data correctly
# in both the current and history tables
# First check the current table
current_node = Node.find(result[3].to_i)
assert_equal 1, current_node.tags.size, "There seems to be a tag that has been added to the node"
assert_equal({ "something" => "foo\t\n\rbar" }, current_node.tags, "tags were not fixed correctly")
assert_equal result[4], current_node.version, "The version returned, is different to the one returned by the amf"
end
# try creating a POI with rubbish in the tags
def test_putpoi_create_with_invalid_utf8
# This node has no tags
nd = Node.new
# create a node with random lat/lon
lat = rand(100)-50 + rand
lon = rand(100)-50 + rand
# normal user has a changeset open
changeset = changesets(:public_user_first_change)
invalid = "\xc0\xc0"
tags = { "something" => "foo#{invalid}bar" }
amf_content "putpoi", "/1", ["test@example.com:test", changeset.id, nil, nil, lon, lat, tags, nil]
post :amf_write
assert_response :success
amf_parse_response
result = amf_result("/1")
assert_equal 2, result.size
assert_equal -1, result[0], "Expected to get the status FAIL in the amf"
assert_equal "One of the tags is invalid. Linux users may need to upgrade to Flash Player 10.1.", result[1]
end
def test_putpoi_delete_valid
end
def test_putpoi_delete_already_deleted
end
def test_putpoi_delete_not_found
end
def test_putpoi_invalid_latlon
end
def test_startchangeset_invalid_xmlchar_comment
invalid = "\035\022"
comment = "foo#{invalid}bar"
amf_content "startchangeset", "/1", ["test@example.com:test", Hash.new, nil, comment, 1]
post :amf_write
assert_response :success
amf_parse_response
result = amf_result("/1")
assert_equal 3, result.size, result.inspect
assert_equal 0, result[0]
new_cs_id = result[2].to_i
cs = Changeset.find(new_cs_id)
assert_equal "foobar", cs.tags["comment"]
end
# ************************************************************
# AMF Helper functions
# Get the result record for the specified ID
# It's an assertion FAIL if the record does not exist
def amf_result ref
assert @amf_result.has_key?("#{ref}/onResult")
@amf_result["#{ref}/onResult"]
end
# Encode the AMF message to invoke "target" with parameters as
# the passed data. The ref is used to retrieve the results.
def amf_content(target, ref, data)
a,b=1.divmod(256)
c = StringIO.new()
c.write 0.chr+0.chr # version 0
c.write 0.chr+0.chr # n headers
c.write a.chr+b.chr # n bodies
c.write AMF.encodestring(target)
c.write AMF.encodestring(ref)
c.write [-1].pack("N")
c.write AMF.encodevalue(data)
@request.env["RAW_POST_DATA"] = c.string
end
# Parses the @response object as an AMF messsage.
# The result is a hash of message_ref => data.
# The attribute @amf_result is initialised to this hash.
def amf_parse_response
req = StringIO.new(@response.body)
req.read(2) # version
# parse through any headers
headers=AMF.getint(req) # Read number of headers
headers.times do # Read each header
name=AMF.getstring(req) # |
req.getc # | skip boolean
value=AMF.getvalue(req) # |
end
# parse through responses
results = {}
bodies=AMF.getint(req) # Read number of bodies
bodies.times do # Read each body
message=AMF.getstring(req) # | get message name
index=AMF.getstring(req) # | get index in response sequence
bytes=AMF.getlong(req) # | get total size in bytes
args=AMF.getvalue(req) # | get response (probably an array)
results[message] = args
end
@amf_result = results
results
end
##
# given an array of bounding boxes (each an array of 4 floats), call the
# AMF "whichways" controller for each and pass the result back to the
# caller's block for assertion testing.
def check_bboxes_are_bad(bboxes)
bboxes.each do |bbox|
amf_content "whichways", "/1", bbox
post :amf_read
assert_response :success
amf_parse_response
# pass the response back to the caller's block to be tested
# against what the caller expected.
map = amf_result "/1"
yield map, bbox
end
end
# this should be what AMF controller returns when the bbox of a
# whichways request is invalid or too large.
def assert_boundary_error(map, msg=nil, error_hint=nil)
expected_map = [-2, "Sorry - I can't get the map for that area.#{msg}"]
assert_equal expected_map, map, "AMF controller should have returned an error. (#{error_hint})"
end
# this should be what AMF controller returns when the bbox of a
# whichways_deleted request is invalid or too large.
def assert_deleted_boundary_error(map, msg=nil, error_hint=nil)
expected_map = [-2, "Sorry - I can't get the map for that area.#{msg}"]
assert_equal expected_map, map, "AMF controller should have returned an error. (#{error_hint})"
end
end

View file

@ -0,0 +1,337 @@
require 'test_helper'
require 'api_controller'
class ApiControllerTest < ActionController::TestCase
api_fixtures
def setup
super
@badbigbbox = %w{ -0.1,-0.1,1.1,1.1 10,10,11,11 }
@badmalformedbbox = %w{ -0.1 hello
10N2W10.1N2.1W }
@badlatmixedbbox = %w{ 0,0.1,0.1,0 -0.1,80,0.1,70 0.24,54.34,0.25,54.33 }
@badlonmixedbbox = %w{ 80,-0.1,70,0.1 54.34,0.24,54.33,0.25 }
#@badlatlonoutboundsbbox = %w{ 191,-0.1,193,0.1 -190.1,89.9,-190,90 }
@goodbbox = %w{ -0.1,-0.1,0.1,0.1 51.1,-0.1,51.2,0
-0.1,%20-0.1,%200.1,%200.1 -0.1edcd,-0.1d,0.1,0.1 -0.1E,-0.1E,0.1S,0.1N S0.1,W0.1,N0.1,E0.1}
# That last item in the goodbbox really shouldn't be there, as the API should
# reall reject it, however this is to test to see if the api changes.
end
##
# test all routes which lead to this controller
def test_routes
assert_routing(
{ :path => "/api/capabilities", :method => :get },
{ :controller => "api", :action => "capabilities" }
)
assert_recognizes(
{ :controller => "api", :action => "capabilities" },
{ :path => "/api/0.6/capabilities", :method => :get }
)
assert_routing(
{ :path => "/api/0.6/permissions", :method => :get },
{ :controller => "api", :action => "permissions" }
)
assert_routing(
{ :path => "/api/0.6/map", :method => :get },
{ :controller => "api", :action => "map" }
)
assert_routing(
{ :path => "/api/0.6/trackpoints", :method => :get },
{ :controller => "api", :action => "trackpoints" }
)
assert_routing(
{ :path => "/api/0.6/changes", :method => :get },
{ :controller => "api", :action => "changes" }
)
end
# -------------------------------------
# Test reading a bounding box.
# -------------------------------------
def test_map
node = current_nodes(:used_node_1)
# Need to split the min/max lat/lon out into their own variables here
# so that we can test they are returned later.
minlon = node.lon-0.1
minlat = node.lat-0.1
maxlon = node.lon+0.1
maxlat = node.lat+0.1
bbox = "#{minlon},#{minlat},#{maxlon},#{maxlat}"
get :map, :bbox => bbox
if $VERBOSE
print @request.to_yaml
print @response.body
end
assert_response :success, "Expected scucess with the map call"
assert_select "osm[version='#{API_VERSION}'][generator='#{GENERATOR}']", :count => 1 do
assert_select "bounds[minlon=#{minlon}][minlat=#{minlat}][maxlon=#{maxlon}][maxlat=#{maxlat}]", :count => 1
assert_select "node[id=#{node.id}][lat=#{node.lat}][lon=#{node.lon}][version=#{node.version}][changeset=#{node.changeset_id}][visible=#{node.visible}][timestamp=#{node.timestamp.xmlschema}]", :count => 1 do
# This should really be more generic
assert_select "tag[k='test'][v='yes']"
end
# Should also test for the ways and relation
end
end
# This differs from the above test in that we are making the bbox exactly
# the same as the node we are looking at
def test_map_inclusive
node = current_nodes(:used_node_1)
bbox = "#{node.lon},#{node.lat},#{node.lon},#{node.lat}"
get :map, :bbox => bbox
assert_response :success, "The map call should have succeeded"
assert_select "osm[version='#{API_VERSION}'][generator='#{GENERATOR}']", :count => 1 do
assert_select "bounds[minlon=#{node.lon}][minlat=#{node.lat}][maxlon=#{node.lon}][maxlat=#{node.lat}]", :count => 1
assert_select "node[id=#{node.id}][lat=#{node.lat}][lon=#{node.lon}][version=#{node.version}][changeset=#{node.changeset_id}][visible=#{node.visible}][timestamp=#{node.timestamp.xmlschema}]", :count => 1 do
# This should really be more generic
assert_select "tag[k='test'][v='yes']"
end
# Should also test for the ways and relation
end
end
def test_tracepoints
point = gpx_files(:public_trace_file)
minlon = point.longitude-0.001
minlat = point.latitude-0.001
maxlon = point.longitude+0.001
maxlat = point.latitude+0.001
bbox = "#{minlon},#{minlat},#{maxlon},#{maxlat}"
get :trackpoints, :bbox => bbox
assert_response :success
assert_select "gpx[version=1.0][creator=OpenStreetMap.org][xmlns=http://www.topografix.com/GPX/1/0]", :count => 1 do
assert_select "trk" do
assert_select "trkseg"
end
end
end
def test_tracepoints_trackable
point = gpx_files(:trackable_trace_file)
minlon = point.longitude-0.002
minlat = point.latitude-0.002
maxlon = point.longitude+0.002
maxlat = point.latitude+0.002
bbox = "#{minlon},#{minlat},#{maxlon},#{maxlat}"
get :trackpoints, :bbox => bbox
assert_response :success
assert_select "gpx[version=1.0][creator=OpenStreetMap.org][xmlns=http://www.topografix.com/GPX/1/0]", :count => 1 do
assert_select "trk", :count => 1 do
assert_select "trk > trkseg", :count => 2 do |trksegs|
trksegs.each do |trkseg|
assert_select trkseg, "trkpt", :count => 1 do |trkpt|
assert_select trkpt[0], "time", :count => 1
end
end
end
end
end
end
def test_tracepoints_identifiable
point = gpx_files(:identifiable_trace_file)
minlon = point.longitude-0.002
minlat = point.latitude-0.002
maxlon = point.longitude+0.002
maxlat = point.latitude+0.002
bbox = "#{minlon},#{minlat},#{maxlon},#{maxlat}"
get :trackpoints, :bbox => bbox
assert_response :success
assert_select "gpx[version=1.0][creator=OpenStreetMap.org][xmlns=http://www.topografix.com/GPX/1/0]", :count => 1 do
assert_select "trk", :count => 1 do
assert_select "trk>name", :count => 1
assert_select "trk>desc", :count => 1
assert_select "trk>url", :count => 1
assert_select "trkseg", :count => 1 do
assert_select "trkpt", :count => 1 do
assert_select "time", :count => 1
end
end
end
end
end
def test_map_without_bbox
["trackpoints", "map"].each do |tq|
get tq
assert_response :bad_request
assert_equal "The parameter bbox is required, and must be of the form min_lon,min_lat,max_lon,max_lat", @response.body, "A bbox param was expected"
end
end
def test_traces_page_less_than_0
-10.upto(-1) do |i|
get :trackpoints, :page => i, :bbox => "-0.1,-0.1,0.1,0.1"
assert_response :bad_request
assert_equal "Page number must be greater than or equal to 0", @response.body, "The page number was #{i}"
end
0.upto(10) do |i|
get :trackpoints, :page => i, :bbox => "-0.1,-0.1,0.1,0.1"
assert_response :success, "The page number was #{i} and should have been accepted"
end
end
def test_bbox_too_big
@badbigbbox.each do |bbox|
[ "trackpoints", "map" ].each do |tq|
get tq, :bbox => bbox
assert_response :bad_request, "The bbox:#{bbox} was expected to be too big"
assert_equal "The maximum bbox size is #{MAX_REQUEST_AREA}, and your request was too large. Either request a smaller area, or use planet.osm", @response.body, "bbox: #{bbox}"
end
end
end
def test_bbox_malformed
@badmalformedbbox.each do |bbox|
[ "trackpoints", "map" ].each do |tq|
get tq, :bbox => bbox
assert_response :bad_request, "The bbox:#{bbox} was expected to be malformed"
assert_equal "The parameter bbox is required, and must be of the form min_lon,min_lat,max_lon,max_lat", @response.body, "bbox: #{bbox}"
end
end
end
def test_bbox_lon_mixedup
@badlonmixedbbox.each do |bbox|
[ "trackpoints", "map" ].each do |tq|
get tq, :bbox => bbox
assert_response :bad_request, "The bbox:#{bbox} was expected to have the longitude mixed up"
assert_equal "The minimum longitude must be less than the maximum longitude, but it wasn't", @response.body, "bbox: #{bbox}"
end
end
end
def test_bbox_lat_mixedup
@badlatmixedbbox.each do |bbox|
["trackpoints", "map"].each do |tq|
get tq, :bbox => bbox
assert_response :bad_request, "The bbox:#{bbox} was expected to have the latitude mixed up"
assert_equal "The minimum latitude must be less than the maximum latitude, but it wasn't", @response.body, "bbox: #{bbox}"
end
end
end
# We can't actually get an out of bounds error, as the bbox is sanitised.
#def test_latlon_outofbounds
# @badlatlonoutboundsbbox.each do |bbox|
# [ "trackpoints", "map" ].each do |tq|
# get tq, :bbox => bbox
# #print @request.to_yaml
# assert_response :bad_request, "The bbox #{bbox} was expected to be out of range"
# assert_equal "The latitudes must be between -90 an 90, and longitudes between -180 and 180", @response.body, "bbox: #{bbox}"
# end
# end
#end
# MySQL and Postgres require that the C based functions are installed for
# this test to work. More information is available from:
# http://wiki.openstreetmap.org/wiki/Rails#Installing_the_quadtile_functions
# or by looking at the readme in db/README
def test_changes_simple
Timecop.freeze(Time.parse('2010-04-03 10:55:00'))
get :changes
assert_response :success
#print @response.body
# As we have loaded the fixtures, we can assume that there are no
# changes at the time we have frozen at
now = Time.now.getutc
hourago = now - 1.hour
assert_select "osm[version='#{API_VERSION}'][generator='#{GENERATOR}']", :count => 1 do
assert_select "changes[starttime='#{hourago.xmlschema}'][endtime='#{now.xmlschema}']", :count => 1
end
Timecop.return
end
def test_changes_zoom_invalid
zoom_to_test = %w{ p -1 0 17 one two }
zoom_to_test.each do |zoom|
get :changes, :zoom => zoom
assert_response :bad_request
assert_equal @response.body, "Requested zoom is invalid, or the supplied start is after the end time, or the start duration is more than 24 hours"
end
end
def test_changes_zoom_valid
1.upto(16) do |zoom|
get :changes, :zoom => zoom
assert_response :success
# NOTE: there was a test here for the timing, but it was too sensitive to be a good test
# and it was annoying.
assert_select "osm[version='#{API_VERSION}'][generator='#{GENERATOR}']", :count => 1 do
assert_select "changes", :count => 1
end
end
end
def test_hours_invalid
invalid = %w{ -21 335 -1 0 25 26 100 one two three ping pong : }
invalid.each do |hour|
get :changes, :hours => hour
assert_response :bad_request, "Problem with the hour: #{hour}"
assert_equal @response.body, "Requested zoom is invalid, or the supplied start is after the end time, or the start duration is more than 24 hours", "Problem with the hour: #{hour}."
end
end
def test_hours_valid
1.upto(24) do |hour|
get :changes, :hours => hour
assert_response :success
end
end
def test_capabilities
get :capabilities
assert_response :success
assert_select "osm[version='#{API_VERSION}'][generator='#{GENERATOR}']", :count => 1 do
assert_select "api", :count => 1 do
assert_select "version[minimum=#{API_VERSION}][maximum=#{API_VERSION}]", :count => 1
assert_select "area[maximum=#{MAX_REQUEST_AREA}]", :count => 1
assert_select "tracepoints[per_page=#{TRACEPOINTS_PER_PAGE}]", :count => 1
assert_select "changesets[maximum_elements=#{Changeset::MAX_ELEMENTS}]", :count => 1
assert_select "status[database=online]", :count => 1
assert_select "status[api=online]", :count => 1
assert_select "status[gpx=online]", :count => 1
end
end
end
def test_permissions_anonymous
get :permissions
assert_response :success
assert_select "osm > permissions", :count => 1 do
assert_select "permission", :count => 0
end
end
def test_permissions_basic_auth
basic_authorization(users(:normal_user).email, "test")
get :permissions
assert_response :success
assert_select "osm > permissions", :count => 1 do
assert_select "permission", :count => ClientApplication.all_permissions.size
ClientApplication.all_permissions.each do |p|
assert_select "permission[name=#{p}]", :count => 1
end
end
end
def test_permissions_oauth
@request.env["oauth.token"] = AccessToken.new do |token|
# Just to test a few
token.allow_read_prefs = true
token.allow_write_api = true
token.allow_read_gpx = false
end
get :permissions
assert_response :success
assert_select "osm > permissions", :count => 1 do
assert_select "permission", :count => 2
assert_select "permission[name=allow_read_prefs]", :count => 1
assert_select "permission[name=allow_write_api]", :count => 1
assert_select "permission[name=allow_read_gpx]", :count => 0
end
end
end

View file

@ -0,0 +1,163 @@
require 'test_helper'
require 'browse_controller'
class BrowseControllerTest < ActionController::TestCase
api_fixtures
##
# test all routes which lead to this controller
def test_routes
assert_routing(
{ :path => "/node/1", :method => :get },
{ :controller => "browse", :action => "node", :id => "1" }
)
assert_routing(
{ :path => "/node/1/history", :method => :get },
{ :controller => "browse", :action => "node_history", :id => "1" }
)
assert_routing(
{ :path => "/way/1", :method => :get },
{ :controller => "browse", :action => "way", :id => "1" }
)
assert_routing(
{ :path => "/way/1/history", :method => :get },
{ :controller => "browse", :action => "way_history", :id => "1" }
)
assert_routing(
{ :path => "/relation/1", :method => :get },
{ :controller => "browse", :action => "relation", :id => "1" }
)
assert_routing(
{ :path => "/relation/1/history", :method => :get },
{ :controller => "browse", :action => "relation_history", :id => "1" }
)
assert_routing(
{ :path => "/changeset/1", :method => :get },
{ :controller => "browse", :action => "changeset", :id => "1" }
)
assert_routing(
{ :path => "/note/1", :method => :get },
{ :controller => "browse", :action => "note", :id => "1" }
)
assert_routing(
{ :path => "/note/new", :method => :get },
{ :controller => "browse", :action => "new_note" }
)
end
def test_read_relation
browse_check 'relation', relations(:visible_relation).relation_id, 'browse/feature'
end
def test_read_relation_history
browse_check 'relation_history', relations(:visible_relation).relation_id, 'browse/history'
end
def test_read_way
browse_check 'way', ways(:visible_way).way_id, 'browse/feature'
end
def test_read_way_history
browse_check 'way_history', ways(:visible_way).way_id, 'browse/history'
end
def test_read_node
browse_check 'node', nodes(:visible_node).node_id, 'browse/feature'
end
def test_read_node_history
browse_check 'node_history', nodes(:visible_node).node_id, 'browse/history'
end
def test_read_changeset
browse_check 'changeset', changesets(:normal_user_first_change).id, 'browse/changeset'
end
def test_read_note
browse_check 'note', notes(:open_note).id, 'browse/note'
end
##
# Methods to check redaction.
#
# note that these are presently highly reliant on the structure of the
# page for the selection tests, which doesn't work out particularly
# well if that structure changes. so... if you change the page layout
# then please make it more easily (and robustly) testable!
##
def test_redacted_node
get :node, :id => current_nodes(:redacted_node).id
assert_response :success
assert_template "feature"
# check that we don't show lat/lon for a redacted node.
assert_select ".browse-section", 1
assert_select ".browse-section.browse-node", 1
assert_select ".browse-section.browse-node .latitude", 0
assert_select ".browse-section.browse-node .longitude", 0
end
def test_redacted_node_history
get :node_history, :id => nodes(:redacted_node_redacted_version).node_id
assert_response :success
assert_template "browse/history"
# there are 2 revisions of the redacted node, but only one
# should be showing details here.
assert_select ".browse-section", 2
assert_select ".browse-section.browse-redacted", 1
assert_select ".browse-section.browse-node", 1
assert_select ".browse-section.browse-node .latitude", 0
assert_select ".browse-section.browse-node .longitude", 0
end
def test_redacted_way_history
get :way_history, :id => ways(:way_with_redacted_versions_v1).way_id
assert_response :success
assert_template 'browse/history'
# there are 4 revisions of the redacted way, but only 2
# should be showing details here.
assert_select ".browse-section", 4
assert_select ".browse-section.browse-redacted", 2
assert_select ".browse-section.browse-way", 2
end
def test_redacted_relation_history
get :relation_history, :id => relations(:relation_with_redacted_versions_v1).relation_id
assert_response :success
assert_template 'browse/history'
# there are 4 revisions of the redacted relation, but only 2
# should be showing details here.
assert_select ".browse-section", 4
assert_select ".browse-section.browse-redacted", 2
assert_select ".browse-section.browse-relation", 2
end
private
# This is a convenience method for most of the above checks
# First we check that when we don't have an id, it will correctly return a 404
# then we check that we get the correct 404 when a non-existant id is passed
# then we check that it will get a successful response, when we do pass an id
def browse_check(type, id, template)
assert_raise ActionController::UrlGenerationError do
get type
end
assert_raise ActionController::UrlGenerationError do
get type, {:id => -10} # we won't have an id that's negative
end
get type, {:id => id}
assert_response :success
assert_template template
assert_template :layout => "map"
xhr :get, type, {:id => id}
assert_response :success
assert_template template
assert_template :layout => "xhr"
end
end

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,467 @@
require 'test_helper'
class DiaryEntryControllerTest < ActionController::TestCase
fixtures :users, :diary_entries, :diary_comments, :languages
include ActionView::Helpers::NumberHelper
##
# test all routes which lead to this controller
def test_routes
assert_routing(
{ :path => "/diary", :method => :get },
{ :controller => "diary_entry", :action => "list" }
)
assert_routing(
{ :path => "/diary/language", :method => :get },
{ :controller => "diary_entry", :action => "list", :language => "language" }
)
assert_routing(
{ :path => "/user/username/diary", :method => :get },
{ :controller => "diary_entry", :action => "list", :display_name => "username" }
)
assert_routing(
{ :path => "/diary/friends", :method => :get },
{ :controller => "diary_entry", :action => "list", :friends => true }
)
assert_routing(
{ :path => "/diary/nearby", :method => :get },
{ :controller => "diary_entry", :action => "list", :nearby => true }
)
assert_routing(
{ :path => "/diary/rss", :method => :get },
{ :controller => "diary_entry", :action => "rss", :format => :rss }
)
assert_routing(
{ :path => "/diary/language/rss", :method => :get },
{ :controller => "diary_entry", :action => "rss", :language => "language", :format => :rss }
)
assert_routing(
{ :path => "/user/username/diary/rss", :method => :get },
{ :controller => "diary_entry", :action => "rss", :display_name => "username", :format => :rss }
)
assert_routing(
{ :path => "/user/username/diary/comments", :method => :get },
{ :controller => "diary_entry", :action => "comments", :display_name => "username" }
)
assert_routing(
{ :path => "/user/username/diary/comments/1", :method => :get },
{ :controller => "diary_entry", :action => "comments", :display_name => "username", :page => "1" }
)
assert_routing(
{ :path => "/diary/new", :method => :get },
{ :controller => "diary_entry", :action => "new" }
)
assert_routing(
{ :path => "/diary/new", :method => :post },
{ :controller => "diary_entry", :action => "new" }
)
assert_routing(
{ :path => "/user/username/diary/1", :method => :get },
{ :controller => "diary_entry", :action => "view", :display_name => "username", :id => "1" }
)
assert_routing(
{ :path => "/user/username/diary/1/edit", :method => :get },
{ :controller => "diary_entry", :action => "edit", :display_name => "username", :id => "1" }
)
assert_routing(
{ :path => "/user/username/diary/1/edit", :method => :post },
{ :controller => "diary_entry", :action => "edit", :display_name => "username", :id => "1" }
)
assert_routing(
{ :path => "/user/username/diary/1/newcomment", :method => :post },
{ :controller => "diary_entry", :action => "comment", :display_name => "username", :id => "1" }
)
assert_routing(
{ :path => "/user/username/diary/1/hide", :method => :post },
{ :controller => "diary_entry", :action => "hide", :display_name => "username", :id => "1" }
)
assert_routing(
{ :path => "/user/username/diary/1/hidecomment/2", :method => :post },
{ :controller => "diary_entry", :action => "hidecomment", :display_name => "username", :id => "1", :comment => "2" }
)
end
def test_showing_new_diary_entry
get :new
assert_response :redirect
assert_redirected_to :controller => :user, :action => "login", :referer => "/diary/new"
# Now pretend to login by using the session hash, with the
# id of the person we want to login as through session(:user)=user.id
get(:new, nil, {'user' => users(:normal_user).id})
assert_response :success
#print @response.body
#print @response.to_yaml
assert_select "title", :text => /New Diary Entry/, :count => 1
assert_select "div.content-heading", :count => 1 do
assert_select "h1", :text => "New Diary Entry", :count => 1
end
assert_select "div#content", :count => 1 do
# We don't care about the layout, we just care about the form fields
# that are available
assert_select "form[action='/diary/new']", :count => 1 do
assert_select "input[id=diary_entry_title][name='diary_entry[title]']", :count => 1
assert_select "textarea#diary_entry_body[name='diary_entry[body]']", :count => 1
assert_select "input#latitude[name='diary_entry[latitude]'][type=text]", :count => 1
assert_select "input#longitude[name='diary_entry[longitude]'][type=text]", :count => 1
assert_select "input[name=commit][type=submit][value=Save]", :count => 1
end
end
end
def test_editing_diary_entry
entry = diary_entries(:normal_user_entry_1)
# Make sure that you are redirected to the login page when you are
# not logged in, without and with the id of the entry you want to edit
get :edit, :display_name => entry.user.display_name, :id => entry.id
assert_response :redirect
assert_redirected_to :controller => :user, :action => "login", :referer => "/user/#{entry.user.display_name}/diary/#{entry.id}/edit"
# Verify that you get a not found error, when you pass a bogus id
get(:edit, {:display_name => entry.user.display_name, :id => 9999}, {'user' => entry.user.id})
assert_response :not_found
assert_select "div.content-heading", :count => 1 do
assert_select "h2", :text => "No entry with the id: 9999", :count => 1
end
# Now pass the id, and check that you can edit it, when using the same
# user as the person who created the entry
get(:edit, {:display_name => entry.user.display_name, :id => entry.id}, {'user' => entry.user.id})
assert_response :success
assert_select "title", :text => /Edit diary entry/, :count => 1
assert_select "div.content-heading", :count => 1 do
assert_select "h1", :text => /Edit diary entry/, :count => 1
end
assert_select "div#content", :count => 1 do
assert_select "form[action='/user/#{entry.user.display_name}/diary/#{entry.id}/edit'][method=post]", :count => 1 do
assert_select "input#diary_entry_title[name='diary_entry[title]'][value='#{entry.title}']", :count => 1
assert_select "textarea#diary_entry_body[name='diary_entry[body]']", :text => entry.body, :count => 1
assert_select "select#diary_entry_language_code", :count => 1
assert_select "input#latitude[name='diary_entry[latitude]']", :count => 1
assert_select "input#longitude[name='diary_entry[longitude]']", :count => 1
assert_select "input[name=commit][type=submit][value=Save]", :count => 1
assert_select "input[name=commit][type=submit][value=Edit]", :count => 1
assert_select "input[name=commit][type=submit][value=Preview]", :count => 1
assert_select "input", :count => 7
end
end
# Now lets see if you can edit the diary entry
new_title = "New Title"
new_body = "This is a new body for the diary entry"
new_latitude = "1.1"
new_longitude = "2.2"
new_language_code = "en"
post(:edit, {:display_name => entry.user.display_name, :id => entry.id, 'commit' => 'save',
'diary_entry'=>{'title' => new_title, 'body' => new_body, 'latitude' => new_latitude,
'longitude' => new_longitude, 'language_code' => new_language_code} },
{'user' => entry.user.id})
assert_response :redirect
assert_redirected_to :action => :view, :display_name => entry.user.display_name, :id => entry.id
# Now check that the new data is rendered, when logged in
get :view, {:display_name => entry.user.display_name, :id => entry.id}, {'user' => entry.user.id}
assert_response :success
assert_template 'diary_entry/view'
assert_select "title", :text => /Users' diaries | /, :count => 1
assert_select "div.content-heading", :count => 1 do
assert_select "h2", :text => /#{entry.user.display_name}&#39;s diary/, :count => 1
end
assert_select "div#content", :count => 1 do
assert_select "div.post_heading", :text => /#{new_title}/, :count => 1
# This next line won't work if the text has been run through the htmlize function
# due to formatting that could be introduced
assert_select "p", :text => /#{new_body}/, :count => 1
assert_select "abbr[class=geo][title=#{number_with_precision(new_latitude, :precision => 4)}; #{number_with_precision(new_longitude, :precision => 4)}]", :count => 1
# As we're not logged in, check that you cannot edit
#print @response.body
assert_select "a[href='/user/#{entry.user.display_name}/diary/#{entry.id}/edit']", :text => "Edit this entry", :count => 1
end
# and when not logged in as the user who wrote the entry
get :view, {:display_name => entry.user.display_name, :id => entry.id}, {'user' => entry.user.id}
assert_response :success
assert_template 'diary_entry/view'
assert_select "title", :text => /Users' diaries | /, :count => 1
assert_select "div.content-heading", :count => 1 do
assert_select "h2", :text => /#{users(:normal_user).display_name}&#39;s diary/, :count => 1
end
assert_select "div#content", :count => 1 do
assert_select "div.post_heading", :text => /#{new_title}/, :count => 1
# This next line won't work if the text has been run through the htmlize function
# due to formatting that could be introduced
assert_select "p", :text => /#{new_body}/, :count => 1
assert_select "abbr[class=geo][title=#{number_with_precision(new_latitude, :precision => 4)}; #{number_with_precision(new_longitude, :precision => 4)}]", :count => 1
# As we're not logged in, check that you cannot edit
assert_select "li[class=hidden show_if_user_#{entry.user.id}]", :count => 1 do
assert_select "a[href='/user/#{entry.user.display_name}/diary/#{entry.id}/edit']", :text => "Edit this entry", :count => 1
end
end
end
def test_edit_diary_entry_i18n
get :edit, {:display_name => users(:normal_user).display_name, :id => diary_entries(:normal_user_entry_1).id}, {'user' => users(:normal_user).id}
assert_response :success
assert_select "span[class=translation_missing]", false, "Missing translation in edit diary entry"
end
def test_create_diary_entry
# Make sure that you are redirected to the login page when you
# are not logged in
get :new
assert_response :redirect
assert_redirected_to :controller => :user, :action => :login, :referer => "/diary/new"
# Now try again when logged in
get :new, {}, {:user => users(:normal_user).id}
assert_response :success
assert_select "title", :text => /New Diary Entry/, :count => 1
assert_select "div.content-heading", :count => 1 do
assert_select "h1", :text => /New Diary Entry/, :count => 1
end
assert_select "div#content", :count => 1 do
assert_select "form[action='/diary/new'][method=post]", :count => 1 do
assert_select "input#diary_entry_title[name='diary_entry[title]']", :count => 1
assert_select "textarea#diary_entry_body[name='diary_entry[body]']", :text => "", :count => 1
assert_select "select#diary_entry_language_code", :count => 1
assert_select "input#latitude[name='diary_entry[latitude]']", :count => 1
assert_select "input#longitude[name='diary_entry[longitude]']", :count => 1
assert_select "input[name=commit][type=submit][value=Save]", :count => 1
assert_select "input[name=commit][type=submit][value=Edit]", :count => 1
assert_select "input[name=commit][type=submit][value=Preview]", :count => 1
assert_select "input", :count => 7
end
end
# Now try creating a diary entry
new_title = "New Title"
new_body = "This is a new body for the diary entry"
new_latitude = "1.1"
new_longitude = "2.2"
new_language_code = "en"
assert_difference "DiaryEntry.count", 1 do
post(:new, {'commit' => 'save',
'diary_entry'=>{'title' => new_title, 'body' => new_body, 'latitude' => new_latitude,
'longitude' => new_longitude, 'language_code' => new_language_code} },
{:user => users(:normal_user).id})
end
assert_response :redirect
assert_redirected_to :action => :list, :display_name => users(:normal_user).display_name
entry = DiaryEntry.find(6)
assert_equal users(:normal_user).id, entry.user_id
assert_equal new_title, entry.title
assert_equal new_body, entry.body
assert_equal new_latitude.to_f, entry.latitude
assert_equal new_longitude.to_f, entry.longitude
assert_equal new_language_code, entry.language_code
end
def test_creating_diary_comment
entry = diary_entries(:normal_user_entry_1)
# Make sure that you are denied when you are not logged in
post :comment, :display_name => entry.user.display_name, :id => entry.id
assert_response :forbidden
# Verify that you get a not found error, when you pass a bogus id
post :comment, {:display_name => entry.user.display_name, :id => 9999}, {:user => users(:public_user).id}
assert_response :not_found
assert_select "div.content-heading", :count => 1 do
assert_select "h2", :text => "No entry with the id: 9999", :count => 1
end
# Now try again with the right id
assert_difference "ActionMailer::Base.deliveries.size", 1 do
assert_difference "DiaryComment.count", 1 do
post :comment, {:display_name => entry.user.display_name, :id => entry.id, :diary_comment => {:body => "New comment"}}, {:user => users(:public_user).id}
end
end
assert_response :redirect
assert_redirected_to :action => :view, :display_name => entry.user.display_name, :id => entry.id
email = ActionMailer::Base.deliveries.first
assert_equal [ users(:normal_user).email ], email.to
assert_equal "[OpenStreetMap] #{users(:public_user).display_name} commented on your diary entry", email.subject
assert_match /New comment/, email.text_part.decoded
assert_match /New comment/, email.html_part.decoded
ActionMailer::Base.deliveries.clear
comment = DiaryComment.find(5)
assert_equal entry.id, comment.diary_entry_id
assert_equal users(:public_user).id, comment.user_id
assert_equal "New comment", comment.body
# Now view the diary entry, and check the new comment is present
get :view, :display_name => entry.user.display_name, :id => entry.id
assert_response :success
assert_select ".diary-comment", :count => 1 do
assert_select "#comment5", :count => 1 do
assert_select "a[href='/user/#{users(:public_user).display_name}']", :text => users(:public_user).display_name, :count => 1
end
assert_select ".richtext", :text => /New comment/, :count => 1
end
end
# Check that you can get the expected response and template for all available languages
# Should test that there are no <span class="translation_missing">
def test_listing_diary_entries
get :list
assert_response :success, "Should be able to list the diary entries in locale"
assert_template 'list', "Should use the list template in locale"
assert_select "span[class=translation_missing]", false, "Missing translation in list of diary entries"
# Now try to find a specific user's diary entry
get :list, {:display_name => users(:normal_user).display_name}
assert_response :success, "Should be able to list the diary entries for a user in locale"
assert_template 'list', "Should use the list template for a user in locale"
assert_no_missing_translations
end
def test_rss
get :rss, {:format => :rss}
assert_response :success, "Should be able to get a diary RSS"
assert_select "rss", :count => 1 do
assert_select "channel", :count => 1 do
assert_select "channel>title", :count => 1
assert_select "image", :count => 1
assert_select "channel>item", :count => 2
end
end
end
def test_rss_language
get :rss, {:language => diary_entries(:normal_user_entry_1).language_code, :format => :rss}
assert_response :success, "Should be able to get a specific language diary RSS"
assert_select "rss>channel>item", :count => 1 #, "Diary entries should be filtered by language"
end
# def test_rss_nonexisting_language
# get :rss, {:language => 'xx', :format => :rss}
# assert_response :not_found, "Should not be able to get a nonexisting language diary RSS"
# end
def test_rss_language_with_no_entries
get :rss, {:language => 'sl', :format => :rss}
assert_response :success, "Should be able to get a specific language diary RSS"
assert_select "rss>channel>item", :count => 0 #, "Diary entries should be filtered by language"
end
def test_rss_user
get :rss, {:display_name => users(:normal_user).display_name, :format => :rss}
assert_response :success, "Should be able to get a specific users diary RSS"
assert_select "rss>channel>item", :count => 2 #, "Diary entries should be filtered by user"
end
def test_rss_nonexisting_user
# Try a user that has never existed
get :rss, {:display_name => 'fakeUsername76543', :format => :rss}
assert_response :not_found, "Should not be able to get a nonexisting users diary RSS"
# Try a suspended user
get :rss, {:display_name => users(:suspended_user).display_name, :format => :rss}
assert_response :not_found, "Should not be able to get a suspended users diary RSS"
# Try a deleted user
get :rss, {:display_name => users(:deleted_user).display_name, :format => :rss}
assert_response :not_found, "Should not be able to get a deleted users diary RSS"
end
def test_viewing_diary_entry
# Try a normal entry that should work
get :view, {:display_name => users(:normal_user).display_name, :id => diary_entries(:normal_user_entry_1).id}
assert_response :success
assert_template :view
# Try a deleted entry
get :view, {:display_name => users(:normal_user).display_name, :id => diary_entries(:deleted_entry).id}
assert_response :not_found
# Try an entry by a suspended user
get :view, {:display_name => users(:suspended_user).display_name, :id => diary_entries(:entry_by_suspended_user).id}
assert_response :not_found
# Try an entry by a deleted user
get :view, {:display_name => users(:deleted_user).display_name, :id => diary_entries(:entry_by_deleted_user).id}
assert_response :not_found
end
def test_viewing_hidden_comments
# Get a diary entry that has hidden comments
get :view, {:display_name => users(:normal_user).display_name, :id => diary_entries(:normal_user_geo_entry).id}
assert_response :success
assert_template :view
assert_select "div.comments" do
assert_select "p#comment1", :count => 1 # visible comment
assert_select "p#comment2", :count => 0 # comment by suspended user
assert_select "p#comment3", :count => 0 # comment by deleted user
assert_select "p#comment4", :count => 0 # hidden comment
end
end
def test_hide
# Try without logging in
post :hide, {:display_name => users(:normal_user).display_name, :id => diary_entries(:normal_user_entry_1).id}
assert_response :forbidden
assert_equal true, DiaryEntry.find(diary_entries(:normal_user_entry_1).id).visible
# Now try as a normal user
post :hide, {:display_name => users(:normal_user).display_name, :id => diary_entries(:normal_user_entry_1).id}, {:user => users(:normal_user).id}
assert_response :redirect
assert_redirected_to :action => :view, :display_name => users(:normal_user).display_name, :id => diary_entries(:normal_user_entry_1).id
assert_equal true, DiaryEntry.find(diary_entries(:normal_user_entry_1).id).visible
# Finally try as an administrator
post :hide, {:display_name => users(:normal_user).display_name, :id => diary_entries(:normal_user_entry_1).id}, {:user => users(:administrator_user).id}
assert_response :redirect
assert_redirected_to :action => :list, :display_name => users(:normal_user).display_name
assert_equal false, DiaryEntry.find(diary_entries(:normal_user_entry_1).id).visible
end
def test_hidecomment
# Try without logging in
post :hidecomment, {:display_name => users(:normal_user).display_name, :id => diary_entries(:normal_user_geo_entry).id, :comment => diary_comments(:comment_for_geo_post).id}
assert_response :forbidden
assert_equal true, DiaryComment.find(diary_comments(:comment_for_geo_post).id).visible
# Now try as a normal user
post :hidecomment, {:display_name => users(:normal_user).display_name, :id => diary_entries(:normal_user_geo_entry).id, :comment => diary_comments(:comment_for_geo_post).id}, {:user => users(:normal_user).id}
assert_response :redirect
assert_redirected_to :action => :view, :display_name => users(:normal_user).display_name, :id => diary_entries(:normal_user_geo_entry).id
assert_equal true, DiaryComment.find(diary_comments(:comment_for_geo_post).id).visible
# Finally try as an administrator
post :hidecomment, {:display_name => users(:normal_user).display_name, :id => diary_entries(:normal_user_geo_entry).id, :comment => diary_comments(:comment_for_geo_post).id}, {:user => users(:administrator_user).id}
assert_response :redirect
assert_redirected_to :action => :view, :display_name => users(:normal_user).display_name, :id => diary_entries(:normal_user_geo_entry).id
assert_equal false, DiaryComment.find(diary_comments(:comment_for_geo_post).id).visible
end
def test_comments
# Test a user with no comments
get :comments, :display_name => users(:normal_user).display_name
assert_response :success
assert_template :comments
assert_select "table.messages" do
assert_select "tr", :count => 1 # header, no comments
end
# Test a user with a comment
get :comments, :display_name => users(:public_user).display_name
assert_response :success
assert_template :comments
assert_select "table.messages" do
assert_select "tr", :count => 2 # header and one comment
end
# Test a suspended user
get :comments, :display_name => users(:suspended_user).display_name
assert_response :not_found
# Test a deleted user
get :comments, :display_name => users(:deleted_user).display_name
assert_response :not_found
end
end

View file

@ -0,0 +1,42 @@
require 'test_helper'
class ExportControllerTest < ActionController::TestCase
##
# test all routes which lead to this controller
def test_routes
assert_routing(
{ :path => "/export/finish", :method => :post },
{ :controller => "export", :action => "finish" }
)
assert_routing(
{ :path => "/export/embed", :method => :get },
{ :controller => "export", :action => "embed" }
)
end
###
# test the finish action for raw OSM data
def test_finish_osm
get :finish, {:minlon => 0, :minlat => 50, :maxlon => 1, :maxlat => 51, :format => 'osm'}
assert_response :redirect
assert_redirected_to "http://api.openstreetmap.org/api/#{API_VERSION}/map?bbox=0.0,50.0,1.0,51.0"
end
###
# test the finish action for mapnik images
def test_finish_mapnik
get :finish, {:minlon => 0, :minlat => 50, :maxlon => 1, :maxlat => 51, :format => 'mapnik', :mapnik_format => 'test', :mapnik_scale => '12'}
assert_response :redirect
assert_redirected_to "http://render.openstreetmap.org/cgi-bin/export?bbox=0.0,50.0,1.0,51.0&scale=12&format=test"
end
##
# test the embed action
def test_embed
get :embed
assert_response :success
assert_template "export/embed"
end
end

View file

@ -0,0 +1,312 @@
# coding: utf-8
require 'test_helper'
require 'geocoder_controller'
class GeocoderControllerTest < ActionController::TestCase
##
# test all routes which lead to this controller
def test_routes
assert_routing(
{ :path => "/search", :method => :get },
{ :controller => "geocoder", :action => "search" }
)
assert_routing(
{ :path => "/geocoder/search_latlon", :method => :get },
{ :controller => "geocoder", :action => "search_latlon" }
)
assert_routing(
{ :path => "/geocoder/search_us_postcode", :method => :get },
{ :controller => "geocoder", :action => "search_us_postcode" }
)
assert_routing(
{ :path => "/geocoder/search_uk_postcode", :method => :get },
{ :controller => "geocoder", :action => "search_uk_postcode" }
)
assert_routing(
{ :path => "/geocoder/search_ca_postcode", :method => :get },
{ :controller => "geocoder", :action => "search_ca_postcode" }
)
assert_routing(
{ :path => "/geocoder/search_osm_nominatim", :method => :get },
{ :controller => "geocoder", :action => "search_osm_nominatim" }
)
assert_routing(
{ :path => "/geocoder/search_geonames", :method => :get },
{ :controller => "geocoder", :action => "search_geonames" }
)
assert_routing(
{ :path => "/geocoder/search_osm_nominatim_reverse", :method => :get },
{ :controller => "geocoder", :action => "search_osm_nominatim_reverse" }
)
assert_routing(
{ :path => "/geocoder/search_geonames_reverse", :method => :get },
{ :controller => "geocoder", :action => "search_geonames_reverse" }
)
end
##
# Test identification of basic lat/lon pairs
def test_identify_latlon_basic
[
'50.06773 14.37742',
'50.06773, 14.37742',
'+50.06773 +14.37742',
'+50.06773, +14.37742'
].each do |code|
latlon_check code, 50.06773, 14.37742
end
end
##
# Test identification of lat/lon pairs using N/E with degrees
def test_identify_latlon_ne_d
[
'N50.06773 E14.37742',
'N50.06773, E14.37742',
'50.06773N 14.37742E',
'50.06773N, 14.37742E'
].each do |code|
latlon_check code, 50.06773, 14.37742
end
end
##
# Test identification of lat/lon pairs using N/W with degrees
def test_identify_latlon_nw_d
[
'N50.06773 W14.37742',
'N50.06773, W14.37742',
'50.06773N 14.37742W',
'50.06773N, 14.37742W'
].each do |code|
latlon_check code, 50.06773, -14.37742
end
end
##
# Test identification of lat/lon pairs using S/E with degrees
def test_identify_latlon_se_d
[
'S50.06773 E14.37742',
'S50.06773, E14.37742',
'50.06773S 14.37742E',
'50.06773S, 14.37742E'
].each do |code|
latlon_check code, -50.06773, 14.37742
end
end
##
# Test identification of lat/lon pairs using S/W with degrees
def test_identify_latlon_sw_d
[
'S50.06773 W14.37742',
'S50.06773, W14.37742',
'50.06773S 14.37742W',
'50.06773S, 14.37742W'
].each do |code|
latlon_check code, -50.06773, -14.37742
end
end
##
# Test identification of lat/lon pairs using N/E with degrees/mins
def test_identify_latlon_ne_dm
[
'N 50° 04.064 E 014° 22.645',
"N 50° 04.064' E 014° 22.645",
"N 50° 04.064', E 014° 22.645'",
'N50° 04.064 E14° 22.645',
'N 50 04.064 E 014 22.645',
'N50 4.064 E14 22.645',
"50° 04.064' N, 014° 22.645' E"
].each do |code|
latlon_check code, 50.06773, 14.37742
end
end
##
# Test identification of lat/lon pairs using N/W with degrees/mins
def test_identify_latlon_nw_dm
[
'N 50° 04.064 W 014° 22.645',
"N 50° 04.064' W 014° 22.645",
"N 50° 04.064', W 014° 22.645'",
'N50° 04.064 W14° 22.645',
'N 50 04.064 W 014 22.645',
'N50 4.064 W14 22.645',
"50° 04.064' N, 014° 22.645' W"
].each do |code|
latlon_check code, 50.06773, -14.37742
end
end
##
# Test identification of lat/lon pairs using S/E with degrees/mins
def test_identify_latlon_se_dm
[
'S 50° 04.064 E 014° 22.645',
"S 50° 04.064' E 014° 22.645",
"S 50° 04.064', E 014° 22.645'",
'S50° 04.064 E14° 22.645',
'S 50 04.064 E 014 22.645',
'S50 4.064 E14 22.645',
"50° 04.064' S, 014° 22.645' E"
].each do |code|
latlon_check code, -50.06773, 14.37742
end
end
##
# Test identification of lat/lon pairs using S/W with degrees/mins
def test_identify_latlon_sw_dm
[
'S 50° 04.064 W 014° 22.645',
"S 50° 04.064' W 014° 22.645",
"S 50° 04.064', W 014° 22.645'",
'S50° 04.064 W14° 22.645',
'S 50 04.064 W 014 22.645',
'S50 4.064 W14 22.645',
"50° 04.064' S, 014° 22.645' W"
].each do |code|
latlon_check code, -50.06773, -14.37742
end
end
##
# Test identification of lat/lon pairs using N/E with degrees/mins/secs
def test_identify_latlon_ne_dms
[
"N 50° 4' 03.828\" E 14° 22' 38.712\"",
"N 50° 4' 03.828\", E 14° 22' 38.712\"",
"N 50° 4 03.828″, E 14° 22 38.712″",
'N50 4 03.828 E14 22 38.712',
'N50 4 03.828, E14 22 38.712',
"50°4'3.828\"N 14°22'38.712\"E"
].each do |code|
latlon_check code, 50.06773, 14.37742
end
end
##
# Test identification of lat/lon pairs using N/W with degrees/mins/secs
def test_identify_latlon_nw_dms
[
"N 50° 4' 03.828\" W 14° 22' 38.712\"",
"N 50° 4' 03.828\", W 14° 22' 38.712\"",
"N 50° 4 03.828″, W 14° 22 38.712″",
'N50 4 03.828 W14 22 38.712',
'N50 4 03.828, W14 22 38.712',
"50°4'3.828\"N 14°22'38.712\"W"
].each do |code|
latlon_check code, 50.06773, -14.37742
end
end
##
# Test identification of lat/lon pairs using S/E with degrees/mins/secs
def test_identify_latlon_se_dms
[
"S 50° 4' 03.828\" E 14° 22' 38.712\"",
"S 50° 4' 03.828\", E 14° 22' 38.712\"",
"S 50° 4 03.828″, E 14° 22 38.712″",
'S50 4 03.828 E14 22 38.712',
'S50 4 03.828, E14 22 38.712',
"50°4'3.828\"S 14°22'38.712\"E"
].each do |code|
latlon_check code, -50.06773, 14.37742
end
end
##
# Test identification of lat/lon pairs using S/W with degrees/mins/secs
def test_identify_latlon_sw_dms
[
"S 50° 4' 03.828\" W 14° 22' 38.712\"",
"S 50° 4' 03.828\", W 14° 22' 38.712\"",
"S 50° 4 03.828″, W 14° 22 38.712″",
'S50 4 03.828 W14 22 38.712',
'S50 4 03.828, W14 22 38.712',
"50°4'3.828\"S 14°22'38.712\"W"
].each do |code|
latlon_check code, -50.06773, -14.37742
end
end
##
# Test identification of US zipcodes
def test_identify_us_postcode
[
'12345',
'12345-6789'
].each do |code|
post :search, query: code
assert_response :success
assert_equal ['us_postcode', 'osm_nominatim'], assigns(:sources)
end
end
##
# Test identification of UK postcodes using examples from
# http://en.wikipedia.org/wiki/Postcodes_in_the_United_Kingdom
def test_identify_uk_postcode
[
'EC1A 1BB',
'W1A 1HQ',
'M1 1AA',
'B33 8TH',
'CR2 6XH',
'DN55 1PT'
].each do |code|
search_check code, ['uk_postcode', 'osm_nominatim']
end
end
##
# Test identification of Canadian postcodes
def test_identify_ca_postcode
search_check 'A1B 2C3', ['ca_postcode', 'osm_nominatim']
end
##
# Test identification fall through to the default case
def test_identify_default
search_check 'foo bar baz', ['osm_nominatim']
end
private
def latlon_check(query, lat, lon)
post :search, :query => query
assert_response :success
assert_template "search"
assert_template :layout => "map"
assert_equal ['latlon' ,'osm_nominatim_reverse'], assigns(:sources)
assert_nil @controller.params[:query]
assert_in_delta lat, @controller.params[:lat]
assert_in_delta lon, @controller.params[:lon]
xhr :post, :search, :query => query
assert_response :success
assert_template "search"
assert_template :layout => "xhr"
assert_equal ['latlon' ,'osm_nominatim_reverse'], assigns(:sources)
assert_nil @controller.params[:query]
assert_in_delta lat, @controller.params[:lat]
assert_in_delta lon, @controller.params[:lon]
end
def search_check(query, sources)
post :search, :query => query
assert_response :success
assert_template "search"
assert_template :layout => "map"
assert_equal sources, assigns(:sources)
xhr :post, :search, :query => query
assert_response :success
assert_template "search"
assert_template :layout => "xhr"
assert_equal sources, assigns(:sources)
end
end

View file

@ -0,0 +1,365 @@
require 'test_helper'
class MessageControllerTest < ActionController::TestCase
fixtures :users, :messages
##
# test all routes which lead to this controller
def test_routes
assert_routing(
{ :path => "/user/username/inbox", :method => :get },
{ :controller => "message", :action => "inbox", :display_name => "username" }
)
assert_routing(
{ :path => "/user/username/outbox", :method => :get },
{ :controller => "message", :action => "outbox", :display_name => "username" }
)
assert_routing(
{ :path => "/message/new/username", :method => :get },
{ :controller => "message", :action => "new", :display_name => "username" }
)
assert_routing(
{ :path => "/message/new/username", :method => :post },
{ :controller => "message", :action => "new", :display_name => "username" }
)
assert_routing(
{ :path => "/message/read/1", :method => :get },
{ :controller => "message", :action => "read", :message_id => "1" }
)
assert_routing(
{ :path => "/message/mark/1", :method => :post },
{ :controller => "message", :action => "mark", :message_id => "1" }
)
assert_routing(
{ :path => "/message/reply/1", :method => :get },
{ :controller => "message", :action => "reply", :message_id => "1" }
)
assert_routing(
{ :path => "/message/reply/1", :method => :post },
{ :controller => "message", :action => "reply", :message_id => "1" }
)
assert_routing(
{ :path => "/message/delete/1", :method => :post },
{ :controller => "message", :action => "delete", :message_id => "1" }
)
end
##
# test the new action
def test_new
# Check that the new message page requires us to login
get :new, :display_name => users(:public_user).display_name
assert_redirected_to login_path(:referer => new_message_path(:display_name => users(:public_user).display_name))
# Login as a normal user
session[:user] = users(:normal_user).id
# Check that the new message page loads
get :new, :display_name => users(:public_user).display_name
assert_response :success
assert_template "new"
assert_select "title", "OpenStreetMap | Send message"
assert_select "form[action='#{new_message_path(:display_name => users(:public_user).display_name)}']", :count => 1 do
assert_select "input#message_title", :count => 1
assert_select "textarea#message_body", :count => 1
assert_select "input[type='submit'][value='Send']", :count => 1
end
# Check that the subject is preserved over errors
assert_difference "ActionMailer::Base.deliveries.size", 0 do
assert_difference "Message.count", 0 do
post :new,
:display_name => users(:public_user).display_name,
:message => { :title => "Test Message", :body => "" }
end
end
assert_response :success
assert_template "new"
assert_select "title", "OpenStreetMap | Send message"
assert_select "form[action='#{new_message_path(:display_name => users(:public_user).display_name)}']", :count => 1 do
assert_select "input#message_title", :count => 1 do
assert_select "[value=Test Message]"
end
assert_select "textarea#message_body", :text => "", :count => 1
assert_select "input[type='submit'][value='Send']", :count => 1
end
# Check that the body text is preserved over errors
assert_difference "ActionMailer::Base.deliveries.size", 0 do
assert_difference "Message.count", 0 do
post :new,
:display_name => users(:public_user).display_name,
:message => { :title => "", :body => "Test message body" }
end
end
assert_response :success
assert_template "new"
assert_select "title", "OpenStreetMap | Send message"
assert_select "form[action='#{new_message_path(:display_name => users(:public_user).display_name)}']", :count => 1 do
assert_select "input#message_title", :count => 1 do
assert_select "[value=]"
end
assert_select "textarea#message_body", :text => "Test message body", :count => 1
assert_select "input[type='submit'][value='Send']", :count => 1
end
# Check that sending a message works
assert_difference "ActionMailer::Base.deliveries.size", 1 do
assert_difference "Message.count", 1 do
post :new,
:display_name => users(:public_user).display_name,
:message => { :title => "Test Message", :body => "Test message body" }
end
end
assert_redirected_to inbox_path(:display_name => users(:normal_user).display_name)
assert_equal "Message sent", flash[:notice]
e = ActionMailer::Base.deliveries.first
assert_equal [ users(:public_user).email ], e.to
assert_equal "[OpenStreetMap] Test Message", e.subject
assert_match /Test message body/, e.text_part.decoded
assert_match /Test message body/, e.html_part.decoded
ActionMailer::Base.deliveries.clear
m = Message.find(3)
assert_equal users(:normal_user).id, m.from_user_id
assert_equal users(:public_user).id, m.to_user_id
assert_in_delta Time.now, m.sent_on, 2
assert_equal "Test Message", m.title
assert_equal "Test message body", m.body
assert_equal "markdown", m.body_format
# Asking to send a message with a bogus user name should fail
get :new, :display_name => "non_existent_user"
assert_response :not_found
assert_template "user/no_such_user"
assert_select "h1", "The user non_existent_user does not exist"
end
##
# test the reply action
def test_reply
# Check that the message reply page requires us to login
get :reply, :message_id => messages(:unread_message).id
assert_redirected_to login_path(:referer => reply_message_path(:message_id => messages(:unread_message).id))
# Login as the wrong user
session[:user] = users(:second_public_user).id
# Check that we can't reply to somebody else's message
get :reply, :message_id => messages(:unread_message).id
assert_redirected_to login_path(:referer => reply_message_path(:message_id => messages(:unread_message).id))
assert_equal "You are logged in as `pulibc_test2' but the message you have asked to reply to was not sent to that user. Please login as the correct user in order to reply.", flash[:notice]
# Login as the right user
session[:user] = users(:public_user).id
# Check that the message reply page loads
get :reply, :message_id => messages(:unread_message).id
assert_response :success
assert_template "new"
assert_select "title", "OpenStreetMap | Re: test message 1"
assert_select "form[action='#{new_message_path(:display_name => users(:normal_user).display_name)}']", :count => 1 do
assert_select "input#message_title[value='Re: test message 1']", :count => 1
assert_select "textarea#message_body", :count => 1
assert_select "input[type='submit'][value='Send']", :count => 1
end
assert_equal true, Message.find(messages(:unread_message).id).message_read
# Asking to reply to a message with no ID should fail
assert_raise ActionController::UrlGenerationError do
get :reply
end
# Asking to reply to a message with a bogus ID should fail
get :reply, :message_id => 99999
assert_response :not_found
assert_template "no_such_message"
end
##
# test the read action
def test_read
# Check that the read message page requires us to login
get :read, :message_id => messages(:unread_message).id
assert_redirected_to login_path(:referer => read_message_path(:message_id => messages(:unread_message).id))
# Login as the wrong user
session[:user] = users(:second_public_user).id
# Check that we can't read the message
get :read, :message_id => messages(:unread_message).id
assert_redirected_to login_path(:referer => read_message_path(:message_id => messages(:unread_message).id))
assert_equal "You are logged in as `pulibc_test2' but the message you have asked to read was not sent by or to that user. Please login as the correct user in order to read it.", flash[:notice]
# Login as the message sender
session[:user] = users(:normal_user).id
# Check that the message sender can read the message
get :read, :message_id => messages(:unread_message).id
assert_response :success
assert_template "read"
assert_equal false, Message.find(messages(:unread_message).id).message_read
# Login as the message recipient
session[:user] = users(:public_user).id
# Check that the message recipient can read the message
get :read, :message_id => messages(:unread_message).id
assert_response :success
assert_template "read"
assert_equal true, Message.find(messages(:unread_message).id).message_read
# Asking to read a message with no ID should fail
assert_raise ActionController::UrlGenerationError do
get :read
end
# Asking to read a message with a bogus ID should fail
get :read, :message_id => 99999
assert_response :not_found
assert_template "no_such_message"
end
##
# test the inbox action
def test_inbox
# Check that the inbox page requires us to login
get :inbox, :display_name => users(:normal_user).display_name
assert_redirected_to login_path(:referer => inbox_path(:display_name => users(:normal_user).display_name))
# Login
session[:user] = users(:normal_user).id
# Check that we can view our inbox when logged in
get :inbox, :display_name => users(:normal_user).display_name
assert_response :success
assert_template "inbox"
assert_select "table.messages", :count => 1 do
assert_select "tr", :count => 2
assert_select "tr#inbox-#{messages(:read_message).id}.inbox-row", :count => 1
end
# Check that we can't view somebody else's inbox when logged in
get :inbox, :display_name => users(:public_user).display_name
assert_redirected_to inbox_path(:display_name => users(:normal_user).display_name)
end
##
# test the outbox action
def test_outbox
# Check that the outbox page requires us to login
get :outbox, :display_name => users(:normal_user).display_name
assert_redirected_to login_path(:referer => outbox_path(:display_name => users(:normal_user).display_name))
# Login
session[:user] = users(:normal_user).id
# Check that we can view our outbox when logged in
get :outbox, :display_name => users(:normal_user).display_name
assert_response :success
assert_template "outbox"
assert_select "table.messages", :count => 1 do
assert_select "tr", :count => 2
assert_select "tr.inbox-row", :count => 1
end
# Check that we can't view somebody else's outbox when logged in
get :outbox, :display_name => users(:public_user).display_name
assert_redirected_to outbox_path(:display_name => users(:normal_user).display_name)
end
##
# test the mark action
def test_mark
# Check that the marking a message requires us to login
post :mark, :message_id => messages(:unread_message).id
assert_response :forbidden
# Login as a user with no messages
session[:user] = users(:second_public_user).id
# Check that marking a message we didn't send or receive fails
post :mark, :message_id => messages(:read_message).id
assert_response :not_found
assert_template "no_such_message"
# Login as the message recipient
session[:user] = users(:public_user).id
# Check that the marking a message read works
post :mark, :message_id => messages(:unread_message).id, :mark => "read"
assert_redirected_to inbox_path(:display_name => users(:public_user).display_name)
assert_equal true, Message.find(messages(:unread_message).id).message_read
# Check that the marking a message unread works
post :mark, :message_id => messages(:unread_message).id, :mark => "unread"
assert_redirected_to inbox_path(:display_name => users(:public_user).display_name)
assert_equal false, Message.find(messages(:unread_message).id).message_read
# Check that the marking a message read via XHR works
xhr :post, :mark, :message_id => messages(:unread_message).id, :mark => "read"
assert_response :success
assert_template "mark"
assert_equal true, Message.find(messages(:unread_message).id).message_read
# Check that the marking a message unread via XHR works
xhr :post, :mark, :message_id => messages(:unread_message).id, :mark => "unread"
assert_response :success
assert_template "mark"
assert_equal false, Message.find(messages(:unread_message).id).message_read
# Asking to mark a message with no ID should fail
assert_raise ActionController::UrlGenerationError do
post :mark
end
# Asking to mark a message with a bogus ID should fail
post :mark, :message_id => 99999
assert_response :not_found
assert_template "no_such_message"
end
##
# test the delete action
def test_delete
# Check that the deleting a message requires us to login
post :delete, :message_id => messages(:read_message).id
assert_response :forbidden
# Login as a user with no messages
session[:user] = users(:second_public_user).id
# Check that deleting a message we didn't send or receive fails
post :delete, :message_id => messages(:read_message).id
assert_response :not_found
assert_template "no_such_message"
# Login as the message recipient
session[:user] = users(:normal_user).id
# Check that the deleting a received message works
post :delete, :message_id => messages(:read_message).id
assert_redirected_to inbox_path(:display_name => users(:normal_user).display_name)
assert_equal "Message deleted", flash[:notice]
m = Message.find(messages(:read_message).id)
assert_equal true, m.from_user_visible
assert_equal false, m.to_user_visible
# Check that the deleting a sent message works
post :delete, :message_id => messages(:unread_message).id
assert_redirected_to inbox_path(:display_name => users(:normal_user).display_name)
assert_equal "Message deleted", flash[:notice]
m = Message.find(messages(:unread_message).id)
assert_equal false, m.from_user_visible
assert_equal true, m.to_user_visible
# Asking to delete a message with no ID should fail
assert_raise ActionController::UrlGenerationError do
post :delete
end
# Asking to delete a message with a bogus ID should fail
post :delete, :message_id => 99999
assert_response :not_found
assert_template "no_such_message"
end
end

View file

@ -0,0 +1,542 @@
require 'test_helper'
class NodeControllerTest < ActionController::TestCase
api_fixtures
##
# test all routes which lead to this controller
def test_routes
assert_routing(
{ :path => "/api/0.6/node/create", :method => :put },
{ :controller => "node", :action => "create" }
)
assert_routing(
{ :path => "/api/0.6/node/1", :method => :get },
{ :controller => "node", :action => "read", :id => "1" }
)
assert_routing(
{ :path => "/api/0.6/node/1", :method => :put },
{ :controller => "node", :action => "update", :id => "1" }
)
assert_routing(
{ :path => "/api/0.6/node/1", :method => :delete },
{ :controller => "node", :action => "delete", :id => "1" }
)
assert_routing(
{ :path => "/api/0.6/nodes", :method => :get },
{ :controller => "node", :action => "nodes" }
)
end
def test_create
# cannot read password from fixture as it is stored as MD5 digest
## First try with no auth
# create a node with random lat/lon
lat = rand(100)-50 + rand
lon = rand(100)-50 + rand
# normal user has a changeset open, so we'll use that.
changeset = changesets(:normal_user_first_change)
# create a minimal xml file
content("<osm><node lat='#{lat}' lon='#{lon}' changeset='#{changeset.id}'/></osm>")
assert_difference('OldNode.count', 0) do
put :create
end
# hope for unauthorized
assert_response :unauthorized, "node upload did not return unauthorized status"
## Now try with the user which doesn't have their data public
basic_authorization(users(:normal_user).email, "test")
# create a node with random lat/lon
lat = rand(100)-50 + rand
lon = rand(100)-50 + rand
# normal user has a changeset open, so we'll use that.
changeset = changesets(:normal_user_first_change)
# create a minimal xml file
content("<osm><node lat='#{lat}' lon='#{lon}' changeset='#{changeset.id}'/></osm>")
assert_difference('Node.count', 0) do
put :create
end
# hope for success
assert_require_public_data "node create did not return forbidden status"
## Now try with the user that has the public data
basic_authorization(users(:public_user).email, "test")
# create a node with random lat/lon
lat = rand(100)-50 + rand
lon = rand(100)-50 + rand
# normal user has a changeset open, so we'll use that.
changeset = changesets(:public_user_first_change)
# create a minimal xml file
content("<osm><node lat='#{lat}' lon='#{lon}' changeset='#{changeset.id}'/></osm>")
put :create
# hope for success
assert_response :success, "node upload did not return success status"
# read id of created node and search for it
nodeid = @response.body
checknode = Node.find(nodeid)
assert_not_nil checknode, "uploaded node not found in data base after upload"
# compare values
assert_in_delta lat * 10000000, checknode.latitude, 1, "saved node does not match requested latitude"
assert_in_delta lon * 10000000, checknode.longitude, 1, "saved node does not match requested longitude"
assert_equal changesets(:public_user_first_change).id, checknode.changeset_id, "saved node does not belong to changeset that it was created in"
assert_equal true, checknode.visible, "saved node is not visible"
end
def test_create_invalid_xml
## Only test public user here, as test_create should cover what's the forbiddens
## that would occur here
# Initial setup
basic_authorization(users(:public_user).email, "test")
# normal user has a changeset open, so we'll use that.
changeset = changesets(:public_user_first_change)
lat = 3.434
lon = 3.23
# test that the upload is rejected when xml is valid, but osm doc isn't
content("<create/>")
put :create
assert_response :bad_request, "node upload did not return bad_request status"
assert_equal "Cannot parse valid node from xml string <create/>. XML doesn't contain an osm/node element.", @response.body
# test that the upload is rejected when no lat is supplied
# create a minimal xml file
content("<osm><node lon='#{lon}' changeset='#{changeset.id}'/></osm>")
put :create
# hope for success
assert_response :bad_request, "node upload did not return bad_request status"
assert_equal "Cannot parse valid node from xml string <node lon=\"3.23\" changeset=\"#{changeset.id}\"/>. lat missing", @response.body
# test that the upload is rejected when no lon is supplied
# create a minimal xml file
content("<osm><node lat='#{lat}' changeset='#{changeset.id}'/></osm>")
put :create
# hope for success
assert_response :bad_request, "node upload did not return bad_request status"
assert_equal "Cannot parse valid node from xml string <node lat=\"3.434\" changeset=\"#{changeset.id}\"/>. lon missing", @response.body
# test that the upload is rejected when lat is non-numeric
# create a minimal xml file
content("<osm><node lat='abc' lon='#{lon}' changeset='#{changeset.id}'/></osm>")
put :create
# hope for success
assert_response :bad_request, "node upload did not return bad_request status"
assert_equal "Cannot parse valid node from xml string <node lat=\"abc\" lon=\"#{lon}\" changeset=\"#{changeset.id}\"/>. lat not a number", @response.body
# test that the upload is rejected when lon is non-numeric
# create a minimal xml file
content("<osm><node lat='#{lat}' lon='abc' changeset='#{changeset.id}'/></osm>")
put :create
# hope for success
assert_response :bad_request, "node upload did not return bad_request status"
assert_equal "Cannot parse valid node from xml string <node lat=\"#{lat}\" lon=\"abc\" changeset=\"#{changeset.id}\"/>. lon not a number", @response.body
# test that the upload is rejected when we have a tag which is too long
content("<osm><node lat='#{lat}' lon='#{lon}' changeset='#{changeset.id}'><tag k='foo' v='#{'x'*256}'/></node></osm>")
put :create
assert_response :bad_request, "node upload did not return bad_request status"
assert_equal ["NodeTag ", " v: is too long (maximum is 255 characters) (\"#{'x'*256}\")"], @response.body.split(/[0-9]+,foo:/)
end
def test_read
# check that a visible node is returned properly
get :read, :id => current_nodes(:visible_node).id
assert_response :success
# check that an invisible node is not returned
get :read, :id => current_nodes(:invisible_node).id
assert_response :gone
# check chat a non-existent node is not returned
get :read, :id => 0
assert_response :not_found
end
# this tests deletion restrictions - basic deletion is tested in the unit
# tests for node!
def test_delete
## first try to delete node without auth
delete :delete, :id => current_nodes(:visible_node).id
assert_response :unauthorized
## now set auth for the non-data public user
basic_authorization(users(:normal_user).email, "test");
# try to delete with an invalid (closed) changeset
content update_changeset(current_nodes(:visible_node).to_xml,
changesets(:normal_user_closed_change).id)
delete :delete, :id => current_nodes(:visible_node).id
assert_require_public_data("non-public user shouldn't be able to delete node")
# try to delete with an invalid (non-existent) changeset
content update_changeset(current_nodes(:visible_node).to_xml,0)
delete :delete, :id => current_nodes(:visible_node).id
assert_require_public_data("shouldn't be able to delete node, when user's data is private")
# valid delete now takes a payload
content(nodes(:visible_node).to_xml)
delete :delete, :id => current_nodes(:visible_node).id
assert_require_public_data("shouldn't be able to delete node when user's data isn't public'")
# this won't work since the node is already deleted
content(nodes(:invisible_node).to_xml)
delete :delete, :id => current_nodes(:invisible_node).id
assert_require_public_data
# this won't work since the node never existed
delete :delete, :id => 0
assert_require_public_data
## these test whether nodes which are in-use can be deleted:
# in a way...
content(nodes(:used_node_1).to_xml)
delete :delete, :id => current_nodes(:used_node_1).id
assert_require_public_data
"shouldn't be able to delete a node used in a way (#{@response.body})"
# in a relation...
content(nodes(:node_used_by_relationship).to_xml)
delete :delete, :id => current_nodes(:node_used_by_relationship).id
assert_require_public_data
"shouldn't be able to delete a node used in a relation (#{@response.body})"
## now set auth for the public data user
basic_authorization(users(:public_user).email, "test");
# try to delete with an invalid (closed) changeset
content update_changeset(current_nodes(:visible_node).to_xml,
changesets(:normal_user_closed_change).id)
delete :delete, :id => current_nodes(:visible_node).id
assert_response :conflict
# try to delete with an invalid (non-existent) changeset
content update_changeset(current_nodes(:visible_node).to_xml,0)
delete :delete, :id => current_nodes(:visible_node).id
assert_response :conflict
# try to delete a node with a different ID
content(nodes(:public_visible_node).to_xml)
delete :delete, :id => current_nodes(:visible_node).id
assert_response :bad_request,
"should not be able to delete a node with a different ID from the XML"
# try to delete a node rubbish in the payloads
content("<delete/>")
delete :delete, :id => current_nodes(:visible_node).id
assert_response :bad_request,
"should not be able to delete a node without a valid XML payload"
# valid delete now takes a payload
content(nodes(:public_visible_node).to_xml)
delete :delete, :id => current_nodes(:public_visible_node).id
assert_response :success
# valid delete should return the new version number, which should
# be greater than the old version number
assert @response.body.to_i > current_nodes(:public_visible_node).version,
"delete request should return a new version number for node"
# deleting the same node twice doesn't work
content(nodes(:public_visible_node).to_xml)
delete :delete, :id => current_nodes(:public_visible_node).id
assert_response :gone
# this won't work since the node never existed
delete :delete, :id => 0
assert_response :not_found
## these test whether nodes which are in-use can be deleted:
# in a way...
content(nodes(:used_node_1).to_xml)
delete :delete, :id => current_nodes(:used_node_1).id
assert_response :precondition_failed,
"shouldn't be able to delete a node used in a way (#{@response.body})"
assert_equal "Precondition failed: Node 3 is still used by ways 1,3.", @response.body
# in a relation...
content(nodes(:node_used_by_relationship).to_xml)
delete :delete, :id => current_nodes(:node_used_by_relationship).id
assert_response :precondition_failed,
"shouldn't be able to delete a node used in a relation (#{@response.body})"
assert_equal "Precondition failed: Node 5 is still used by relations 1,3.", @response.body
end
##
# tests whether the API works and prevents incorrect use while trying
# to update nodes.
def test_update
## First test with no user credentials
# try and update a node without authorisation
# first try to delete node without auth
content current_nodes(:visible_node).to_xml
put :update, :id => current_nodes(:visible_node).id
assert_response :unauthorized
## Second test with the private user
# setup auth
basic_authorization(users(:normal_user).email, "test")
## trying to break changesets
# try and update in someone else's changeset
content update_changeset(current_nodes(:visible_node).to_xml,
changesets(:public_user_first_change).id)
put :update, :id => current_nodes(:visible_node).id
assert_require_public_data "update with other user's changeset should be forbidden when date isn't public"
# try and update in a closed changeset
content update_changeset(current_nodes(:visible_node).to_xml,
changesets(:normal_user_closed_change).id)
put :update, :id => current_nodes(:visible_node).id
assert_require_public_data "update with closed changeset should be forbidden, when data isn't public"
# try and update in a non-existant changeset
content update_changeset(current_nodes(:visible_node).to_xml, 0)
put :update, :id => current_nodes(:visible_node).id
assert_require_public_data("update with changeset=0 should be forbidden, when data isn't public")
## try and submit invalid updates
content xml_attr_rewrite(current_nodes(:visible_node).to_xml, 'lat', 91.0);
put :update, :id => current_nodes(:visible_node).id
assert_require_public_data "node at lat=91 should be forbidden, when data isn't public"
content xml_attr_rewrite(current_nodes(:visible_node).to_xml, 'lat', -91.0);
put :update, :id => current_nodes(:visible_node).id
assert_require_public_data "node at lat=-91 should be forbidden, when data isn't public"
content xml_attr_rewrite(current_nodes(:visible_node).to_xml, 'lon', 181.0);
put :update, :id => current_nodes(:visible_node).id
assert_require_public_data "node at lon=181 should be forbidden, when data isn't public"
content xml_attr_rewrite(current_nodes(:visible_node).to_xml, 'lon', -181.0);
put :update, :id => current_nodes(:visible_node).id
assert_require_public_data "node at lon=-181 should be forbidden, when data isn't public"
## finally, produce a good request which should work
content current_nodes(:visible_node).to_xml
put :update, :id => current_nodes(:visible_node).id
assert_require_public_data "should have failed with a forbidden when data isn't public"
## Finally test with the public user
# try and update a node without authorisation
# first try to delete node without auth
content current_nodes(:visible_node).to_xml
put :update, :id => current_nodes(:visible_node).id
assert_response :forbidden
# setup auth
basic_authorization(users(:public_user).email, "test")
## trying to break changesets
# try and update in someone else's changeset
content update_changeset(current_nodes(:visible_node).to_xml,
changesets(:normal_user_first_change).id)
put :update, :id => current_nodes(:visible_node).id
assert_response :conflict, "update with other user's changeset should be rejected"
# try and update in a closed changeset
content update_changeset(current_nodes(:visible_node).to_xml,
changesets(:normal_user_closed_change).id)
put :update, :id => current_nodes(:visible_node).id
assert_response :conflict, "update with closed changeset should be rejected"
# try and update in a non-existant changeset
content update_changeset(current_nodes(:visible_node).to_xml, 0)
put :update, :id => current_nodes(:visible_node).id
assert_response :conflict, "update with changeset=0 should be rejected"
## try and submit invalid updates
content xml_attr_rewrite(current_nodes(:visible_node).to_xml, 'lat', 91.0);
put :update, :id => current_nodes(:visible_node).id
assert_response :bad_request, "node at lat=91 should be rejected"
content xml_attr_rewrite(current_nodes(:visible_node).to_xml, 'lat', -91.0);
put :update, :id => current_nodes(:visible_node).id
assert_response :bad_request, "node at lat=-91 should be rejected"
content xml_attr_rewrite(current_nodes(:visible_node).to_xml, 'lon', 181.0);
put :update, :id => current_nodes(:visible_node).id
assert_response :bad_request, "node at lon=181 should be rejected"
content xml_attr_rewrite(current_nodes(:visible_node).to_xml, 'lon', -181.0);
put :update, :id => current_nodes(:visible_node).id
assert_response :bad_request, "node at lon=-181 should be rejected"
## next, attack the versioning
current_node_version = current_nodes(:visible_node).version
# try and submit a version behind
content xml_attr_rewrite(current_nodes(:visible_node).to_xml,
'version', current_node_version - 1);
put :update, :id => current_nodes(:visible_node).id
assert_response :conflict, "should have failed on old version number"
# try and submit a version ahead
content xml_attr_rewrite(current_nodes(:visible_node).to_xml,
'version', current_node_version + 1);
put :update, :id => current_nodes(:visible_node).id
assert_response :conflict, "should have failed on skipped version number"
# try and submit total crap in the version field
content xml_attr_rewrite(current_nodes(:visible_node).to_xml,
'version', 'p1r4t3s!');
put :update, :id => current_nodes(:visible_node).id
assert_response :conflict,
"should not be able to put 'p1r4at3s!' in the version field"
## try an update with the wrong ID
content current_nodes(:public_visible_node).to_xml
put :update, :id => current_nodes(:visible_node).id
assert_response :bad_request,
"should not be able to update a node with a different ID from the XML"
## try an update with a minimal valid XML doc which isn't a well-formed OSM doc.
content "<update/>"
put :update, :id => current_nodes(:visible_node).id
assert_response :bad_request,
"should not be able to update a node with non-OSM XML doc."
## finally, produce a good request which should work
content current_nodes(:public_visible_node).to_xml
put :update, :id => current_nodes(:public_visible_node).id
assert_response :success, "a valid update request failed"
end
##
# test fetching multiple nodes
def test_nodes
# check error when no parameter provided
get :nodes
assert_response :bad_request
# check error when no parameter value provided
get :nodes, :nodes => ""
assert_response :bad_request
# test a working call
get :nodes, :nodes => "1,2,4,15,17"
assert_response :success
assert_select "osm" do
assert_select "node", :count => 5
assert_select "node[id=1][visible=true]", :count => 1
assert_select "node[id=2][visible=false]", :count => 1
assert_select "node[id=4][visible=true]", :count => 1
assert_select "node[id=15][visible=true]", :count => 1
assert_select "node[id=17][visible=false]", :count => 1
end
# check error when a non-existent node is included
get :nodes, :nodes => "1,2,4,15,17,400"
assert_response :not_found
end
##
# test adding tags to a node
def test_duplicate_tags
# setup auth
basic_authorization(users(:public_user).email, "test")
# add an identical tag to the node
tag_xml = XML::Node.new("tag")
tag_xml['k'] = current_node_tags(:public_v_t1).k
tag_xml['v'] = current_node_tags(:public_v_t1).v
# add the tag into the existing xml
node_xml = current_nodes(:public_visible_node).to_xml
node_xml.find("//osm/node").first << tag_xml
# try and upload it
content node_xml
put :update, :id => current_nodes(:public_visible_node).id
assert_response :bad_request,
"adding duplicate tags to a node should fail with 'bad request'"
assert_equal "Element node/#{current_nodes(:public_visible_node).id} has duplicate tags with key #{current_node_tags(:t1).k}", @response.body
end
# test whether string injection is possible
def test_string_injection
## First try with the non-data public user
basic_authorization(users(:normal_user).email, "test")
changeset_id = changesets(:normal_user_first_change).id
# try and put something into a string that the API might
# use unquoted and therefore allow code injection...
content "<osm><node lat='0' lon='0' changeset='#{changeset_id}'>" +
'<tag k="#{@user.inspect}" v="0"/>' +
'</node></osm>'
put :create
assert_require_public_data "Shouldn't be able to create with non-public user"
## Then try with the public data user
basic_authorization(users(:public_user).email, "test")
changeset_id = changesets(:public_user_first_change).id
# try and put something into a string that the API might
# use unquoted and therefore allow code injection...
content "<osm><node lat='0' lon='0' changeset='#{changeset_id}'>" +
'<tag k="#{@user.inspect}" v="0"/>' +
'</node></osm>'
put :create
assert_response :success
nodeid = @response.body
# find the node in the database
checknode = Node.find(nodeid)
assert_not_nil checknode, "node not found in data base after upload"
# and grab it using the api
get :read, :id => nodeid
assert_response :success
apinode = Node.from_xml(@response.body)
assert_not_nil apinode, "downloaded node is nil, but shouldn't be"
# check the tags are not corrupted
assert_equal checknode.tags, apinode.tags
assert apinode.tags.include?('#{@user.inspect}')
end
def basic_authorization(user, pass)
@request.env["HTTP_AUTHORIZATION"] = "Basic %s" % Base64.encode64("#{user}:#{pass}")
end
def content(c)
@request.env["RAW_POST_DATA"] = c.to_s
end
##
# update the changeset_id of a node element
def update_changeset(xml, changeset_id)
xml_attr_rewrite(xml, 'changeset', changeset_id)
end
##
# update an attribute in the node element
def xml_attr_rewrite(xml, name, value)
xml.find("//osm/node").first[name] = value.to_s
return xml
end
##
# parse some xml
def xml_parse(xml)
parser = XML::Parser.string(xml)
parser.parse
end
end

View file

@ -0,0 +1,760 @@
require 'test_helper'
class NotesControllerTest < ActionController::TestCase
fixtures :users, :notes, :note_comments
##
# test all routes which lead to this controller
def test_routes
assert_routing(
{ :path => "/api/0.6/notes", :method => :post },
{ :controller => "notes", :action => "create", :format => "xml" }
)
assert_routing(
{ :path => "/api/0.6/notes/1", :method => :get },
{ :controller => "notes", :action => "show", :id => "1", :format => "xml" }
)
assert_recognizes(
{ :controller => "notes", :action => "show", :id => "1", :format => "xml" },
{ :path => "/api/0.6/notes/1.xml", :method => :get }
)
assert_routing(
{ :path => "/api/0.6/notes/1.rss", :method => :get },
{ :controller => "notes", :action => "show", :id => "1", :format => "rss" }
)
assert_routing(
{ :path => "/api/0.6/notes/1.json", :method => :get },
{ :controller => "notes", :action => "show", :id => "1", :format => "json" }
)
assert_routing(
{ :path => "/api/0.6/notes/1.gpx", :method => :get },
{ :controller => "notes", :action => "show", :id => "1", :format => "gpx" }
)
assert_routing(
{ :path => "/api/0.6/notes/1/comment", :method => :post },
{ :controller => "notes", :action => "comment", :id => "1", :format => "xml" }
)
assert_routing(
{ :path => "/api/0.6/notes/1/close", :method => :post },
{ :controller => "notes", :action => "close", :id => "1", :format => "xml" }
)
assert_routing(
{ :path => "/api/0.6/notes/1/reopen", :method => :post },
{ :controller => "notes", :action => "reopen", :id => "1", :format => "xml" }
)
assert_routing(
{ :path => "/api/0.6/notes/1", :method => :delete },
{ :controller => "notes", :action => "destroy", :id => "1", :format => "xml" }
)
assert_routing(
{ :path => "/api/0.6/notes", :method => :get },
{ :controller => "notes", :action => "index", :format => "xml" }
)
assert_recognizes(
{ :controller => "notes", :action => "index", :format => "xml" },
{ :path => "/api/0.6/notes.xml", :method => :get }
)
assert_routing(
{ :path => "/api/0.6/notes.rss", :method => :get },
{ :controller => "notes", :action => "index", :format => "rss" }
)
assert_routing(
{ :path => "/api/0.6/notes.json", :method => :get },
{ :controller => "notes", :action => "index", :format => "json" }
)
assert_routing(
{ :path => "/api/0.6/notes.gpx", :method => :get },
{ :controller => "notes", :action => "index", :format => "gpx" }
)
assert_routing(
{ :path => "/api/0.6/notes/search", :method => :get },
{ :controller => "notes", :action => "search", :format => "xml" }
)
assert_recognizes(
{ :controller => "notes", :action => "search", :format => "xml" },
{ :path => "/api/0.6/notes/search.xml", :method => :get }
)
assert_routing(
{ :path => "/api/0.6/notes/search.rss", :method => :get },
{ :controller => "notes", :action => "search", :format => "rss" }
)
assert_routing(
{ :path => "/api/0.6/notes/search.json", :method => :get },
{ :controller => "notes", :action => "search", :format => "json" }
)
assert_routing(
{ :path => "/api/0.6/notes/search.gpx", :method => :get },
{ :controller => "notes", :action => "search", :format => "gpx" }
)
assert_routing(
{ :path => "/api/0.6/notes/feed", :method => :get },
{ :controller => "notes", :action => "feed", :format => "rss" }
)
assert_recognizes(
{ :controller => "notes", :action => "create" },
{ :path => "/api/0.6/notes/addPOIexec", :method => :post }
)
assert_recognizes(
{ :controller => "notes", :action => "close" },
{ :path => "/api/0.6/notes/closePOIexec", :method => :post }
)
assert_recognizes(
{ :controller => "notes", :action => "comment" },
{ :path => "/api/0.6/notes/editPOIexec", :method => :post }
)
assert_recognizes(
{ :controller => "notes", :action => "index", :format => "gpx" },
{ :path => "/api/0.6/notes/getGPX", :method => :get }
)
assert_recognizes(
{ :controller => "notes", :action => "feed", :format => "rss" },
{ :path => "/api/0.6/notes/getRSSfeed", :method => :get }
)
assert_routing(
{ :path => "/user/username/notes", :method => :get },
{ :controller => "notes", :action => "mine", :display_name => "username" }
)
end
def test_create_success
assert_difference('Note.count') do
assert_difference('NoteComment.count') do
post :create, {:lat => -1.0, :lon => -1.0, :text => "This is a comment", :format => "json"}
end
end
assert_response :success
js = ActiveSupport::JSON.decode(@response.body)
assert_not_nil js
assert_equal "Feature", js["type"]
assert_equal "Point", js["geometry"]["type"]
assert_equal [-1.0, -1.0], js["geometry"]["coordinates"]
assert_equal "open", js["properties"]["status"]
assert_equal 1, js["properties"]["comments"].count
assert_equal "opened", js["properties"]["comments"].last["action"]
assert_equal "This is a comment", js["properties"]["comments"].last["text"]
assert_nil js["properties"]["comments"].last["user"]
id = js["properties"]["id"]
get :show, {:id => id, :format => "json"}
assert_response :success
js = ActiveSupport::JSON.decode(@response.body)
assert_not_nil js
assert_equal "Feature", js["type"]
assert_equal "Point", js["geometry"]["type"]
assert_equal [-1.0, -1.0], js["geometry"]["coordinates"]
assert_equal id, js["properties"]["id"]
assert_equal "open", js["properties"]["status"]
assert_equal 1, js["properties"]["comments"].count
assert_equal "opened", js["properties"]["comments"].last["action"]
assert_equal "This is a comment", js["properties"]["comments"].last["text"]
assert_nil js["properties"]["comments"].last["user"]
end
def test_create_fail
assert_no_difference('Note.count') do
assert_no_difference('NoteComment.count') do
post :create, {:lon => -1.0, :text => "This is a comment"}
end
end
assert_response :bad_request
assert_no_difference('Note.count') do
assert_no_difference('NoteComment.count') do
post :create, {:lat => -1.0, :text => "This is a comment"}
end
end
assert_response :bad_request
assert_no_difference('Note.count') do
assert_no_difference('NoteComment.count') do
post :create, {:lat => -1.0, :lon => -1.0}
end
end
assert_response :bad_request
assert_no_difference('Note.count') do
assert_no_difference('NoteComment.count') do
post :create, {:lat => -1.0, :lon => -1.0, :text => ""}
end
end
assert_response :bad_request
assert_no_difference('Note.count') do
assert_no_difference('NoteComment.count') do
post :create, {:lat => -100.0, :lon => -1.0, :text => "This is a comment"}
end
end
assert_response :bad_request
assert_no_difference('Note.count') do
assert_no_difference('NoteComment.count') do
post :create, {:lat => -1.0, :lon => -200.0, :text => "This is a comment"}
end
end
assert_response :bad_request
assert_no_difference('Note.count') do
assert_no_difference('NoteComment.count') do
post :create, {:lat => 'abc', :lon => -1.0, :text => "This is a comment"}
end
end
assert_response :bad_request
assert_no_difference('Note.count') do
assert_no_difference('NoteComment.count') do
post :create, {:lat => -1.0, :lon => 'abc', :text => "This is a comment"}
end
end
assert_response :bad_request
end
def test_comment_success
assert_difference('NoteComment.count') do
post :comment, {:id => notes(:open_note_with_comment).id, :text => "This is an additional comment", :format => "json"}
end
assert_response :success
js = ActiveSupport::JSON.decode(@response.body)
assert_not_nil js
assert_equal "Feature", js["type"]
assert_equal notes(:open_note_with_comment).id, js["properties"]["id"]
assert_equal "open", js["properties"]["status"]
assert_equal 3, js["properties"]["comments"].count
assert_equal "commented", js["properties"]["comments"].last["action"]
assert_equal "This is an additional comment", js["properties"]["comments"].last["text"]
assert_nil js["properties"]["comments"].last["user"]
get :show, {:id => notes(:open_note_with_comment).id, :format => "json"}
assert_response :success
js = ActiveSupport::JSON.decode(@response.body)
assert_not_nil js
assert_equal "Feature", js["type"]
assert_equal notes(:open_note_with_comment).id, js["properties"]["id"]
assert_equal "open", js["properties"]["status"]
assert_equal 3, js["properties"]["comments"].count
assert_equal "commented", js["properties"]["comments"].last["action"]
assert_equal "This is an additional comment", js["properties"]["comments"].last["text"]
assert_nil js["properties"]["comments"].last["user"]
end
def test_comment_fail
assert_no_difference('NoteComment.count') do
post :comment, {:text => "This is an additional comment"}
end
assert_response :bad_request
assert_no_difference('NoteComment.count') do
post :comment, {:id => notes(:open_note_with_comment).id}
end
assert_response :bad_request
assert_no_difference('NoteComment.count') do
post :comment, {:id => notes(:open_note_with_comment).id, :text => ""}
end
assert_response :bad_request
assert_no_difference('NoteComment.count') do
post :comment, {:id => 12345, :text => "This is an additional comment"}
end
assert_response :not_found
assert_no_difference('NoteComment.count') do
post :comment, {:id => notes(:hidden_note_with_comment).id, :text => "This is an additional comment"}
end
assert_response :gone
assert_no_difference('NoteComment.count') do
post :comment, {:id => notes(:closed_note_with_comment).id, :text => "This is an additional comment"}
end
assert_response :conflict
end
def test_close_success
post :close, {:id => notes(:open_note_with_comment).id, :text => "This is a close comment", :format => "json"}
assert_response :unauthorized
basic_authorization(users(:public_user).email, "test")
post :close, {:id => notes(:open_note_with_comment).id, :text => "This is a close comment", :format => "json"}
assert_response :success
js = ActiveSupport::JSON.decode(@response.body)
assert_not_nil js
assert_equal "Feature", js["type"]
assert_equal notes(:open_note_with_comment).id, js["properties"]["id"]
assert_equal "closed", js["properties"]["status"]
assert_equal 3, js["properties"]["comments"].count
assert_equal "closed", js["properties"]["comments"].last["action"]
assert_equal "This is a close comment", js["properties"]["comments"].last["text"]
assert_equal "test2", js["properties"]["comments"].last["user"]
get :show, {:id => notes(:open_note_with_comment).id, :format => "json"}
assert_response :success
js = ActiveSupport::JSON.decode(@response.body)
assert_not_nil js
assert_equal "Feature", js["type"]
assert_equal notes(:open_note_with_comment).id, js["properties"]["id"]
assert_equal "closed", js["properties"]["status"]
assert_equal 3, js["properties"]["comments"].count
assert_equal "closed", js["properties"]["comments"].last["action"]
assert_equal "This is a close comment", js["properties"]["comments"].last["text"]
assert_equal "test2", js["properties"]["comments"].last["user"]
end
def test_close_fail
post :close
assert_response :unauthorized
basic_authorization(users(:public_user).email, "test")
post :close
assert_response :bad_request
post :close, {:id => 12345}
assert_response :not_found
post :close, {:id => notes(:hidden_note_with_comment).id}
assert_response :gone
post :close, {:id => notes(:closed_note_with_comment).id}
assert_response :conflict
end
def test_reopen_success
post :reopen, {:id => notes(:closed_note_with_comment).id, :text => "This is a reopen comment", :format => "json"}
assert_response :unauthorized
basic_authorization(users(:public_user).email, "test")
post :reopen, {:id => notes(:closed_note_with_comment).id, :text => "This is a reopen comment", :format => "json"}
assert_response :success
js = ActiveSupport::JSON.decode(@response.body)
assert_not_nil js
assert_equal "Feature", js["type"]
assert_equal notes(:closed_note_with_comment).id, js["properties"]["id"]
assert_equal "open", js["properties"]["status"]
assert_equal 2, js["properties"]["comments"].count
assert_equal "reopened", js["properties"]["comments"].last["action"]
assert_equal "This is a reopen comment", js["properties"]["comments"].last["text"]
assert_equal "test2", js["properties"]["comments"].last["user"]
get :show, {:id => notes(:closed_note_with_comment).id, :format => "json"}
assert_response :success
js = ActiveSupport::JSON.decode(@response.body)
assert_not_nil js
assert_equal "Feature", js["type"]
assert_equal notes(:closed_note_with_comment).id, js["properties"]["id"]
assert_equal "open", js["properties"]["status"]
assert_equal 2, js["properties"]["comments"].count
assert_equal "reopened", js["properties"]["comments"].last["action"]
assert_equal "This is a reopen comment", js["properties"]["comments"].last["text"]
assert_equal "test2", js["properties"]["comments"].last["user"]
end
def test_reopen_fail
post :reopen, {:id => notes(:hidden_note_with_comment).id}
assert_response :unauthorized
basic_authorization(users(:public_user).email, "test")
post :reopen, {:id => 12345}
assert_response :not_found
post :reopen, {:id => notes(:hidden_note_with_comment).id}
assert_response :gone
post :reopen, {:id => notes(:open_note_with_comment).id}
assert_response :conflict
end
def test_show_success
get :show, {:id => notes(:open_note).id, :format => "xml"}
assert_response :success
assert_equal "application/xml", @response.content_type
assert_select "osm", :count => 1 do
assert_select "note[lat=#{notes(:open_note).lat}][lon=#{notes(:open_note).lon}]", :count => 1 do
assert_select "id", notes(:open_note).id
assert_select "url", note_url(notes(:open_note), :format => "xml")
assert_select "comment_url", comment_note_url(notes(:open_note), :format => "xml")
assert_select "close_url", close_note_url(notes(:open_note), :format => "xml")
assert_select "date_created", notes(:open_note).created_at.to_s
assert_select "status", notes(:open_note).status
assert_select "comments", :count => 1 do
assert_select "comment", :count => 1
end
end
end
get :show, {:id => notes(:open_note).id, :format => "rss"}
assert_response :success
assert_equal "application/rss+xml", @response.content_type
assert_select "rss", :count => 1 do
assert_select "channel", :count => 1 do
assert_select "item", :count => 1 do
assert_select "link", browse_note_url(notes(:open_note))
assert_select "guid", note_url(notes(:open_note))
assert_select "pubDate", notes(:open_note).created_at.to_s(:rfc822)
# assert_select "geo:lat", notes(:open_note).lat.to_s
# assert_select "geo:long", notes(:open_note).lon
# assert_select "georss:point", "#{notes(:open_note).lon} #{notes(:open_note).lon}"
end
end
end
get :show, {:id => notes(:open_note).id, :format => "json"}
assert_response :success
assert_equal "application/json", @response.content_type
js = ActiveSupport::JSON.decode(@response.body)
assert_not_nil js
assert_equal "Feature", js["type"]
assert_equal "Point", js["geometry"]["type"]
assert_equal notes(:open_note).lat, js["geometry"]["coordinates"][0]
assert_equal notes(:open_note).lon, js["geometry"]["coordinates"][1]
assert_equal notes(:open_note).id, js["properties"]["id"]
assert_equal note_url(notes(:open_note), :format => "json"), js["properties"]["url"]
assert_equal comment_note_url(notes(:open_note), :format => "json"), js["properties"]["comment_url"]
assert_equal close_note_url(notes(:open_note), :format => "json"), js["properties"]["close_url"]
assert_equal notes(:open_note).created_at, js["properties"]["date_created"]
assert_equal notes(:open_note).status, js["properties"]["status"]
get :show, {:id => notes(:open_note).id, :format => "gpx"}
assert_response :success
assert_equal "application/gpx+xml", @response.content_type
assert_select "gpx", :count => 1 do
assert_select "wpt[lat=#{notes(:open_note).lat}][lon=#{notes(:open_note).lon}]", :count => 1 do
assert_select "extension", :count => 1 do
assert_select "id", notes(:open_note).id
assert_select "url", note_url(notes(:open_note), :format => "gpx")
assert_select "comment_url", comment_note_url(notes(:open_note), :format => "gpx")
assert_select "close_url", close_note_url(notes(:open_note), :format => "gpx")
end
end
end
end
def test_show_hidden_comment
get :show, {:id => notes(:note_with_hidden_comment).id, :format => "json"}
assert_response :success
js = ActiveSupport::JSON.decode(@response.body)
assert_not_nil js
assert_equal "Feature", js["type"]
assert_equal notes(:note_with_hidden_comment).id, js["properties"]["id"]
assert_equal 2, js["properties"]["comments"].count
assert_equal "Valid comment for note 5", js["properties"]["comments"][0]["text"]
assert_equal "Another valid comment for note 5", js["properties"]["comments"][1]["text"]
end
def test_show_fail
get :show, {:id => 12345}
assert_response :not_found
get :show, {:id => notes(:hidden_note_with_comment).id}
assert_response :gone
end
def test_destroy_success
delete :destroy, {:id => notes(:open_note_with_comment).id, :text => "This is a hide comment", :format => "json"}
assert_response :unauthorized
basic_authorization(users(:public_user).email, "test")
delete :destroy, {:id => notes(:open_note_with_comment).id, :text => "This is a hide comment", :format => "json"}
assert_response :forbidden
basic_authorization(users(:moderator_user).email, "test")
delete :destroy, {:id => notes(:open_note_with_comment).id, :text => "This is a hide comment", :format => "json"}
assert_response :success
js = ActiveSupport::JSON.decode(@response.body)
assert_not_nil js
assert_equal "Feature", js["type"]
assert_equal notes(:open_note_with_comment).id, js["properties"]["id"]
assert_equal "hidden", js["properties"]["status"]
assert_equal 3, js["properties"]["comments"].count
assert_equal "hidden", js["properties"]["comments"].last["action"]
assert_equal "This is a hide comment", js["properties"]["comments"].last["text"]
assert_equal "moderator", js["properties"]["comments"].last["user"]
get :show, {:id => notes(:open_note_with_comment).id, :format => 'json'}
assert_response :gone
end
def test_destroy_fail
delete :destroy, {:id => 12345, :format => "json"}
assert_response :unauthorized
basic_authorization(users(:public_user).email, "test")
delete :destroy, {:id => 12345, :format => "json"}
assert_response :forbidden
basic_authorization(users(:moderator_user).email, "test")
delete :destroy, {:id => 12345, :format => "json"}
assert_response :not_found
delete :destroy, {:id => notes(:hidden_note_with_comment).id, :format => "json"}
assert_response :gone
end
def test_index_success
get :index, {:bbox => '1,1,1.2,1.2', :format => 'rss'}
assert_response :success
assert_equal "application/rss+xml", @response.content_type
assert_select "rss", :count => 1 do
assert_select "channel", :count => 1 do
assert_select "item", :count => 2
end
end
get :index, {:bbox => '1,1,1.2,1.2', :format => 'json'}
assert_response :success
assert_equal "application/json", @response.content_type
js = ActiveSupport::JSON.decode(@response.body)
assert_not_nil js
assert_equal "FeatureCollection", js["type"]
assert_equal 2, js["features"].count
get :index, {:bbox => '1,1,1.2,1.2', :format => 'xml'}
assert_response :success
assert_equal "application/xml", @response.content_type
assert_select "osm", :count => 1 do
assert_select "note", :count => 2
end
get :index, {:bbox => '1,1,1.2,1.2', :format => 'gpx'}
assert_response :success
assert_equal "application/gpx+xml", @response.content_type
assert_select "gpx", :count => 1 do
assert_select "wpt", :count => 2
end
end
def test_index_empty_area
get :index, {:bbox => '5,5,5.1,5.1', :format => 'rss'}
assert_response :success
assert_equal "application/rss+xml", @response.content_type
assert_select "rss", :count => 1 do
assert_select "channel", :count => 1 do
assert_select "item", :count => 0
end
end
get :index, {:bbox => '5,5,5.1,5.1', :format => 'json'}
assert_response :success
assert_equal "application/json", @response.content_type
js = ActiveSupport::JSON.decode(@response.body)
assert_not_nil js
assert_equal "FeatureCollection", js["type"]
assert_equal 0, js["features"].count
get :index, {:bbox => '5,5,5.1,5.1', :format => 'xml'}
assert_response :success
assert_equal "application/xml", @response.content_type
assert_select "osm", :count => 1 do
assert_select "note", :count => 0
end
get :index, {:bbox => '5,5,5.1,5.1', :format => 'gpx'}
assert_response :success
assert_equal "application/gpx+xml", @response.content_type
assert_select "gpx", :count => 1 do
assert_select "wpt", :count => 0
end
end
def test_index_large_area
get :index, {:bbox => '-2.5,-2.5,2.5,2.5', :format => :json}
assert_response :success
assert_equal "application/json", @response.content_type
get :index, {:l => '-2.5', :b => '-2.5', :r => '2.5', :t => '2.5', :format => :json}
assert_response :success
assert_equal "application/json", @response.content_type
get :index, {:bbox => '-10,-10,12,12', :format => :json}
assert_response :bad_request
assert_equal "text/plain", @response.content_type
get :index, {:l => '-10', :b => '-10', :r => '12', :t => '12', :format => :json}
assert_response :bad_request
assert_equal "text/plain", @response.content_type
end
def test_index_closed
get :index, {:bbox => '1,1,1.7,1.7', :closed => '7', :format => 'json'}
assert_response :success
assert_equal "application/json", @response.content_type
js = ActiveSupport::JSON.decode(@response.body)
assert_not_nil js
assert_equal "FeatureCollection", js["type"]
assert_equal 4, js["features"].count
get :index, {:bbox => '1,1,1.7,1.7', :closed => '0', :format => 'json'}
assert_response :success
assert_equal "application/json", @response.content_type
js = ActiveSupport::JSON.decode(@response.body)
assert_not_nil js
assert_equal "FeatureCollection", js["type"]
assert_equal 4, js["features"].count
get :index, {:bbox => '1,1,1.7,1.7', :closed => '-1', :format => 'json'}
assert_response :success
assert_equal "application/json", @response.content_type
js = ActiveSupport::JSON.decode(@response.body)
assert_not_nil js
assert_equal "FeatureCollection", js["type"]
assert_equal 6, js["features"].count
end
def test_index_bad_params
get :index, {:bbox => '-2.5,-2.5,2.5'}
assert_response :bad_request
get :index, {:bbox => '-2.5,-2.5,2.5,2.5,2.5'}
assert_response :bad_request
get :index, {:b => '-2.5', :r => '2.5', :t => '2.5'}
assert_response :bad_request
get :index, {:l => '-2.5', :r => '2.5', :t => '2.5'}
assert_response :bad_request
get :index, {:l => '-2.5', :b => '-2.5', :t => '2.5'}
assert_response :bad_request
get :index, {:l => '-2.5', :b => '-2.5', :r => '2.5'}
assert_response :bad_request
get :index, {:bbox => '1,1,1.7,1.7', :limit => '0', :format => 'json'}
assert_response :bad_request
get :index, {:bbox => '1,1,1.7,1.7', :limit => '10001', :format => 'json'}
assert_response :bad_request
end
def test_search_success
get :search, {:q => 'note 1', :format => 'xml'}
assert_response :success
assert_equal "application/xml", @response.content_type
assert_select "osm", :count => 1 do
assert_select "note", :count => 1
end
get :search, {:q => 'note 1', :format => 'json'}
assert_response :success
assert_equal "application/json", @response.content_type
js = ActiveSupport::JSON.decode(@response.body)
assert_not_nil js
assert_equal "FeatureCollection", js["type"]
assert_equal 1, js["features"].count
get :search, {:q => 'note 1', :format => 'rss'}
assert_response :success
assert_equal "application/rss+xml", @response.content_type
assert_select "rss", :count => 1 do
assert_select "channel", :count => 1 do
assert_select "item", :count => 1
end
end
get :search, {:q => 'note 1', :format => 'gpx'}
assert_response :success
assert_equal "application/gpx+xml", @response.content_type
assert_select "gpx", :count => 1 do
assert_select "wpt", :count => 1
end
end
def test_search_no_match
get :search, {:q => 'no match', :format => 'xml'}
assert_response :success
assert_equal "application/xml", @response.content_type
assert_select "osm", :count => 1 do
assert_select "note", :count => 0
end
get :search, {:q => 'no match', :format => 'json'}
assert_response :success
assert_equal "application/json", @response.content_type
js = ActiveSupport::JSON.decode(@response.body)
assert_not_nil js
assert_equal "FeatureCollection", js["type"]
assert_equal 0, js["features"].count
get :search, {:q => 'no match', :format => 'rss'}
assert_response :success
assert_equal "application/rss+xml", @response.content_type
assert_select "rss", :count => 1 do
assert_select "channel", :count => 1 do
assert_select "item", :count => 0
end
end
get :search, {:q => 'no match', :format => 'gpx'}
assert_response :success
assert_equal "application/gpx+xml", @response.content_type
assert_select "gpx", :count => 1 do
assert_select "wpt", :count => 0
end
end
def test_search_bad_params
get :search
assert_response :bad_request
get :search, {:q => 'no match', :limit => '0', :format => 'json'}
assert_response :bad_request
get :search, {:q => 'no match', :limit => '10001', :format => 'json'}
assert_response :bad_request
end
def test_feed_success
get :feed, {:format => "rss"}
assert_response :success
assert_equal "application/rss+xml", @response.content_type
assert_select "rss", :count => 1 do
assert_select "channel", :count => 1 do
assert_select "item", :count => 8
end
end
get :feed, {:bbox => "1,1,1.2,1.2", :format => "rss"}
assert_response :success
assert_equal "application/rss+xml", @response.content_type
assert_select "rss", :count => 1 do
assert_select "channel", :count => 1 do
assert_select "item", :count => 3
end
end
end
def test_feed_fail
get :feed, {:bbox => "1,1,1.2", :format => "rss"}
assert_response :bad_request
get :feed, {:bbox => "1,1,1.2,1.2,1.2", :format => "rss"}
assert_response :bad_request
get :feed, {:bbox => "1,1,1.2,1.2", :limit => '0', :format => "rss"}
assert_response :bad_request
get :feed, {:bbox => "1,1,1.2,1.2", :limit => '10001', :format => "rss"}
assert_response :bad_request
end
def test_mine_success
get :mine, {:display_name => "test"}
assert_response :success
get :mine, {:display_name => "pulibc_test2"}
assert_response :success
get :mine, {:display_name => "non-existent"}
assert_response :not_found
end
end

View file

@ -0,0 +1,211 @@
require 'test_helper'
class OauthClientsControllerTest < ActionController::TestCase
fixtures :users, :client_applications
##
# test all routes which lead to this controller
def test_routes
assert_routing(
{ :path => "/user/username/oauth_clients", :method => :get },
{ :controller => "oauth_clients", :action => "index", :display_name => "username" }
)
assert_routing(
{ :path => "/user/username/oauth_clients/new", :method => :get },
{ :controller => "oauth_clients", :action => "new", :display_name => "username" }
)
assert_routing(
{ :path => "/user/username/oauth_clients", :method => :post },
{ :controller => "oauth_clients", :action => "create", :display_name => "username" }
)
assert_routing(
{ :path => "/user/username/oauth_clients/1", :method => :get },
{ :controller => "oauth_clients", :action => "show", :display_name => "username", :id => "1" }
)
assert_routing(
{ :path => "/user/username/oauth_clients/1/edit", :method => :get },
{ :controller => "oauth_clients", :action => "edit", :display_name => "username", :id => "1" }
)
assert_routing(
{ :path => "/user/username/oauth_clients/1", :method => :put },
{ :controller => "oauth_clients", :action => "update", :display_name => "username", :id => "1" }
)
assert_routing(
{ :path => "/user/username/oauth_clients/1", :method => :delete },
{ :controller => "oauth_clients", :action => "destroy", :display_name => "username", :id => "1" }
)
end
def test_index
user = users(:public_user)
get :index, { :display_name => user.display_name }
assert_response :redirect
assert_redirected_to login_path(:referer => oauth_clients_path(:display_name => user.display_name))
get :index, { :display_name => user.display_name }, { :user => user }
assert_response :success
assert_template "index"
assert_select "div.client_application", 2
end
def test_new
user = users(:public_user)
get :new, { :display_name => user.display_name }
assert_response :redirect
assert_redirected_to login_path(:referer => new_oauth_client_path(:display_name => user.display_name))
get :new, { :display_name => user.display_name }, { :user => user }
assert_response :success
assert_template "new"
assert_select "form", 1 do
assert_select "input#client_application_name", 1
assert_select "input#client_application_url", 1
assert_select "input#client_application_callback_url", 1
assert_select "input#client_application_support_url", 1
ClientApplication.all_permissions.each do |perm|
assert_select "input#client_application_#{perm}", 1
end
end
end
def test_create
user = users(:public_user)
assert_difference "ClientApplication.count", 0 do
post :create, { :display_name => user.display_name }
end
assert_response :forbidden
assert_difference "ClientApplication.count", 0 do
post :create, {
:display_name => user.display_name,
:client_application => {
:name => "Test Application"
}
}, {
:user => user
}
end
assert_response :success
assert_template "new"
assert_difference "ClientApplication.count", 1 do
post :create, {
:display_name => user.display_name,
:client_application => {
:name => "Test Application",
:url => "http://test.example.com/"
}
}, {
:user => user
}
end
assert_response :redirect
assert_redirected_to oauth_client_path(:id => ClientApplication.find_by_name("Test Application").id)
end
def test_show
user = users(:public_user)
client = client_applications(:oauth_web_app)
get :show, { :display_name => user.display_name, :id => client.id }
assert_response :redirect
assert_redirected_to login_path(:referer => oauth_client_path(:display_name => user.display_name, :id => client.id))
get :show, { :display_name => user.display_name, :id => client_applications(:normal_user_app).id }, { :user => user }
assert_response :not_found
assert_template "not_found"
get :show, { :display_name => user.display_name, :id => client.id }, { :user => user }
assert_response :success
assert_template "show"
end
def test_edit
user = users(:public_user)
client = client_applications(:oauth_web_app)
get :edit, { :display_name => user.display_name, :id => client.id }
assert_response :redirect
assert_redirected_to login_path(:referer => edit_oauth_client_path(:display_name => user.display_name, :id => client.id))
get :edit, { :display_name => user.display_name, :id => client_applications(:normal_user_app).id }, { :user => user }
assert_response :not_found
assert_template "not_found"
get :edit, { :display_name => user.display_name, :id => client.id }, { :user => user }
assert_response :success
assert_template "edit"
assert_select "form", 1 do
assert_select "input#client_application_name", 1
assert_select "input#client_application_url", 1
assert_select "input#client_application_callback_url", 1
assert_select "input#client_application_support_url", 1
ClientApplication.all_permissions.each do |perm|
assert_select "input#client_application_#{perm}", 1
end
end
end
def test_update
user = users(:public_user)
client = client_applications(:oauth_web_app)
put :update, { :display_name => user.display_name, :id => client.id }
assert_response :forbidden
put :update, { :display_name => user.display_name, :id => client_applications(:normal_user_app).id }, { :user => user }
assert_response :not_found
assert_template "not_found"
put :update, {
:display_name => user.display_name,
:id => client.id,
:client_application => {
:name => "New Name",
:url => nil
}
}, {
:user => user
}
assert_response :success
assert_template "edit"
put :update, {
:display_name => user.display_name,
:id => client.id,
:client_application => {
:name => "New Name",
:url => "http://new.example.com/url"
}
}, {
:user => user
}
assert_response :redirect
assert_redirected_to oauth_client_path(:id => client.id)
end
def test_destroy
user = users(:public_user)
client = client_applications(:oauth_web_app)
assert_difference "ClientApplication.count", 0 do
delete :destroy, { :display_name => user.display_name, :id => client.id }
end
assert_response :forbidden
assert_difference "ClientApplication.count", 0 do
delete :destroy, { :display_name => user.display_name, :id => client_applications(:normal_user_app).id }, { :user => user }
end
assert_response :not_found
assert_template "not_found"
assert_difference "ClientApplication.count", -1 do
delete :destroy, { :display_name => user.display_name, :id => client.id }, { :user => user }
end
assert_response :redirect
assert_redirected_to oauth_clients_path(:display_name => user.display_name)
end
end

View file

@ -0,0 +1,48 @@
require 'test_helper'
class OauthControllerTest < ActionController::TestCase
##
# test all routes which lead to this controller
def test_routes
assert_routing(
{ :path => "/oauth/revoke", :method => :get },
{ :controller => "oauth", :action => "revoke" }
)
assert_routing(
{ :path => "/oauth/revoke", :method => :post },
{ :controller => "oauth", :action => "revoke" }
)
assert_routing(
{ :path => "/oauth/authorize", :method => :get },
{ :controller => "oauth", :action => "authorize" }
)
assert_routing(
{ :path => "/oauth/authorize", :method => :post },
{ :controller => "oauth", :action => "authorize" }
)
assert_routing(
{ :path => "/oauth/token", :method => :get },
{ :controller => "oauth", :action => "token" }
)
assert_routing(
{ :path => "/oauth/request_token", :method => :get },
{ :controller => "oauth", :action => "request_token" }
)
assert_routing(
{ :path => "/oauth/request_token", :method => :post },
{ :controller => "oauth", :action => "request_token" }
)
assert_routing(
{ :path => "/oauth/access_token", :method => :get },
{ :controller => "oauth", :action => "access_token" }
)
assert_routing(
{ :path => "/oauth/access_token", :method => :post },
{ :controller => "oauth", :action => "access_token" }
)
assert_routing(
{ :path => "/oauth/test_request", :method => :get },
{ :controller => "oauth", :action => "test_request" }
)
end
end

View file

@ -0,0 +1,328 @@
require 'test_helper'
require 'old_node_controller'
class OldNodeControllerTest < ActionController::TestCase
api_fixtures
#
# TODO: test history
#
##
# test all routes which lead to this controller
def test_routes
assert_routing(
{ :path => "/api/0.6/node/1/history", :method => :get },
{ :controller => "old_node", :action => "history", :id => "1" }
)
assert_routing(
{ :path => "/api/0.6/node/1/2", :method => :get },
{ :controller => "old_node", :action => "version", :id => "1", :version => "2" }
)
assert_routing(
{ :path => "/api/0.6/node/1/2/redact", :method => :post },
{ :controller => "old_node", :action => "redact", :id => "1", :version => "2" }
)
end
##
# test the version call by submitting several revisions of a new node
# to the API and ensuring that later calls to version return the
# matching versions of the object.
#
##
# FIXME Move this test to being an integration test since it spans multiple controllers
def test_version
## First try this with a non-public user
basic_authorization(users(:normal_user).email, "test")
changeset_id = changesets(:normal_user_first_change).id
# setup a simple XML node
xml_doc = current_nodes(:visible_node).to_xml
xml_node = xml_doc.find("//osm/node").first
nodeid = current_nodes(:visible_node).id
# keep a hash of the versions => string, as we'll need something
# to test against later
versions = Hash.new
# save a version for later checking
versions[xml_node['version']] = xml_doc.to_s
# randomly move the node about
20.times do
# move the node somewhere else
xml_node['lat'] = precision(rand * 180 - 90).to_s
xml_node['lon'] = precision(rand * 360 - 180).to_s
with_controller(NodeController.new) do
content xml_doc
put :update, :id => nodeid
assert_response :forbidden, "Should have rejected node update"
xml_node['version'] = @response.body.to_s
end
# save a version for later checking
versions[xml_node['version']] = xml_doc.to_s
end
# add a bunch of random tags
30.times do
xml_tag = XML::Node.new("tag")
xml_tag['k'] = random_string
xml_tag['v'] = random_string
xml_node << xml_tag
with_controller(NodeController.new) do
content xml_doc
put :update, :id => nodeid
assert_response :forbidden,
"should have rejected node #{nodeid} (#{@response.body}) with forbidden"
xml_node['version'] = @response.body.to_s
end
# save a version for later checking
versions[xml_node['version']] = xml_doc.to_s
end
# probably should check that they didn't get written to the database
## Now do it with the public user
basic_authorization(users(:public_user).email, "test")
changeset_id = changesets(:public_user_first_change).id
# setup a simple XML node
xml_doc = current_nodes(:node_with_versions).to_xml
xml_node = xml_doc.find("//osm/node").first
nodeid = current_nodes(:node_with_versions).id
# keep a hash of the versions => string, as we'll need something
# to test against later
versions = Hash.new
# save a version for later checking
versions[xml_node['version']] = xml_doc.to_s
# randomly move the node about
20.times do
# move the node somewhere else
xml_node['lat'] = precision(rand * 180 - 90).to_s
xml_node['lon'] = precision(rand * 360 - 180).to_s
with_controller(NodeController.new) do
content xml_doc
put :update, :id => nodeid
assert_response :success
xml_node['version'] = @response.body.to_s
end
# save a version for later checking
versions[xml_node['version']] = xml_doc.to_s
end
# add a bunch of random tags
30.times do
xml_tag = XML::Node.new("tag")
xml_tag['k'] = random_string
xml_tag['v'] = random_string
xml_node << xml_tag
with_controller(NodeController.new) do
content xml_doc
put :update, :id => nodeid
assert_response :success,
"couldn't update node #{nodeid} (#{@response.body})"
xml_node['version'] = @response.body.to_s
end
# save a version for later checking
versions[xml_node['version']] = xml_doc.to_s
end
# check all the versions
versions.keys.each do |key|
get :version, :id => nodeid, :version => key.to_i
assert_response :success,
"couldn't get version #{key.to_i} of node #{nodeid}"
check_node = Node.from_xml(versions[key])
api_node = Node.from_xml(@response.body.to_s)
assert_nodes_are_equal check_node, api_node
end
end
def test_not_found_version
check_not_found_id_version(70000,312344)
check_not_found_id_version(-1, -13)
check_not_found_id_version(nodes(:visible_node).id, 24354)
check_not_found_id_version(24356, nodes(:visible_node).version)
end
def check_not_found_id_version(id, version)
get :version, :id => id, :version => version
assert_response :not_found
rescue ActionController::UrlGenerationError => ex
assert_match /No route matches/, ex.to_s
end
##
# Test that getting the current version is identical to picking
# that version with the version URI call.
def test_current_version
check_current_version(current_nodes(:visible_node))
check_current_version(current_nodes(:used_node_1))
check_current_version(current_nodes(:used_node_2))
check_current_version(current_nodes(:node_used_by_relationship))
check_current_version(current_nodes(:node_with_versions))
end
##
# test the redaction of an old version of a node, while not being
# authorised.
def test_redact_node_unauthorised
do_redact_node(nodes(:node_with_versions_v3),
redactions(:example))
assert_response :unauthorized, "should need to be authenticated to redact."
end
##
# test the redaction of an old version of a node, while being
# authorised as a normal user.
def test_redact_node_normal_user
basic_authorization(users(:public_user).email, "test")
do_redact_node(nodes(:node_with_versions_v3),
redactions(:example))
assert_response :forbidden, "should need to be moderator to redact."
end
##
# test that, even as moderator, the current version of a node
# can't be redacted.
def test_redact_node_current_version
basic_authorization(users(:moderator_user).email, "test")
do_redact_node(nodes(:node_with_versions_v4),
redactions(:example))
assert_response :bad_request, "shouldn't be OK to redact current version as moderator."
end
##
# test that redacted nodes aren't visible, regardless of
# authorisation except as moderator...
def test_version_redacted
node = nodes(:redacted_node_redacted_version)
get :version, :id => node.node_id, :version => node.version
assert_response :forbidden, "Redacted node shouldn't be visible via the version API."
# not even to a logged-in user
basic_authorization(users(:public_user).email, "test")
get :version, :id => node.node_id, :version => node.version
assert_response :forbidden, "Redacted node shouldn't be visible via the version API, even when logged in."
end
##
# test that redacted nodes aren't visible in the history
def test_history_redacted
node = nodes(:redacted_node_redacted_version)
get :history, :id => node.node_id
assert_response :success, "Redaction shouldn't have stopped history working."
assert_select "osm node[id=#{node.node_id}][version=#{node.version}]", 0, "redacted node #{node.node_id} version #{node.version} shouldn't be present in the history."
# not even to a logged-in user
basic_authorization(users(:public_user).email, "test")
get :history, :id => node.node_id
assert_response :success, "Redaction shouldn't have stopped history working."
assert_select "osm node[id=#{node.node_id}][version=#{node.version}]", 0, "redacted node #{node.node_id} version #{node.version} shouldn't be present in the history, even when logged in."
end
##
# test the redaction of an old version of a node, while being
# authorised as a moderator.
def test_redact_node_moderator
node = nodes(:node_with_versions_v3)
basic_authorization(users(:moderator_user).email, "test")
do_redact_node(node, redactions(:example))
assert_response :success, "should be OK to redact old version as moderator."
# check moderator can still see the redacted data, when passing
# the appropriate flag
get :version, :id => node.node_id, :version => node.version
assert_response :forbidden, "After redaction, node should be gone for moderator, when flag not passed."
get :version, :id => node.node_id, :version => node.version, :show_redactions => 'true'
assert_response :success, "After redaction, node should not be gone for moderator, when flag passed."
# and when accessed via history
get :history, :id => node.node_id
assert_response :success, "Redaction shouldn't have stopped history working."
assert_select "osm node[id=#{node.node_id}][version=#{node.version}]", 0, "node #{node.node_id} version #{node.version} should not be present in the history for moderators when not passing flag."
get :history, :id => node.node_id, :show_redactions => 'true'
assert_response :success, "Redaction shouldn't have stopped history working."
assert_select "osm node[id=#{node.node_id}][version=#{node.version}]", 1, "node #{node.node_id} version #{node.version} should still be present in the history for moderators when passing flag."
end
# testing that if the moderator drops auth, he can't see the
# redacted stuff any more.
def test_redact_node_is_redacted
node = nodes(:node_with_versions_v3)
basic_authorization(users(:moderator_user).email, "test")
do_redact_node(node, redactions(:example))
assert_response :success, "should be OK to redact old version as moderator."
# re-auth as non-moderator
basic_authorization(users(:public_user).email, "test")
# check can't see the redacted data
get :version, :id => node.node_id, :version => node.version
assert_response :forbidden, "Redacted node shouldn't be visible via the version API."
# and when accessed via history
get :history, :id => node.node_id
assert_response :success, "Redaction shouldn't have stopped history working."
assert_select "osm node[id=#{node.node_id}][version=#{node.version}]", 0, "redacted node #{node.node_id} version #{node.version} shouldn't be present in the history."
end
def do_redact_node(node, redaction)
get :version, :id => node.node_id, :version => node.version
assert_response :success, "should be able to get version #{node.version} of node #{node.node_id}."
# now redact it
post :redact, :id => node.node_id, :version => node.version, :redaction => redaction.id
end
def check_current_version(node_id)
# get the current version of the node
current_node = with_controller(NodeController.new) do
get :read, :id => node_id
assert_response :success, "cant get current node #{node_id}"
Node.from_xml(@response.body)
end
assert_not_nil current_node, "getting node #{node_id} returned nil"
# get the "old" version of the node from the old_node interface
get :version, :id => node_id, :version => current_node.version
assert_response :success, "cant get old node #{node_id}, v#{current_node.version}"
old_node = Node.from_xml(@response.body)
# check the nodes are the same
assert_nodes_are_equal current_node, old_node
end
##
# returns a 16 character long string with some nasty characters in it.
# this ought to stress-test the tag handling as well as the versioning.
def random_string
letters = [['!','"','$','&',';','@'],
('a'..'z').to_a,
('A'..'Z').to_a,
('0'..'9').to_a].flatten
(1..16).map { |i| letters[ rand(letters.length) ] }.join
end
##
# truncate a floating point number to the scale that it is stored in
# the database. otherwise rounding errors can produce failing unit
# tests when they shouldn't.
def precision(f)
return (f * GeoRecord::SCALE).round.to_f / GeoRecord::SCALE
end
end

View file

@ -0,0 +1,198 @@
require 'test_helper'
require 'old_relation_controller'
class OldRelationControllerTest < ActionController::TestCase
api_fixtures
##
# test all routes which lead to this controller
def test_routes
assert_routing(
{ :path => "/api/0.6/relation/1/history", :method => :get },
{ :controller => "old_relation", :action => "history", :id => "1" }
)
assert_routing(
{ :path => "/api/0.6/relation/1/2", :method => :get },
{ :controller => "old_relation", :action => "version", :id => "1", :version => "2" }
)
assert_routing(
{ :path => "/api/0.6/relation/1/2/redact", :method => :post },
{ :controller => "old_relation", :action => "redact", :id => "1", :version => "2" }
)
end
# -------------------------------------
# Test reading old relations.
# -------------------------------------
def test_history
# check that a visible relations is returned properly
get :history, :id => relations(:visible_relation).relation_id
assert_response :success
# check chat a non-existent relations is not returned
get :history, :id => 0
assert_response :not_found
end
##
# test the redaction of an old version of a relation, while not being
# authorised.
def test_redact_relation_unauthorised
do_redact_relation(relations(:relation_with_versions_v3),
redactions(:example))
assert_response :unauthorized, "should need to be authenticated to redact."
end
##
# test the redaction of an old version of a relation, while being
# authorised as a normal user.
def test_redact_relation_normal_user
basic_authorization(users(:public_user).email, "test")
do_redact_relation(relations(:relation_with_versions_v3),
redactions(:example))
assert_response :forbidden, "should need to be moderator to redact."
end
##
# test that, even as moderator, the current version of a relation
# can't be redacted.
def test_redact_relation_current_version
basic_authorization(users(:moderator_user).email, "test")
do_redact_relation(relations(:relation_with_versions_v4),
redactions(:example))
assert_response :bad_request, "shouldn't be OK to redact current version as moderator."
end
##
# test that redacted relations aren't visible, regardless of
# authorisation except as moderator...
def test_version_redacted
relation = relations(:relation_with_redacted_versions_v2)
get :version, :id => relation.relation_id, :version => relation.version
assert_response :forbidden, "Redacted node shouldn't be visible via the version API."
# not even to a logged-in user
basic_authorization(users(:public_user).email, "test")
get :version, :id => relation.relation_id, :version => relation.version
assert_response :forbidden, "Redacted node shouldn't be visible via the version API, even when logged in."
end
##
# test that redacted nodes aren't visible in the history
def test_history_redacted
relation = relations(:relation_with_redacted_versions_v2)
get :history, :id => relation.relation_id
assert_response :success, "Redaction shouldn't have stopped history working."
assert_select "osm relation[id=#{relation.relation_id}][version=#{relation.version}]", 0, "redacted relation #{relation.relation_id} version #{relation.version} shouldn't be present in the history."
# not even to a logged-in user
basic_authorization(users(:public_user).email, "test")
get :version, :id => relation.relation_id, :version => relation.version
get :history, :id => relation.relation_id
assert_response :success, "Redaction shouldn't have stopped history working."
assert_select "osm relation[id=#{relation.relation_id}][version=#{relation.version}]", 0, "redacted node #{relation.relation_id} version #{relation.version} shouldn't be present in the history, even when logged in."
end
##
# test the redaction of an old version of a relation, while being
# authorised as a moderator.
def test_redact_relation_moderator
relation = relations(:relation_with_versions_v3)
basic_authorization(users(:moderator_user).email, "test")
do_redact_relation(relation, redactions(:example))
assert_response :success, "should be OK to redact old version as moderator."
# check moderator can still see the redacted data, when passing
# the appropriate flag
get :version, :id => relation.relation_id, :version => relation.version
assert_response :forbidden, "After redaction, node should be gone for moderator, when flag not passed."
get :version, :id => relation.relation_id, :version => relation.version, :show_redactions => 'true'
assert_response :success, "After redaction, node should not be gone for moderator, when flag passed."
# and when accessed via history
get :history, :id => relation.relation_id
assert_response :success, "Redaction shouldn't have stopped history working."
assert_select "osm relation[id=#{relation.relation_id}][version=#{relation.version}]", 0, "relation #{relation.relation_id} version #{relation.version} should not be present in the history for moderators when not passing flag."
get :history, :id => relation.relation_id, :show_redactions => 'true'
assert_response :success, "Redaction shouldn't have stopped history working."
assert_select "osm relation[id=#{relation.relation_id}][version=#{relation.version}]", 1, "relation #{relation.relation_id} version #{relation.version} should still be present in the history for moderators when passing flag."
end
# testing that if the moderator drops auth, he can't see the
# redacted stuff any more.
def test_redact_relation_is_redacted
relation = relations(:relation_with_versions_v3)
basic_authorization(users(:moderator_user).email, "test")
do_redact_relation(relation, redactions(:example))
assert_response :success, "should be OK to redact old version as moderator."
# re-auth as non-moderator
basic_authorization(users(:public_user).email, "test")
# check can't see the redacted data
get :version, :id => relation.relation_id, :version => relation.version
assert_response :forbidden, "Redacted node shouldn't be visible via the version API."
# and when accessed via history
get :history, :id => relation.relation_id
assert_response :success, "Redaction shouldn't have stopped history working."
assert_select "osm relation[id=#{relation.relation_id}][version=#{relation.version}]", 0, "redacted relation #{relation.relation_id} version #{relation.version} shouldn't be present in the history."
end
##
# check that the current version of a relation is equivalent to the
# version which we're getting from the versions call.
def check_current_version(relation_id)
# get the current version
current_relation = with_controller(RelationController.new) do
get :read, :id => relation_id
assert_response :success, "can't get current relation #{relation_id}"
Relation.from_xml(@response.body)
end
assert_not_nil current_relation, "getting relation #{relation_id} returned nil"
# get the "old" version of the relation from the version method
get :version, :id => relation_id, :version => current_relation.version
assert_response :success, "can't get old relation #{relation_id}, v#{current_relation.version}"
old_relation = Relation.from_xml(@response.body)
# check that the relations are identical
assert_relations_are_equal current_relation, old_relation
end
##
# look at all the versions of the relation in the history and get each version from
# the versions call. check that they're the same.
def check_history_equals_versions(relation_id)
get :history, :id => relation_id
assert_response :success, "can't get relation #{relation_id} from API"
history_doc = XML::Parser.string(@response.body).parse
assert_not_nil history_doc, "parsing relation #{relation_id} history failed"
history_doc.find("//osm/relation").each do |relation_doc|
history_relation = Relation.from_xml_node(relation_doc)
assert_not_nil history_relation, "parsing relation #{relation_id} version failed"
get :version, :id => relation_id, :version => history_relation.version
assert_response :success, "couldn't get relation #{relation_id}, v#{history_relation.version}"
version_relation = Relation.from_xml(@response.body)
assert_not_nil version_relation, "failed to parse #{relation_id}, v#{history_relation.version}"
assert_relations_are_equal history_relation, version_relation
end
end
def do_redact_relation(relation, redaction)
get :version, :id => relation.relation_id, :version => relation.version
assert_response :success, "should be able to get version #{relation.version} of node #{relation.relation_id}."
# now redact it
post :redact, :id => relation.relation_id, :version => relation.version, :redaction => redaction.id
end
end

View file

@ -0,0 +1,225 @@
require 'test_helper'
require 'old_way_controller'
class OldWayControllerTest < ActionController::TestCase
api_fixtures
##
# test all routes which lead to this controller
def test_routes
assert_routing(
{ :path => "/api/0.6/way/1/history", :method => :get },
{ :controller => "old_way", :action => "history", :id => "1" }
)
assert_routing(
{ :path => "/api/0.6/way/1/2", :method => :get },
{ :controller => "old_way", :action => "version", :id => "1", :version => "2" }
)
assert_routing(
{ :path => "/api/0.6/way/1/2/redact", :method => :post },
{ :controller => "old_way", :action => "redact", :id => "1", :version => "2" }
)
end
# -------------------------------------
# Test reading old ways.
# -------------------------------------
def test_history_visible
# check that a visible way is returned properly
get :history, :id => ways(:visible_way).way_id
assert_response :success
end
def test_history_invisible
# check that an invisible way's history is returned properly
get :history, :id => ways(:invisible_way).way_id
assert_response :success
end
def test_history_invalid
# check chat a non-existent way is not returned
get :history, :id => 0
assert_response :not_found
end
##
# check that we can retrieve versions of a way
def test_version
check_current_version(current_ways(:visible_way).id)
check_current_version(current_ways(:used_way).id)
check_current_version(current_ways(:way_with_versions).id)
end
##
# check that returned history is the same as getting all
# versions of a way from the api.
def test_history_equals_versions
check_history_equals_versions(current_ways(:visible_way).id)
check_history_equals_versions(current_ways(:used_way).id)
check_history_equals_versions(current_ways(:way_with_versions).id)
end
##
# test the redaction of an old version of a way, while not being
# authorised.
def test_redact_way_unauthorised
do_redact_way(ways(:way_with_versions_v3),
redactions(:example))
assert_response :unauthorized, "should need to be authenticated to redact."
end
##
# test the redaction of an old version of a way, while being
# authorised as a normal user.
def test_redact_way_normal_user
basic_authorization(users(:public_user).email, "test")
do_redact_way(ways(:way_with_versions_v3),
redactions(:example))
assert_response :forbidden, "should need to be moderator to redact."
end
##
# test that, even as moderator, the current version of a way
# can't be redacted.
def test_redact_way_current_version
basic_authorization(users(:moderator_user).email, "test")
do_redact_way(ways(:way_with_versions_v4),
redactions(:example))
assert_response :bad_request, "shouldn't be OK to redact current version as moderator."
end
##
# test that redacted ways aren't visible, regardless of
# authorisation except as moderator...
def test_version_redacted
way = ways(:way_with_redacted_versions_v2)
get :version, :id => way.way_id, :version => way.version
assert_response :forbidden, "Redacted node shouldn't be visible via the version API."
# not even to a logged-in user
basic_authorization(users(:public_user).email, "test")
get :version, :id => way.way_id, :version => way.version
assert_response :forbidden, "Redacted node shouldn't be visible via the version API, even when logged in."
end
##
# test that redacted nodes aren't visible in the history
def test_history_redacted
way = ways(:way_with_redacted_versions_v2)
get :history, :id => way.way_id
assert_response :success, "Redaction shouldn't have stopped history working."
assert_select "osm way[id=#{way.way_id}][version=#{way.version}]", 0, "redacted way #{way.way_id} version #{way.version} shouldn't be present in the history."
# not even to a logged-in user
basic_authorization(users(:public_user).email, "test")
get :version, :id => way.way_id, :version => way.version
get :history, :id => way.way_id
assert_response :success, "Redaction shouldn't have stopped history working."
assert_select "osm way[id=#{way.way_id}][version=#{way.version}]", 0, "redacted node #{way.way_id} version #{way.version} shouldn't be present in the history, even when logged in."
end
##
# test the redaction of an old version of a way, while being
# authorised as a moderator.
def test_redact_way_moderator
way = ways(:way_with_versions_v3)
basic_authorization(users(:moderator_user).email, "test")
do_redact_way(way, redactions(:example))
assert_response :success, "should be OK to redact old version as moderator."
# check moderator can still see the redacted data, when passing
# the appropriate flag
get :version, :id => way.way_id, :version => way.version
assert_response :forbidden, "After redaction, node should be gone for moderator, when flag not passed."
get :version, :id => way.way_id, :version => way.version, :show_redactions => 'true'
assert_response :success, "After redaction, node should not be gone for moderator, when flag passed."
# and when accessed via history
get :history, :id => way.way_id
assert_response :success, "Redaction shouldn't have stopped history working."
assert_select "osm way[id=#{way.way_id}][version=#{way.version}]", 0, "way #{way.way_id} version #{way.version} should not be present in the history for moderators when not passing flag."
get :history, :id => way.way_id, :show_redactions => 'true'
assert_response :success, "Redaction shouldn't have stopped history working."
assert_select "osm way[id=#{way.way_id}][version=#{way.version}]", 1, "way #{way.way_id} version #{way.version} should still be present in the history for moderators when passing flag."
end
# testing that if the moderator drops auth, he can't see the
# redacted stuff any more.
def test_redact_way_is_redacted
way = ways(:way_with_versions_v3)
basic_authorization(users(:moderator_user).email, "test")
do_redact_way(way, redactions(:example))
assert_response :success, "should be OK to redact old version as moderator."
# re-auth as non-moderator
basic_authorization(users(:public_user).email, "test")
# check can't see the redacted data
get :version, :id => way.way_id, :version => way.version
assert_response :forbidden, "Redacted node shouldn't be visible via the version API."
# and when accessed via history
get :history, :id => way.way_id
assert_response :success, "Redaction shouldn't have stopped history working."
assert_select "osm way[id=#{way.way_id}][version=#{way.version}]", 0, "redacted way #{way.way_id} version #{way.version} shouldn't be present in the history."
end
##
# check that the current version of a way is equivalent to the
# version which we're getting from the versions call.
def check_current_version(way_id)
# get the current version
current_way = with_controller(WayController.new) do
get :read, :id => way_id
assert_response :success, "can't get current way #{way_id}"
Way.from_xml(@response.body)
end
assert_not_nil current_way, "getting way #{way_id} returned nil"
# get the "old" version of the way from the version method
get :version, :id => way_id, :version => current_way.version
assert_response :success, "can't get old way #{way_id}, v#{current_way.version}"
old_way = Way.from_xml(@response.body)
# check that the ways are identical
assert_ways_are_equal current_way, old_way
end
##
# look at all the versions of the way in the history and get each version from
# the versions call. check that they're the same.
def check_history_equals_versions(way_id)
get :history, :id => way_id
assert_response :success, "can't get way #{way_id} from API"
history_doc = XML::Parser.string(@response.body).parse
assert_not_nil history_doc, "parsing way #{way_id} history failed"
history_doc.find("//osm/way").each do |way_doc|
history_way = Way.from_xml_node(way_doc)
assert_not_nil history_way, "parsing way #{way_id} version failed"
get :version, :id => way_id, :version => history_way.version
assert_response :success, "couldn't get way #{way_id}, v#{history_way.version}"
version_way = Way.from_xml(@response.body)
assert_not_nil version_way, "failed to parse #{way_id}, v#{history_way.version}"
assert_ways_are_equal history_way, version_way
end
end
def do_redact_way(way, redaction)
get :version, :id => way.way_id, :version => way.version
assert_response :success, "should be able to get version #{way.version} of node #{way.way_id}."
# now redact it
post :redact, :id => way.way_id, :version => way.version, :redaction => redaction.id
end
end

View file

@ -0,0 +1,121 @@
require 'test_helper'
require 'redactions_controller'
class RedactionsControllerTest < ActionController::TestCase
api_fixtures
##
# test all routes which lead to this controller
def test_routes
assert_routing(
{ :path => "/redactions", :method => :get },
{ :controller => "redactions", :action => "index" }
)
assert_routing(
{ :path => "/redactions/new", :method => :get },
{ :controller => "redactions", :action => "new" }
)
assert_routing(
{ :path => "/redactions", :method => :post },
{ :controller => "redactions", :action => "create" }
)
assert_routing(
{ :path => "/redactions/1", :method => :get },
{ :controller => "redactions", :action => "show", :id => "1" }
)
assert_routing(
{ :path => "/redactions/1/edit", :method => :get },
{ :controller => "redactions", :action => "edit", :id => "1" }
)
assert_routing(
{ :path => "/redactions/1", :method => :put },
{ :controller => "redactions", :action => "update", :id => "1" }
)
assert_routing(
{ :path => "/redactions/1", :method => :delete },
{ :controller => "redactions", :action => "destroy", :id => "1" }
)
end
def test_moderators_can_create
session[:user] = users(:moderator_user).id
post :create, :redaction => { :title => "Foo", :description => "Description here." }
assert_response :redirect
assert_redirected_to(redaction_path(Redaction.find_by_title("Foo")))
end
def test_non_moderators_cant_create
session[:user] = users(:public_user).id
post :create, :redaction => { :title => "Foo", :description => "Description here." }
assert_response :forbidden
end
def test_moderators_can_delete_empty
session[:user] = users(:moderator_user).id
# remove all elements from the redaction
redaction = redactions(:example)
redaction.old_nodes.each { |n| n.redaction = nil; n.save! }
redaction.old_ways.each { |w| w.redaction = nil; w.save! }
redaction.old_relations.each { |r| r.redaction = nil; r.save! }
delete :destroy, :id => redaction.id
assert_response :redirect
assert_redirected_to(redactions_path)
end
def test_moderators_cant_delete_nonempty
session[:user] = users(:moderator_user).id
# leave elements in the redaction
redaction = redactions(:example)
delete :destroy, :id => redaction.id
assert_response :redirect
assert_redirected_to(redaction_path(redaction))
assert_match /^Redaction is not empty/, flash[:error]
end
def test_non_moderators_cant_delete
session[:user] = users(:public_user).id
delete :destroy, :id => redactions(:example).id
assert_response :forbidden
end
def test_moderators_can_edit
session[:user] = users(:moderator_user).id
get :edit, :id => redactions(:example).id
assert_response :success
end
def test_non_moderators_cant_edit
session[:user] = users(:public_user).id
get :edit, :id => redactions(:example).id
assert_response :redirect
assert_redirected_to(redactions_path)
end
def test_moderators_can_update
session[:user] = users(:moderator_user).id
redaction = redactions(:example)
put :update, :id => redaction.id, :redaction => { :title => "Foo", :description => "Description here." }
assert_response :redirect
assert_redirected_to(redaction_path(redaction))
end
def test_non_moderators_cant_update
session[:user] = users(:public_user).id
redaction = redactions(:example)
put :update, :id => redaction.id, :redaction => { :title => "Foo", :description => "Description here." }
assert_response :forbidden
end
end

View file

@ -0,0 +1,987 @@
require 'test_helper'
require 'relation_controller'
class RelationControllerTest < ActionController::TestCase
api_fixtures
##
# test all routes which lead to this controller
def test_routes
assert_routing(
{ :path => "/api/0.6/relation/create", :method => :put },
{ :controller => "relation", :action => "create" }
)
assert_routing(
{ :path => "/api/0.6/relation/1/full", :method => :get },
{ :controller => "relation", :action => "full", :id => "1" }
)
assert_routing(
{ :path => "/api/0.6/relation/1", :method => :get },
{ :controller => "relation", :action => "read", :id => "1" }
)
assert_routing(
{ :path => "/api/0.6/relation/1", :method => :put },
{ :controller => "relation", :action => "update", :id => "1" }
)
assert_routing(
{ :path => "/api/0.6/relation/1", :method => :delete },
{ :controller => "relation", :action => "delete", :id => "1" }
)
assert_routing(
{ :path => "/api/0.6/relations", :method => :get },
{ :controller => "relation", :action => "relations" }
)
assert_routing(
{ :path => "/api/0.6/node/1/relations", :method => :get },
{ :controller => "relation", :action => "relations_for_node", :id => "1" }
)
assert_routing(
{ :path => "/api/0.6/way/1/relations", :method => :get },
{ :controller => "relation", :action => "relations_for_way", :id => "1" }
)
assert_routing(
{ :path => "/api/0.6/relation/1/relations", :method => :get },
{ :controller => "relation", :action => "relations_for_relation", :id => "1" }
)
end
# -------------------------------------
# Test reading relations.
# -------------------------------------
def test_read
# check that a visible relation is returned properly
get :read, :id => current_relations(:visible_relation).id
assert_response :success
# check that an invisible relation is not returned
get :read, :id => current_relations(:invisible_relation).id
assert_response :gone
# check chat a non-existent relation is not returned
get :read, :id => 0
assert_response :not_found
end
##
# check that all relations containing a particular node, and no extra
# relations, are returned from the relations_for_node call.
def test_relations_for_node
check_relations_for_element(:relations_for_node, "node",
current_nodes(:node_used_by_relationship).id,
[ :visible_relation, :used_relation ])
end
def test_relations_for_way
check_relations_for_element(:relations_for_way, "way",
current_ways(:used_way).id,
[ :visible_relation ])
end
def test_relations_for_relation
check_relations_for_element(:relations_for_relation, "relation",
current_relations(:used_relation).id,
[ :visible_relation ])
end
def check_relations_for_element(method, type, id, expected_relations)
# check the "relations for relation" mode
get method, :id => id
assert_response :success
# count one osm element
assert_select "osm[version=#{API_VERSION}][generator=\"OpenStreetMap server\"]", 1
# we should have only the expected number of relations
assert_select "osm>relation", expected_relations.size
# and each of them should contain the node we originally searched for
expected_relations.each do |r|
relation_id = current_relations(r).id
assert_select "osm>relation#?", relation_id
assert_select "osm>relation#?>member[type=\"#{type}\"][ref=#{id}]", relation_id
end
end
def test_full
# check the "full" mode
get :full, :id => current_relations(:visible_relation).id
assert_response :success
# FIXME check whether this contains the stuff we want!
if $VERBOSE
print @response.body
end
end
##
# test fetching multiple relations
def test_relations
# check error when no parameter provided
get :relations
assert_response :bad_request
# check error when no parameter value provided
get :relations, :relations => ""
assert_response :bad_request
# test a working call
get :relations, :relations => "1,2,4,7"
assert_response :success
assert_select "osm" do
assert_select "relation", :count => 4
assert_select "relation[id=1][visible=true]", :count => 1
assert_select "relation[id=2][visible=false]", :count => 1
assert_select "relation[id=4][visible=true]", :count => 1
assert_select "relation[id=7][visible=true]", :count => 1
end
# check error when a non-existent relation is included
get :relations, :relations => "1,2,4,7,400"
assert_response :not_found
end
# -------------------------------------
# Test simple relation creation.
# -------------------------------------
def test_create
basic_authorization users(:normal_user).email, "test"
# put the relation in a dummy fixture changset
changeset_id = changesets(:normal_user_first_change).id
# create an relation without members
content "<osm><relation changeset='#{changeset_id}'><tag k='test' v='yes' /></relation></osm>"
put :create
# hope for forbidden, due to user
assert_response :forbidden,
"relation upload should have failed with forbidden"
###
# create an relation with a node as member
# This time try with a role attribute in the relation
nid = current_nodes(:used_node_1).id
content "<osm><relation changeset='#{changeset_id}'>" +
"<member ref='#{nid}' type='node' role='some'/>" +
"<tag k='test' v='yes' /></relation></osm>"
put :create
# hope for forbidden due to user
assert_response :forbidden,
"relation upload did not return forbidden status"
###
# create an relation with a node as member, this time test that we don't
# need a role attribute to be included
nid = current_nodes(:used_node_1).id
content "<osm><relation changeset='#{changeset_id}'>" +
"<member ref='#{nid}' type='node'/>"+
"<tag k='test' v='yes' /></relation></osm>"
put :create
# hope for forbidden due to user
assert_response :forbidden,
"relation upload did not return forbidden status"
###
# create an relation with a way and a node as members
nid = current_nodes(:used_node_1).id
wid = current_ways(:used_way).id
content "<osm><relation changeset='#{changeset_id}'>" +
"<member type='node' ref='#{nid}' role='some'/>" +
"<member type='way' ref='#{wid}' role='other'/>" +
"<tag k='test' v='yes' /></relation></osm>"
put :create
# hope for forbidden, due to user
assert_response :forbidden,
"relation upload did not return success status"
## Now try with the public user
basic_authorization users(:public_user).email, "test"
# put the relation in a dummy fixture changset
changeset_id = changesets(:public_user_first_change).id
# create an relation without members
content "<osm><relation changeset='#{changeset_id}'><tag k='test' v='yes' /></relation></osm>"
put :create
# hope for success
assert_response :success,
"relation upload did not return success status"
# read id of created relation and search for it
relationid = @response.body
checkrelation = Relation.find(relationid)
assert_not_nil checkrelation,
"uploaded relation not found in data base after upload"
# compare values
assert_equal checkrelation.members.length, 0,
"saved relation contains members but should not"
assert_equal checkrelation.tags.length, 1,
"saved relation does not contain exactly one tag"
assert_equal changeset_id, checkrelation.changeset.id,
"saved relation does not belong in the changeset it was assigned to"
assert_equal users(:public_user).id, checkrelation.changeset.user_id,
"saved relation does not belong to user that created it"
assert_equal true, checkrelation.visible,
"saved relation is not visible"
# ok the relation is there but can we also retrieve it?
get :read, :id => relationid
assert_response :success
###
# create an relation with a node as member
# This time try with a role attribute in the relation
nid = current_nodes(:used_node_1).id
content "<osm><relation changeset='#{changeset_id}'>" +
"<member ref='#{nid}' type='node' role='some'/>" +
"<tag k='test' v='yes' /></relation></osm>"
put :create
# hope for success
assert_response :success,
"relation upload did not return success status"
# read id of created relation and search for it
relationid = @response.body
checkrelation = Relation.find(relationid)
assert_not_nil checkrelation,
"uploaded relation not found in data base after upload"
# compare values
assert_equal checkrelation.members.length, 1,
"saved relation does not contain exactly one member"
assert_equal checkrelation.tags.length, 1,
"saved relation does not contain exactly one tag"
assert_equal changeset_id, checkrelation.changeset.id,
"saved relation does not belong in the changeset it was assigned to"
assert_equal users(:public_user).id, checkrelation.changeset.user_id,
"saved relation does not belong to user that created it"
assert_equal true, checkrelation.visible,
"saved relation is not visible"
# ok the relation is there but can we also retrieve it?
get :read, :id => relationid
assert_response :success
###
# create an relation with a node as member, this time test that we don't
# need a role attribute to be included
nid = current_nodes(:used_node_1).id
content "<osm><relation changeset='#{changeset_id}'>" +
"<member ref='#{nid}' type='node'/>"+
"<tag k='test' v='yes' /></relation></osm>"
put :create
# hope for success
assert_response :success,
"relation upload did not return success status"
# read id of created relation and search for it
relationid = @response.body
checkrelation = Relation.find(relationid)
assert_not_nil checkrelation,
"uploaded relation not found in data base after upload"
# compare values
assert_equal checkrelation.members.length, 1,
"saved relation does not contain exactly one member"
assert_equal checkrelation.tags.length, 1,
"saved relation does not contain exactly one tag"
assert_equal changeset_id, checkrelation.changeset.id,
"saved relation does not belong in the changeset it was assigned to"
assert_equal users(:public_user).id, checkrelation.changeset.user_id,
"saved relation does not belong to user that created it"
assert_equal true, checkrelation.visible,
"saved relation is not visible"
# ok the relation is there but can we also retrieve it?
get :read, :id => relationid
assert_response :success
###
# create an relation with a way and a node as members
nid = current_nodes(:used_node_1).id
wid = current_ways(:used_way).id
content "<osm><relation changeset='#{changeset_id}'>" +
"<member type='node' ref='#{nid}' role='some'/>" +
"<member type='way' ref='#{wid}' role='other'/>" +
"<tag k='test' v='yes' /></relation></osm>"
put :create
# hope for success
assert_response :success,
"relation upload did not return success status"
# read id of created relation and search for it
relationid = @response.body
checkrelation = Relation.find(relationid)
assert_not_nil checkrelation,
"uploaded relation not found in data base after upload"
# compare values
assert_equal checkrelation.members.length, 2,
"saved relation does not have exactly two members"
assert_equal checkrelation.tags.length, 1,
"saved relation does not contain exactly one tag"
assert_equal changeset_id, checkrelation.changeset.id,
"saved relation does not belong in the changeset it was assigned to"
assert_equal users(:public_user).id, checkrelation.changeset.user_id,
"saved relation does not belong to user that created it"
assert_equal true, checkrelation.visible,
"saved relation is not visible"
# ok the relation is there but can we also retrieve it?
get :read, :id => relationid
assert_response :success
end
# ------------------------------------
# Test updating relations
# ------------------------------------
##
# test that, when tags are updated on a relation, the correct things
# happen to the correct tables and the API gives sensible results.
# this is to test a case that gregory marler noticed and posted to
# josm-dev.
## FIXME Move this to an integration test
def test_update_relation_tags
basic_authorization "test@example.com", "test"
rel_id = current_relations(:multi_tag_relation).id
cs_id = changesets(:public_user_first_change).id
with_relation(rel_id) do |rel|
# alter one of the tags
tag = rel.find("//osm/relation/tag").first
tag['v'] = 'some changed value'
update_changeset(rel, cs_id)
# check that the downloaded tags are the same as the uploaded tags...
new_version = with_update(rel) do |new_rel|
assert_tags_equal rel, new_rel
end
# check the original one in the current_* table again
with_relation(rel_id) { |r| assert_tags_equal rel, r }
# now check the version in the history
with_relation(rel_id, new_version) { |r| assert_tags_equal rel, r }
end
end
##
# test that, when tags are updated on a relation when using the diff
# upload function, the correct things happen to the correct tables
# and the API gives sensible results. this is to test a case that
# gregory marler noticed and posted to josm-dev.
def test_update_relation_tags_via_upload
basic_authorization users(:public_user).email, "test"
rel_id = current_relations(:multi_tag_relation).id
cs_id = changesets(:public_user_first_change).id
with_relation(rel_id) do |rel|
# alter one of the tags
tag = rel.find("//osm/relation/tag").first
tag['v'] = 'some changed value'
update_changeset(rel, cs_id)
# check that the downloaded tags are the same as the uploaded tags...
new_version = with_update_diff(rel) do |new_rel|
assert_tags_equal rel, new_rel
end
# check the original one in the current_* table again
with_relation(rel_id) { |r| assert_tags_equal rel, r }
# now check the version in the history
with_relation(rel_id, new_version) { |r| assert_tags_equal rel, r }
end
end
# -------------------------------------
# Test creating some invalid relations.
# -------------------------------------
def test_create_invalid
basic_authorization users(:public_user).email, "test"
# put the relation in a dummy fixture changset
changeset_id = changesets(:public_user_first_change).id
# create a relation with non-existing node as member
content "<osm><relation changeset='#{changeset_id}'>" +
"<member type='node' ref='0'/><tag k='test' v='yes' />" +
"</relation></osm>"
put :create
# expect failure
assert_response :precondition_failed,
"relation upload with invalid node did not return 'precondition failed'"
assert_equal "Precondition failed: Relation with id cannot be saved due to Node with id 0", @response.body
end
# -------------------------------------
# Test creating a relation, with some invalid XML
# -------------------------------------
def test_create_invalid_xml
basic_authorization users(:public_user).email, "test"
# put the relation in a dummy fixture changeset that works
changeset_id = changesets(:public_user_first_change).id
# create some xml that should return an error
content "<osm><relation changeset='#{changeset_id}'>" +
"<member type='type' ref='#{current_nodes(:used_node_1).id}' role=''/>" +
"<tag k='tester' v='yep'/></relation></osm>"
put :create
# expect failure
assert_response :bad_request
assert_match(/Cannot parse valid relation from xml string/, @response.body)
assert_match(/The type is not allowed only, /, @response.body)
end
# -------------------------------------
# Test deleting relations.
# -------------------------------------
def test_delete
## First try to delete relation without auth
delete :delete, :id => current_relations(:visible_relation).id
assert_response :unauthorized
## Then try with the private user, to make sure that you get a forbidden
basic_authorization(users(:normal_user).email, "test")
# this shouldn't work, as we should need the payload...
delete :delete, :id => current_relations(:visible_relation).id
assert_response :forbidden
# try to delete without specifying a changeset
content "<osm><relation id='#{current_relations(:visible_relation).id}'/></osm>"
delete :delete, :id => current_relations(:visible_relation).id
assert_response :forbidden
# try to delete with an invalid (closed) changeset
content update_changeset(current_relations(:visible_relation).to_xml,
changesets(:normal_user_closed_change).id)
delete :delete, :id => current_relations(:visible_relation).id
assert_response :forbidden
# try to delete with an invalid (non-existent) changeset
content update_changeset(current_relations(:visible_relation).to_xml,0)
delete :delete, :id => current_relations(:visible_relation).id
assert_response :forbidden
# this won't work because the relation is in-use by another relation
content(relations(:used_relation).to_xml)
delete :delete, :id => current_relations(:used_relation).id
assert_response :forbidden
# this should work when we provide the appropriate payload...
content(relations(:visible_relation).to_xml)
delete :delete, :id => current_relations(:visible_relation).id
assert_response :forbidden
# this won't work since the relation is already deleted
content(relations(:invisible_relation).to_xml)
delete :delete, :id => current_relations(:invisible_relation).id
assert_response :forbidden
# this works now because the relation which was using this one
# has been deleted.
content(relations(:used_relation).to_xml)
delete :delete, :id => current_relations(:used_relation).id
assert_response :forbidden
# this won't work since the relation never existed
delete :delete, :id => 0
assert_response :forbidden
## now set auth for the public user
basic_authorization(users(:public_user).email, "test");
# this shouldn't work, as we should need the payload...
delete :delete, :id => current_relations(:visible_relation).id
assert_response :bad_request
# try to delete without specifying a changeset
content "<osm><relation id='#{current_relations(:visible_relation).id}' version='#{current_relations(:visible_relation).version}' /></osm>"
delete :delete, :id => current_relations(:visible_relation).id
assert_response :bad_request
assert_match(/Changeset id is missing/, @response.body)
# try to delete with an invalid (closed) changeset
content update_changeset(current_relations(:visible_relation).to_xml,
changesets(:normal_user_closed_change).id)
delete :delete, :id => current_relations(:visible_relation).id
assert_response :conflict
# try to delete with an invalid (non-existent) changeset
content update_changeset(current_relations(:visible_relation).to_xml,0)
delete :delete, :id => current_relations(:visible_relation).id
assert_response :conflict
# this won't work because the relation is in a changeset owned by someone else
content(relations(:used_relation).to_xml)
delete :delete, :id => current_relations(:used_relation).id
assert_response :conflict,
"shouldn't be able to delete a relation in a changeset owned by someone else (#{@response.body})"
# this won't work because the relation in the payload is different to that passed
content(relations(:public_used_relation).to_xml)
delete :delete, :id => current_relations(:used_relation).id
assert_not_equal relations(:public_used_relation).id, current_relations(:used_relation).id
assert_response :bad_request, "shouldn't be able to delete a relation when payload is different to the url"
# this won't work because the relation is in-use by another relation
content(relations(:public_used_relation).to_xml)
delete :delete, :id => current_relations(:public_used_relation).id
assert_response :precondition_failed,
"shouldn't be able to delete a relation used in a relation (#{@response.body})"
assert_equal "Precondition failed: The relation 5 is used in relation 6.", @response.body
# this should work when we provide the appropriate payload...
content(relations(:multi_tag_relation).to_xml)
delete :delete, :id => current_relations(:multi_tag_relation).id
assert_response :success
# valid delete should return the new version number, which should
# be greater than the old version number
assert @response.body.to_i > current_relations(:visible_relation).version,
"delete request should return a new version number for relation"
# this won't work since the relation is already deleted
content(relations(:invisible_relation).to_xml)
delete :delete, :id => current_relations(:invisible_relation).id
assert_response :gone
# Public visible relation needs to be deleted
content(relations(:public_visible_relation).to_xml)
delete :delete, :id => current_relations(:public_visible_relation).id
assert_response :success
# this works now because the relation which was using this one
# has been deleted.
content(relations(:public_used_relation).to_xml)
delete :delete, :id => current_relations(:public_used_relation).id
assert_response :success,
"should be able to delete a relation used in an old relation (#{@response.body})"
# this won't work since the relation never existed
delete :delete, :id => 0
assert_response :not_found
end
##
# when a relation's tag is modified then it should put the bounding
# box of all its members into the changeset.
def test_tag_modify_bounding_box
# in current fixtures, relation 5 contains nodes 3 and 5 (node 3
# indirectly via way 3), so the bbox should be [3,3,5,5].
check_changeset_modify(BoundingBox.new(3,3,5,5)) do |changeset_id|
# add a tag to an existing relation
relation_xml = current_relations(:visible_relation).to_xml
relation_element = relation_xml.find("//osm/relation").first
new_tag = XML::Node.new("tag")
new_tag['k'] = "some_new_tag"
new_tag['v'] = "some_new_value"
relation_element << new_tag
# update changeset ID to point to new changeset
update_changeset(relation_xml, changeset_id)
# upload the change
content relation_xml
put :update, :id => current_relations(:visible_relation).id
assert_response :success, "can't update relation for tag/bbox test"
end
end
##
# add a member to a relation and check the bounding box is only that
# element.
def test_add_member_bounding_box
relation_id = current_relations(:visible_relation).id
[current_nodes(:used_node_1),
current_nodes(:used_node_2),
current_ways(:used_way),
current_ways(:way_with_versions)
].each_with_index do |element, version|
bbox = element.bbox.to_unscaled
check_changeset_modify(bbox) do |changeset_id|
relation_xml = Relation.find(relation_id).to_xml
relation_element = relation_xml.find("//osm/relation").first
new_member = XML::Node.new("member")
new_member['ref'] = element.id.to_s
new_member['type'] = element.class.to_s.downcase
new_member['role'] = "some_role"
relation_element << new_member
# update changeset ID to point to new changeset
update_changeset(relation_xml, changeset_id)
# upload the change
content relation_xml
put :update, :id => current_relations(:visible_relation).id
assert_response :success, "can't update relation for add #{element.class}/bbox test: #{@response.body}"
# get it back and check the ordering
get :read, :id => relation_id
assert_response :success, "can't read back the relation: #{@response.body}"
check_ordering(relation_xml, @response.body)
end
end
end
##
# remove a member from a relation and check the bounding box is
# only that element.
def test_remove_member_bounding_box
check_changeset_modify(BoundingBox.new(5,5,5,5)) do |changeset_id|
# remove node 5 (5,5) from an existing relation
relation_xml = current_relations(:visible_relation).to_xml
relation_xml.
find("//osm/relation/member[@type='node'][@ref='5']").
first.remove!
# update changeset ID to point to new changeset
update_changeset(relation_xml, changeset_id)
# upload the change
content relation_xml
put :update, :id => current_relations(:visible_relation).id
assert_response :success, "can't update relation for remove node/bbox test"
end
end
##
# check that relations are ordered
def test_relation_member_ordering
basic_authorization(users(:public_user).email, "test")
doc_str = <<OSM
<osm>
<relation changeset='4'>
<member ref='1' type='node' role='first'/>
<member ref='3' type='node' role='second'/>
<member ref='1' type='way' role='third'/>
<member ref='3' type='way' role='fourth'/>
</relation>
</osm>
OSM
doc = XML::Parser.string(doc_str).parse
content doc
put :create
assert_response :success, "can't create a relation: #{@response.body}"
relation_id = @response.body.to_i
# get it back and check the ordering
get :read, :id => relation_id
assert_response :success, "can't read back the relation: #{@response.body}"
check_ordering(doc, @response.body)
# insert a member at the front
new_member = XML::Node.new "member"
new_member['ref'] = 5.to_s
new_member['type'] = 'node'
new_member['role'] = 'new first'
doc.find("//osm/relation").first.child.prev = new_member
# update the version, should be 1?
doc.find("//osm/relation").first['id'] = relation_id.to_s
doc.find("//osm/relation").first['version'] = 1.to_s
# upload the next version of the relation
content doc
put :update, :id => relation_id
assert_response :success, "can't update relation: #{@response.body}"
new_version = @response.body.to_i
# get it back again and check the ordering again
get :read, :id => relation_id
assert_response :success, "can't read back the relation: #{@response.body}"
check_ordering(doc, @response.body)
# check the ordering in the history tables:
with_controller(OldRelationController.new) do
get :version, :id => relation_id, :version => 2
assert_response :success, "can't read back version 2 of the relation #{relation_id}"
check_ordering(doc, @response.body)
end
end
##
# check that relations can contain duplicate members
def test_relation_member_duplicates
doc_str = <<OSM
<osm>
<relation changeset='4'>
<member ref='1' type='node' role='forward'/>
<member ref='3' type='node' role='forward'/>
<member ref='1' type='node' role='forward'/>
<member ref='3' type='node' role='forward'/>
</relation>
</osm>
OSM
doc = XML::Parser.string(doc_str).parse
## First try with the private user
basic_authorization(users(:normal_user).email, "test");
content doc
put :create
assert_response :forbidden
## Now try with the public user
basic_authorization(users(:public_user).email, "test");
content doc
put :create
assert_response :success, "can't create a relation: #{@response.body}"
relation_id = @response.body.to_i
# get it back and check the ordering
get :read, :id => relation_id
assert_response :success, "can't read back the relation: #{relation_id}"
check_ordering(doc, @response.body)
end
##
# test that the ordering of elements in the history is the same as in current.
def test_history_ordering
doc_str = <<OSM
<osm>
<relation changeset='4'>
<member ref='1' type='node' role='forward'/>
<member ref='5' type='node' role='forward'/>
<member ref='4' type='node' role='forward'/>
<member ref='3' type='node' role='forward'/>
</relation>
</osm>
OSM
doc = XML::Parser.string(doc_str).parse
basic_authorization(users(:public_user).email, "test");
content doc
put :create
assert_response :success, "can't create a relation: #{@response.body}"
relation_id = @response.body.to_i
# check the ordering in the current tables:
get :read, :id => relation_id
assert_response :success, "can't read back the relation: #{@response.body}"
check_ordering(doc, @response.body)
# check the ordering in the history tables:
with_controller(OldRelationController.new) do
get :version, :id => relation_id, :version => 1
assert_response :success, "can't read back version 1 of the relation: #{@response.body}"
check_ordering(doc, @response.body)
end
end
##
# remove all the members from a relation. the result is pretty useless, but
# still technically valid.
def test_remove_all_members
check_changeset_modify(BoundingBox.new(3,3,5,5)) do |changeset_id|
relation_xml = current_relations(:visible_relation).to_xml
relation_xml.
find("//osm/relation/member").
each {|m| m.remove!}
# update changeset ID to point to new changeset
update_changeset(relation_xml, changeset_id)
# upload the change
content relation_xml
put :update, :id => current_relations(:visible_relation).id
assert_response :success, "can't update relation for remove all members test"
checkrelation = Relation.find(current_relations(:visible_relation).id)
assert_not_nil(checkrelation,
"uploaded relation not found in database after upload")
assert_equal(0, checkrelation.members.length,
"relation contains members but they should have all been deleted")
end
end
# ============================================================
# utility functions
# ============================================================
##
# checks that the XML document and the string arguments have
# members in the same order.
def check_ordering(doc, xml)
new_doc = XML::Parser.string(xml).parse
doc_members = doc.find("//osm/relation/member").collect do |m|
[m['ref'].to_i, m['type'].to_sym, m['role']]
end
new_members = new_doc.find("//osm/relation/member").collect do |m|
[m['ref'].to_i, m['type'].to_sym, m['role']]
end
doc_members.zip(new_members).each do |d, n|
assert_equal d, n, "members are not equal - ordering is wrong? (#{doc}, #{xml})"
end
end
##
# create a changeset and yield to the caller to set it up, then assert
# that the changeset bounding box is +bbox+.
def check_changeset_modify(bbox)
## First test with the private user to check that you get a forbidden
basic_authorization(users(:normal_user).email, "test");
# create a new changeset for this operation, so we are assured
# that the bounding box will be newly-generated.
changeset_id = with_controller(ChangesetController.new) do
content "<osm><changeset/></osm>"
put :create
assert_response :forbidden, "shouldn't be able to create changeset for modify test, as should get forbidden"
end
## Now do the whole thing with the public user
basic_authorization(users(:public_user).email, "test")
# create a new changeset for this operation, so we are assured
# that the bounding box will be newly-generated.
changeset_id = with_controller(ChangesetController.new) do
content "<osm><changeset/></osm>"
put :create
assert_response :success, "couldn't create changeset for modify test"
@response.body.to_i
end
# go back to the block to do the actual modifies
yield changeset_id
# now download the changeset to check its bounding box
with_controller(ChangesetController.new) do
get :read, :id => changeset_id
assert_response :success, "can't re-read changeset for modify test"
assert_select "osm>changeset", 1, "Changeset element doesn't exist in #{@response.body}"
assert_select "osm>changeset[id=#{changeset_id}]", 1, "Changeset id=#{changeset_id} doesn't exist in #{@response.body}"
assert_select "osm>changeset[min_lon=#{bbox.min_lon}]", 1, "Changeset min_lon wrong in #{@response.body}"
assert_select "osm>changeset[min_lat=#{bbox.min_lat}]", 1, "Changeset min_lat wrong in #{@response.body}"
assert_select "osm>changeset[max_lon=#{bbox.max_lon}]", 1, "Changeset max_lon wrong in #{@response.body}"
assert_select "osm>changeset[max_lat=#{bbox.max_lat}]", 1, "Changeset max_lat wrong in #{@response.body}"
end
end
##
# yields the relation with the given +id+ (and optional +version+
# to read from the history tables) into the block. the parsed XML
# doc is returned.
def with_relation(id, ver = nil)
if ver.nil?
get :read, :id => id
else
with_controller(OldRelationController.new) do
get :version, :id => id, :version => ver
end
end
assert_response :success
yield xml_parse(@response.body)
end
##
# updates the relation (XML) +rel+ and
# yields the new version of that relation into the block.
# the parsed XML doc is retured.
def with_update(rel)
rel_id = rel.find("//osm/relation").first["id"].to_i
content rel
put :update, :id => rel_id
assert_response :success, "can't update relation: #{@response.body}"
version = @response.body.to_i
# now get the new version
get :read, :id => rel_id
assert_response :success
new_rel = xml_parse(@response.body)
yield new_rel
return version
end
##
# updates the relation (XML) +rel+ via the diff-upload API and
# yields the new version of that relation into the block.
# the parsed XML doc is retured.
def with_update_diff(rel)
rel_id = rel.find("//osm/relation").first["id"].to_i
cs_id = rel.find("//osm/relation").first['changeset'].to_i
version = nil
with_controller(ChangesetController.new) do
doc = OSM::API.new.get_xml_doc
change = XML::Node.new 'osmChange'
doc.root = change
modify = XML::Node.new 'modify'
change << modify
modify << doc.import(rel.find("//osm/relation").first)
content doc.to_s
post :upload, :id => cs_id
assert_response :success, "can't upload diff relation: #{@response.body}"
version = xml_parse(@response.body).find("//diffResult/relation").first["new_version"].to_i
end
# now get the new version
get :read, :id => rel_id
assert_response :success
new_rel = xml_parse(@response.body)
yield new_rel
return version
end
##
# returns a k->v hash of tags from an xml doc
def get_tags_as_hash(a)
a.find("//osm/relation/tag").sort_by { |v| v['k'] }.inject({}) do |h,v|
h[v['k']] = v['v']
h
end
end
##
# assert that all tags on relation documents +a+ and +b+
# are equal
def assert_tags_equal(a, b)
# turn the XML doc into tags hashes
a_tags = get_tags_as_hash(a)
b_tags = get_tags_as_hash(b)
assert_equal a_tags.keys, b_tags.keys, "Tag keys should be identical."
a_tags.each do |k, v|
assert_equal v, b_tags[k],
"Tags which were not altered should be the same. " +
"#{a_tags.inspect} != #{b_tags.inspect}"
end
end
##
# update the changeset_id of a node element
def update_changeset(xml, changeset_id)
xml_attr_rewrite(xml, 'changeset', changeset_id)
end
##
# update an attribute in the node element
def xml_attr_rewrite(xml, name, value)
xml.find("//osm/relation").first[name] = value.to_s
return xml
end
##
# parse some xml
def xml_parse(xml)
parser = XML::Parser.string(xml)
parser.parse
end
end

View file

@ -0,0 +1,24 @@
require 'test_helper'
class SearchControllerTest < ActionController::TestCase
##
# test all routes which lead to this controller
def test_routes
assert_routing(
{ :path => "/api/0.6/search", :method => :get },
{ :controller => "search", :action => "search_all" }
)
assert_routing(
{ :path => "/api/0.6/nodes/search", :method => :get },
{ :controller => "search", :action => "search_nodes" }
)
assert_routing(
{ :path => "/api/0.6/ways/search", :method => :get },
{ :controller => "search", :action => "search_ways" }
)
assert_routing(
{ :path => "/api/0.6/relations/search", :method => :get },
{ :controller => "search", :action => "search_relations" }
)
end
end

View file

@ -0,0 +1,344 @@
require 'test_helper'
class SiteControllerTest < ActionController::TestCase
api_fixtures
##
# setup oauth keys
def setup
Object.const_set("ID_KEY", client_applications(:oauth_web_app).key)
Object.const_set("POTLATCH2_KEY", client_applications(:oauth_web_app).key)
end
##
# clear oauth keys
def teardown
Object.send("remove_const", "ID_KEY")
Object.send("remove_const", "POTLATCH2_KEY")
end
##
# test all routes which lead to this controller
def test_routes
assert_routing(
{ :path => "/", :method => :get },
{ :controller => "site", :action => "index" }
)
assert_routing(
{ :path => "/", :method => :post },
{ :controller => "site", :action => "index" }
)
assert_routing(
{ :path => "/edit", :method => :get },
{ :controller => "site", :action => "edit" }
)
assert_recognizes(
{ :controller => "site", :action => "edit", :format => "html" },
{ :path => "/edit.html", :method => :get }
)
assert_routing(
{ :path => "/copyright", :method => :get },
{ :controller => "site", :action => "copyright" }
)
assert_routing(
{ :path => "/copyright/locale", :method => :get },
{ :controller => "site", :action => "copyright", :copyright_locale => "locale" }
)
assert_routing(
{ :path => "/welcome", :method => :get },
{ :controller => "site", :action => "welcome" }
)
assert_routing(
{ :path => "/fixthemap", :method => :get },
{ :controller => "site", :action => "fixthemap" }
)
assert_routing(
{ :path => "/export", :method => :get },
{ :controller => "site", :action => "export" }
)
assert_recognizes(
{ :controller => "site", :action => "export", :format => "html" },
{ :path => "/export.html", :method => :get }
)
assert_routing(
{ :path => "/offline", :method => :get },
{ :controller => "site", :action => "offline" }
)
assert_routing(
{ :path => "/key", :method => :get },
{ :controller => "site", :action => "key" }
)
assert_routing(
{ :path => "/go/shortcode", :method => :get },
{ :controller => "site", :action => "permalink", :code => "shortcode" }
)
assert_routing(
{ :path => "/preview/formatname", :method => :post },
{ :controller => "site", :action => "preview", :format => "formatname" }
)
assert_routing(
{ :path => "/id", :method => :get },
{ :controller => "site", :action => "id" }
)
end
# Test the index page
def test_index
get :index
assert_response :success
assert_template 'index'
end
# Test the index page redirects
def test_index_redirect
get :index, :lat => 4, :lon => 5
assert_redirected_to :controller => :site, :action => :index, :anchor => 'map=5/4/5'
get :index, :lat => 4, :lon => 5, :zoom => 3
assert_redirected_to :controller => :site, :action => :index, :anchor => 'map=3/4/5'
get :index, :layers => 'T'
assert_redirected_to :controller => :site, :action => :index, :anchor => 'layers=T'
get :index, :notes => 'yes'
assert_redirected_to :controller => :site, :action => :index, :anchor => 'layers=N'
get :index, :lat => 4, :lon => 5, :zoom => 3, :layers => 'T'
assert_redirected_to :controller => :site, :action => :index, :anchor => 'map=3/4/5&layers=T'
end
# Test the permalink redirect
def test_permalink
get :permalink, :code => 'wBz3--'
assert_response :redirect
assert_redirected_to :controller => :site, :action => :index, :anchor => 'map=3/4.8779296875/3.955078125'
get :permalink, :code => 'wBz3--', :m => ''
assert_response :redirect
assert_redirected_to :controller => :site, :action => :index, :mlat => '4.8779296875', :mlon => '3.955078125', :anchor => 'map=3/4.8779296875/3.955078125'
get :permalink, :code => 'wBz3--', :layers => 'T'
assert_response :redirect
assert_redirected_to :controller => :site, :action => :index, :layers => 'T', :anchor => 'map=3/4.8779296875/3.955078125'
get :permalink, :code => 'wBz3--', :node => 1
assert_response :redirect
assert_redirected_to :controller => :browse, :action => :node, :id => 1, :anchor => 'map=3/4.8779296875/3.955078125'
get :permalink, :code => 'wBz3--', :way => 2
assert_response :redirect
assert_redirected_to :controller => :browse, :action => :way, :id => 2, :anchor => 'map=3/4.8779296875/3.955078125'
get :permalink, :code => 'wBz3--', :relation => 3
assert_response :redirect
assert_redirected_to :controller => :browse, :action => :relation, :id => 3, :anchor => 'map=3/4.8779296875/3.955078125'
get :permalink, :code => 'wBz3--', :changeset => 4
assert_response :redirect
assert_redirected_to :controller => :browse, :action => :changeset, :id => 4, :anchor => 'map=3/4.8779296875/3.955078125'
end
# Test the key page
def test_key
xhr :get, :key
assert_response :success
assert_template "key"
assert_template :layout => false
end
# Test the edit page redirects when you aren't logged in
def test_edit
get :edit
assert_response :redirect
assert_redirected_to :controller => :user, :action => :login, :referer => "/edit"
end
# Test the right editor gets used when the user hasn't set a preference
def test_edit_without_preference
get :edit, nil, { :user => users(:public_user).id }
assert_response :success
assert_template "edit"
assert_template :partial => "_#{DEFAULT_EDITOR}", :count => 1
end
# Test the right editor gets used when the user has set a preference
def test_edit_with_preference
user = users(:public_user)
user.preferred_editor = "id"
user.save!
get :edit, nil, { :user => user.id }
assert_response :success
assert_template "edit"
assert_template :partial => "_id", :count => 1
user = users(:public_user)
user.preferred_editor = "potlatch2"
user.save!
get :edit, nil, { :user => user.id }
assert_response :success
assert_template "edit"
assert_template :partial => "_potlatch2", :count => 1
user = users(:public_user)
user.preferred_editor = "potlatch"
user.save!
get :edit, nil, { :user => user.id }
assert_response :success
assert_template "edit"
assert_template :partial => "_potlatch", :count => 1
user = users(:public_user)
user.preferred_editor = "remote"
user.save!
get :edit, nil, { :user => user.id }
assert_response :success
assert_template "index"
end
# Test editing a specific node
def test_edit_with_node
user = users(:public_user)
node = current_nodes(:visible_node)
get :edit, { :node => node.id }, { :user => user.id }
assert_response :success
assert_template "edit"
assert_equal 1.0, assigns(:lat)
assert_equal 1.0, assigns(:lon)
assert_equal 18, assigns(:zoom)
end
# Test editing a specific way
def test_edit_with_way
user = users(:public_user)
way = current_ways(:visible_way)
get :edit, { :way => way.id }, { :user => user.id }
assert_response :success
assert_template "edit"
assert_equal 3.0, assigns(:lat)
assert_equal 3.0, assigns(:lon)
assert_equal 17, assigns(:zoom)
end
# Test editing a specific note
def test_edit_with_note
user = users(:public_user)
note = notes(:open_note)
get :edit, { :note => note.id }, { :user => user.id }
assert_response :success
assert_template "edit"
assert_equal 1.0, assigns(:lat)
assert_equal 1.0, assigns(:lon)
assert_equal 17, assigns(:zoom)
end
# Test editing a specific GPX trace
def test_edit_with_gpx
user = users(:public_user)
gpx = gpx_files(:public_trace_file)
get :edit, { :gpx => gpx.id }, { :user => user.id }
assert_response :success
assert_template "edit"
assert_equal 1.0, assigns(:lat)
assert_equal 1.0, assigns(:lon)
assert_equal 16, assigns(:zoom)
end
# Test the edit page redirects
def test_edit_redirect
get :edit, :lat => 4, :lon => 5
assert_redirected_to :controller => :site, :action => :edit, :anchor => 'map=5/4/5'
get :edit, :lat => 4, :lon => 5, :zoom => 3
assert_redirected_to :controller => :site, :action => :edit, :anchor => 'map=3/4/5'
get :edit, :lat => 4, :lon => 5, :zoom => 3, :editor => 'id'
assert_redirected_to :controller => :site, :action => :edit, :editor => 'id', :anchor => 'map=3/4/5'
end
# Test the copyright page
def test_copyright
get :copyright
assert_response :success
assert_template "copyright"
end
# Test the welcome page
def test_welcome
get :welcome
assert_response :redirect
assert_redirected_to :controller => :user, :action => :login, :referer => "/welcome"
get :welcome, nil, { :user => users(:public_user).id }
assert_response :success
assert_template "welcome"
end
# Test the fixthemap page
def test_fixthemap
get :fixthemap
assert_response :success
assert_template "fixthemap"
end
# Test the help page
def test_help
get :help
assert_response :success
assert_template "help"
end
# Test the about page
def test_about
get :about
assert_response :success
assert_template "about"
end
# Test the export page
def test_export
get :export
assert_response :success
assert_template "export"
assert_template :layout => "map"
xhr :get, :export
assert_response :success
assert_template "export"
assert_template :layout => "xhr"
end
# Test the offline page
def test_offline
get :offline
assert_response :success
assert_template "offline"
end
# Test the rich text preview
def test_preview
xhr :post, :preview, :format => "html"
assert_response :success
xhr :post, :preview, :format => "markdown"
assert_response :success
xhr :post, :preview, :format => "text"
assert_response :success
end
# Test the id frame
def test_id
get :id, nil, { :user => users(:public_user).id }
assert_response :success
assert_template "id"
assert_template :layout => false
end
end

View file

@ -0,0 +1,12 @@
require 'test_helper'
class SwfControllerTest < ActionController::TestCase
##
# test all routes which lead to this controller
def test_routes
assert_routing(
{ :path => "/api/0.6/swf/trackpoints", :method => :get },
{ :controller => "swf", :action => "trackpoints" }
)
end
end

View file

@ -0,0 +1,600 @@
require 'test_helper'
class TraceControllerTest < ActionController::TestCase
fixtures :users, :gpx_files
set_fixture_class :gpx_files => 'Trace'
def setup
@gpx_trace_dir = Object.send("remove_const", "GPX_TRACE_DIR")
Object.const_set("GPX_TRACE_DIR", File.dirname(__FILE__) + "/../traces")
end
def teardown
Object.send("remove_const", "GPX_TRACE_DIR")
Object.const_set("GPX_TRACE_DIR", @gpx_trace_dir)
end
##
# test all routes which lead to this controller
def test_routes
assert_routing(
{ :path => "/api/0.6/gpx/create", :method => :post },
{ :controller => "trace", :action => "api_create" }
)
assert_routing(
{ :path => "/api/0.6/gpx/1", :method => :get },
{ :controller => "trace", :action => "api_read", :id => "1" }
)
assert_routing(
{ :path => "/api/0.6/gpx/1", :method => :put },
{ :controller => "trace", :action => "api_update", :id => "1" }
)
assert_routing(
{ :path => "/api/0.6/gpx/1", :method => :delete },
{ :controller => "trace", :action => "api_delete", :id => "1" }
)
assert_recognizes(
{ :controller => "trace", :action => "api_read", :id => "1" },
{ :path => "/api/0.6/gpx/1/details", :method => :get }
)
assert_routing(
{ :path => "/api/0.6/gpx/1/data", :method => :get },
{ :controller => "trace", :action => "api_data", :id => "1" }
)
assert_routing(
{ :path => "/api/0.6/gpx/1/data.xml", :method => :get },
{ :controller => "trace", :action => "api_data", :id => "1", :format => "xml" }
)
assert_routing(
{ :path => "/traces", :method => :get },
{ :controller => "trace", :action => "list" }
)
assert_routing(
{ :path => "/traces/page/1", :method => :get },
{ :controller => "trace", :action => "list", :page => "1" }
)
assert_routing(
{ :path => "/traces/tag/tagname", :method => :get },
{ :controller => "trace", :action => "list", :tag => "tagname" }
)
assert_routing(
{ :path => "/traces/tag/tagname/page/1", :method => :get },
{ :controller => "trace", :action => "list", :tag => "tagname", :page => "1" }
)
assert_routing(
{ :path => "/user/username/traces", :method => :get },
{ :controller => "trace", :action => "list", :display_name => "username" }
)
assert_routing(
{ :path => "/user/username/traces/page/1", :method => :get },
{ :controller => "trace", :action => "list", :display_name => "username", :page => "1" }
)
assert_routing(
{ :path => "/user/username/traces/tag/tagname", :method => :get },
{ :controller => "trace", :action => "list", :display_name => "username", :tag => "tagname" }
)
assert_routing(
{ :path => "/user/username/traces/tag/tagname/page/1", :method => :get },
{ :controller => "trace", :action => "list", :display_name => "username", :tag => "tagname", :page => "1" }
)
assert_routing(
{ :path => "/traces/mine", :method => :get },
{ :controller => "trace", :action => "mine" }
)
assert_routing(
{ :path => "/traces/mine/page/1", :method => :get },
{ :controller => "trace", :action => "mine", :page => "1" }
)
assert_routing(
{ :path => "/traces/mine/tag/tagname", :method => :get },
{ :controller => "trace", :action => "mine", :tag => "tagname" }
)
assert_routing(
{ :path => "/traces/mine/tag/tagname/page/1", :method => :get },
{ :controller => "trace", :action => "mine", :tag => "tagname", :page => "1" }
)
assert_routing(
{ :path => "/traces/rss", :method => :get },
{ :controller => "trace", :action => "georss", :format => :rss }
)
assert_routing(
{ :path => "/traces/tag/tagname/rss", :method => :get },
{ :controller => "trace", :action => "georss", :tag => "tagname", :format => :rss }
)
assert_routing(
{ :path => "/user/username/traces/rss", :method => :get },
{ :controller => "trace", :action => "georss", :display_name => "username", :format => :rss }
)
assert_routing(
{ :path => "/user/username/traces/tag/tagname/rss", :method => :get },
{ :controller => "trace", :action => "georss", :display_name => "username", :tag => "tagname", :format => :rss }
)
assert_routing(
{ :path => "/user/username/traces/1", :method => :get },
{ :controller => "trace", :action => "view", :display_name => "username", :id => "1" }
)
assert_routing(
{ :path => "/user/username/traces/1/picture", :method => :get },
{ :controller => "trace", :action => "picture", :display_name => "username", :id => "1" }
)
assert_routing(
{ :path => "/user/username/traces/1/icon", :method => :get },
{ :controller => "trace", :action => "icon", :display_name => "username", :id => "1" }
)
assert_routing(
{ :path => "/trace/create", :method => :get },
{ :controller => "trace", :action => "create" }
)
assert_routing(
{ :path => "/trace/create", :method => :post },
{ :controller => "trace", :action => "create" }
)
assert_routing(
{ :path => "/trace/1/data", :method => :get },
{ :controller => "trace", :action => "data", :id => "1" }
)
assert_routing(
{ :path => "/trace/1/data.xml", :method => :get },
{ :controller => "trace", :action => "data", :id => "1", :format => "xml" }
)
assert_routing(
{ :path => "/trace/1/edit", :method => :get },
{ :controller => "trace", :action => "edit", :id => "1" }
)
assert_routing(
{ :path => "/trace/1/edit", :method => :post },
{ :controller => "trace", :action => "edit", :id => "1" }
)
assert_routing(
{ :path => "/trace/1/edit", :method => :patch },
{ :controller => "trace", :action => "edit", :id => "1" }
)
assert_routing(
{ :path => "/trace/1/delete", :method => :post },
{ :controller => "trace", :action => "delete", :id => "1" }
)
end
# Check that the list of changesets is displayed
def test_list
get :list
check_trace_list Trace.public
get :list, :tag => "London"
check_trace_list Trace.tagged("London").public
end
# Check that I can get mine
def test_list_mine
# First try to get it when not logged in
get :mine
assert_redirected_to :controller => 'user', :action => 'login', :referer => '/traces/mine'
# Now try when logged in
get :mine, {}, {:user => users(:public_user).id}
assert_redirected_to :controller => 'trace', :action => 'list', :display_name => users(:public_user).display_name
# Fetch the actual list
get :list, {:display_name => users(:public_user).display_name}, {:user => users(:public_user).id}
check_trace_list users(:public_user).traces
end
# Check the list of changesets for a specific user
def test_list_user
# Test a user with no traces
get :list, :display_name => users(:second_public_user).display_name
check_trace_list users(:second_public_user).traces.public
# Test a user with some traces - should see only public ones
get :list, :display_name => users(:public_user).display_name
check_trace_list users(:public_user).traces.public
# Should still see only public ones when authenticated as another user
get :list, {:display_name => users(:public_user).display_name}, {:user => users(:normal_user).id}
check_trace_list users(:public_user).traces.public
# Should see all traces when authenticated as the target user
get :list, {:display_name => users(:public_user).display_name}, {:user => users(:public_user).id}
check_trace_list users(:public_user).traces
# Should only see traces with the correct tag when a tag is specified
get :list, {:display_name => users(:public_user).display_name, :tag => "London"}, {:user => users(:public_user).id}
check_trace_list users(:public_user).traces.tagged("London")
end
# Check that the rss loads
def test_rss
get :georss, :format => :rss
check_trace_feed Trace.public
get :georss, :tag => "London", :format => :rss
check_trace_feed Trace.tagged("London").public
get :georss, :display_name => users(:public_user).display_name, :format => :rss
check_trace_feed users(:public_user).traces.public
get :georss, :display_name => users(:public_user).display_name, :tag => "Birmingham", :format => :rss
check_trace_feed users(:public_user).traces.tagged("Birmingham").public
end
# Test viewing a trace
def test_view
# First with no auth, which should work since the trace is public
get :view, {:display_name => users(:normal_user).display_name, :id => gpx_files(:public_trace_file).id}
check_trace_view gpx_files(:public_trace_file)
# Now with some other user, which should work since the trace is public
get :view, {:display_name => users(:normal_user).display_name, :id => gpx_files(:public_trace_file).id}, {:user => users(:public_user).id}
check_trace_view gpx_files(:public_trace_file)
# And finally we should be able to do it with the owner of the trace
get :view, {:display_name => users(:normal_user).display_name, :id => gpx_files(:public_trace_file).id}, {:user => users(:normal_user).id}
check_trace_view gpx_files(:public_trace_file)
end
# Check an anonymous trace can't be viewed by another user
def test_view_anon
# First with no auth
get :view, {:display_name => users(:public_user).display_name, :id => gpx_files(:anon_trace_file).id}
assert_response :redirect
assert_redirected_to :action => :list
# Now with some other user, which should work since the trace is anon
get :view, {:display_name => users(:public_user).display_name, :id => gpx_files(:anon_trace_file).id}, {:user => users(:normal_user).id}
assert_response :redirect
assert_redirected_to :action => :list
# And finally we should be able to do it with the owner of the trace
get :view, {:display_name => users(:public_user).display_name, :id => gpx_files(:anon_trace_file).id}, {:user => users(:public_user).id}
check_trace_view gpx_files(:anon_trace_file)
end
# Test viewing a trace that doesn't exist
def test_view_not_found
# First with no auth, which should work since the trace is public
get :view, {:display_name => users(:public_user).display_name, :id => 0}
assert_response :redirect
assert_redirected_to :action => :list
# Now with some other user, which should work since the trace is public
get :view, {:display_name => users(:public_user).display_name, :id => 0}, {:user => users(:public_user).id}
assert_response :redirect
assert_redirected_to :action => :list
# And finally we should be able to do it with the owner of the trace
get :view, {:display_name => users(:public_user).display_name, :id => 5}, {:user => users(:public_user).id}
assert_response :redirect
assert_redirected_to :action => :list
end
# Test downloading a trace
def test_data
# First with no auth, which should work since the trace is public
get :data, {:display_name => users(:normal_user).display_name, :id => gpx_files(:public_trace_file).id}
check_trace_data gpx_files(:public_trace_file)
# Now with some other user, which should work since the trace is public
get :data, {:display_name => users(:normal_user).display_name, :id => gpx_files(:public_trace_file).id}, {:user => users(:public_user).id}
check_trace_data gpx_files(:public_trace_file)
# And finally we should be able to do it with the owner of the trace
get :data, {:display_name => users(:normal_user).display_name, :id => gpx_files(:public_trace_file).id}, {:user => users(:normal_user).id}
check_trace_data gpx_files(:public_trace_file)
end
# Test downloading a compressed trace
def test_data_compressed
# First get the data as is
get :data, {:display_name => users(:public_user).display_name, :id => gpx_files(:identifiable_trace_file).id}
check_trace_data gpx_files(:identifiable_trace_file), "application/x-gzip", "gpx.gz"
# Now ask explicitly for XML format
get :data, {:display_name => users(:public_user).display_name, :id => gpx_files(:identifiable_trace_file).id, :format => "xml"}
check_trace_data gpx_files(:identifiable_trace_file), "application/xml", "xml"
# Now ask explicitly for GPX format
get :data, {:display_name => users(:public_user).display_name, :id => gpx_files(:identifiable_trace_file).id, :format => "gpx"}
check_trace_data gpx_files(:identifiable_trace_file)
end
# Check an anonymous trace can't be downloaded by another user
def test_data_anon
# First with no auth
get :data, {:display_name => users(:public_user).display_name, :id => gpx_files(:anon_trace_file).id}
assert_response :not_found
# Now with some other user, which should work since the trace is anon
get :data, {:display_name => users(:public_user).display_name, :id => gpx_files(:anon_trace_file).id}, {:user => users(:normal_user).id}
assert_response :not_found
# And finally we should be able to do it with the owner of the trace
get :data, {:display_name => users(:public_user).display_name, :id => gpx_files(:anon_trace_file).id}, {:user => users(:public_user).id}
check_trace_data gpx_files(:anon_trace_file)
end
# Test downloading a trace that doesn't exist
def test_data_not_found
# First with no auth, which should work since the trace is public
get :data, {:display_name => users(:public_user).display_name, :id => 0}
assert_response :not_found
# Now with some other user, which should work since the trace is public
get :data, {:display_name => users(:public_user).display_name, :id => 0}, {:user => users(:public_user).id}
assert_response :not_found
# And finally we should be able to do it with the owner of the trace
get :data, {:display_name => users(:public_user).display_name, :id => 5}, {:user => users(:public_user).id}
assert_response :not_found
end
# Test fetching the edit page for a trace
def test_edit_get
# First with no auth
get :edit, {:display_name => users(:normal_user).display_name, :id => gpx_files(:public_trace_file).id}
assert_response :redirect
assert_redirected_to :controller => :user, :action => :login, :referer => trace_edit_path(:display_name => users(:normal_user).display_name, :id => gpx_files(:public_trace_file).id)
# Now with some other user, which should fail
get :edit, {:display_name => users(:normal_user).display_name, :id => gpx_files(:public_trace_file).id}, {:user => users(:public_user).id}
assert_response :forbidden
# Now with a trace which doesn't exist
get :edit, {:display_name => users(:public_user).display_name, :id => 0}, {:user => users(:public_user).id}
assert_response :not_found
# Now with a trace which has been deleted
get :edit, {:display_name => users(:public_user).display_name, :id => gpx_files(:deleted_trace_file).id}, {:user => users(:public_user).id}
assert_response :not_found
# Finally with a trace that we are allowed to edit
get :edit, {:display_name => users(:normal_user).display_name, :id => gpx_files(:public_trace_file).id}, {:user => users(:normal_user).id}
assert_response :success
end
# Test saving edits to a trace
def test_edit_post
# New details
new_details = { :description => "Changed description", :tagstring => "new_tag", :visibility => "private" }
# First with no auth
post :edit, {:display_name => users(:normal_user).display_name, :id => gpx_files(:public_trace_file).id, :trace => new_details}
assert_response :forbidden
# Now with some other user, which should fail
post :edit, {:display_name => users(:normal_user).display_name, :id => gpx_files(:public_trace_file).id, :trace => new_details}, {:user => users(:public_user).id}
assert_response :forbidden
# Now with a trace which doesn't exist
post :edit, {:display_name => users(:public_user).display_name, :id => 0}, {:user => users(:public_user).id, :trace => new_details}
assert_response :not_found
# Now with a trace which has been deleted
post :edit, {:display_name => users(:public_user).display_name, :id => gpx_files(:deleted_trace_file).id, :trace => new_details}, {:user => users(:public_user).id}
assert_response :not_found
# Finally with a trace that we are allowed to edit
post :edit, {:display_name => users(:normal_user).display_name, :id => gpx_files(:public_trace_file).id, :trace => new_details}, {:user => users(:normal_user).id}
assert_response :redirect
assert_redirected_to :action => :view, :display_name => users(:normal_user).display_name
trace = Trace.find(gpx_files(:public_trace_file).id)
assert_equal new_details[:description], trace.description
assert_equal new_details[:tagstring], trace.tagstring
assert_equal new_details[:visibility], trace.visibility
end
# Test deleting a trace
def test_delete
# First with no auth
post :delete, {:display_name => users(:normal_user).display_name, :id => gpx_files(:public_trace_file).id,}
assert_response :forbidden
# Now with some other user, which should fail
post :delete, {:display_name => users(:normal_user).display_name, :id => gpx_files(:public_trace_file).id}, {:user => users(:public_user).id}
assert_response :forbidden
# Now with a trace which doesn't exist
post :delete, {:display_name => users(:public_user).display_name, :id => 0}, {:user => users(:public_user).id}
assert_response :not_found
# Now with a trace has already been deleted
post :delete, {:display_name => users(:public_user).display_name, :id => gpx_files(:deleted_trace_file).id}, {:user => users(:public_user).id}
assert_response :not_found
# Finally with a trace that we are allowed to delete
post :delete, {:display_name => users(:normal_user).display_name, :id => gpx_files(:public_trace_file).id}, {:user => users(:normal_user).id}
assert_response :redirect
assert_redirected_to :action => :list, :display_name => users(:normal_user).display_name
trace = Trace.find(gpx_files(:public_trace_file).id)
assert_equal false, trace.visible
end
# Check getting a specific trace through the api
def test_api_read
# First with no auth
get :api_read, :id => gpx_files(:public_trace_file).id
assert_response :unauthorized
# Now with some other user, which should work since the trace is public
basic_authorization(users(:public_user).display_name, "test")
get :api_read, :id => gpx_files(:public_trace_file).id
assert_response :success
# And finally we should be able to do it with the owner of the trace
basic_authorization(users(:normal_user).display_name, "test")
get :api_read, :id => gpx_files(:public_trace_file).id
assert_response :success
end
# Check an anoymous trace can't be specifically fetched by another user
def test_api_read_anon
# Furst with no auth
get :api_read, :id => gpx_files(:anon_trace_file).id
assert_response :unauthorized
# Now try with another user, which shouldn't work since the trace is anon
basic_authorization(users(:normal_user).display_name, "test")
get :api_read, :id => gpx_files(:anon_trace_file).id
assert_response :forbidden
# And finally we should be able to get the trace details with the trace owner
basic_authorization(users(:public_user).display_name, "test")
get :api_read, :id => gpx_files(:anon_trace_file).id
assert_response :success
end
# Check the api details for a trace that doesn't exist
def test_api_read_not_found
# Try first with no auth, as it should requure it
get :api_read, :id => 0
assert_response :unauthorized
# Login, and try again
basic_authorization(users(:public_user).display_name, "test")
get :api_read, :id => 0
assert_response :not_found
# Now try a trace which did exist but has been deleted
basic_authorization(users(:public_user).display_name, "test")
get :api_read, :id => 5
assert_response :not_found
end
# Check updating a trace through the api
def test_api_update
# First with no auth
content gpx_files(:public_trace_file).to_xml
put :api_update, :id => gpx_files(:public_trace_file).id
assert_response :unauthorized
# Now with some other user, which should fail
basic_authorization(users(:public_user).display_name, "test")
content gpx_files(:public_trace_file).to_xml
put :api_update, :id => gpx_files(:public_trace_file).id
assert_response :forbidden
# Now with a trace which doesn't exist
basic_authorization(users(:public_user).display_name, "test")
content gpx_files(:public_trace_file).to_xml
put :api_update, :id => 0
assert_response :not_found
# Now with a trace which did exist but has been deleted
basic_authorization(users(:public_user).display_name, "test")
content gpx_files(:deleted_trace_file).to_xml
put :api_update, :id => gpx_files(:deleted_trace_file).id
assert_response :not_found
# Now try an update with the wrong ID
basic_authorization(users(:normal_user).display_name, "test")
content gpx_files(:anon_trace_file).to_xml
put :api_update, :id => gpx_files(:public_trace_file).id
assert_response :bad_request,
"should not be able to update a trace with a different ID from the XML"
# And finally try an update that should work
basic_authorization(users(:normal_user).display_name, "test")
t = gpx_files(:public_trace_file)
t.description = "Changed description"
t.visibility = "private"
content t.to_xml
put :api_update, :id => t.id
assert_response :success
nt = Trace.find(t.id)
assert_equal nt.description, t.description
assert_equal nt.visibility, t.visibility
end
# Check deleting a trace through the api
def test_api_delete
# First with no auth
delete :api_delete, :id => gpx_files(:public_trace_file).id
assert_response :unauthorized
# Now with some other user, which should fail
basic_authorization(users(:public_user).display_name, "test")
delete :api_delete, :id => gpx_files(:public_trace_file).id
assert_response :forbidden
# Now with a trace which doesn't exist
basic_authorization(users(:public_user).display_name, "test")
delete :api_delete, :id => 0
assert_response :not_found
# And finally we should be able to do it with the owner of the trace
basic_authorization(users(:normal_user).display_name, "test")
delete :api_delete, :id => gpx_files(:public_trace_file).id
assert_response :success
# Try it a second time, which should fail
basic_authorization(users(:normal_user).display_name, "test")
delete :api_delete, :id => gpx_files(:public_trace_file).id
assert_response :not_found
end
private
def check_trace_feed(traces)
assert_response :success
assert_template "georss"
assert_equal "application/rss+xml", @response.content_type
assert_select "rss", :count => 1 do
assert_select "channel", :count => 1 do
assert_select "title"
assert_select "description"
assert_select "link"
assert_select "image"
assert_select "item", :count => traces.visible.count do |items|
traces.visible.order("timestamp DESC").zip(items).each do |trace,item|
assert_select item, "title", trace.name
assert_select item, "link", "http://test.host/user/#{trace.user.display_name}/traces/#{trace.id}"
assert_select item, "guid", "http://test.host/user/#{trace.user.display_name}/traces/#{trace.id}"
assert_select item, "description"
# assert_select item, "dc:creator", trace.user.display_name
assert_select item, "pubDate", trace.timestamp.rfc822
end
end
end
end
end
def check_trace_list(traces)
assert_response :success
assert_template "list"
if traces.count > 0
assert_select "table#trace_list tbody", :count => 1 do
assert_select "tr", :count => traces.visible.count do |rows|
traces.visible.order("timestamp DESC").zip(rows).each do |trace,row|
assert_select row, "span.trace_summary", Regexp.new(Regexp.escape("(#{trace.size} points)"))
assert_select row, "td", Regexp.new(Regexp.escape(trace.description))
assert_select row, "td", Regexp.new(Regexp.escape("by #{trace.user.display_name}"))
end
end
end
else
assert_select "h4", /Nothing here yet/
end
end
def check_trace_view(trace)
assert_response :success
assert_template "view"
assert_select "table", :count => 1 do
assert_select "td", /^#{Regexp.quote(trace.name)} /
assert_select "td", trace.user.display_name
assert_select "td", trace.description
end
end
def check_trace_data(trace, content_type = "application/gpx+xml", extension = "gpx")
assert_response :success
assert_equal content_type, @response.content_type
assert_equal "attachment; filename=\"#{trace.id}.#{extension}\"", @response.header["Content-Disposition"]
end
end

View file

@ -0,0 +1,435 @@
require 'test_helper'
class UserBlocksControllerTest < ActionController::TestCase
fixtures :users, :user_roles, :user_blocks
##
# test all routes which lead to this controller
def test_routes
assert_routing(
{ :path => "/blocks/new/username", :method => :get },
{ :controller => "user_blocks", :action => "new", :display_name => "username" }
)
assert_routing(
{ :path => "/user_blocks", :method => :get },
{ :controller => "user_blocks", :action => "index" }
)
assert_routing(
{ :path => "/user_blocks/new", :method => :get },
{ :controller => "user_blocks", :action => "new" }
)
assert_routing(
{ :path => "/user_blocks", :method => :post },
{ :controller => "user_blocks", :action => "create" }
)
assert_routing(
{ :path => "/user_blocks/1", :method => :get },
{ :controller => "user_blocks", :action => "show", :id => "1" }
)
assert_routing(
{ :path => "/user_blocks/1/edit", :method => :get },
{ :controller => "user_blocks", :action => "edit", :id => "1" }
)
assert_routing(
{ :path => "/user_blocks/1", :method => :put },
{ :controller => "user_blocks", :action => "update", :id => "1" }
)
assert_routing(
{ :path => "/user_blocks/1", :method => :delete },
{ :controller => "user_blocks", :action => "destroy", :id => "1" }
)
assert_routing(
{ :path => "/blocks/1/revoke", :method => :get },
{ :controller => "user_blocks", :action => "revoke", :id => "1" }
)
assert_routing(
{ :path => "/blocks/1/revoke", :method => :post },
{ :controller => "user_blocks", :action => "revoke", :id => "1" }
)
assert_routing(
{ :path => "/user/username/blocks", :method => :get },
{ :controller => "user_blocks", :action => "blocks_on", :display_name => "username" }
)
assert_routing(
{ :path => "/user/username/blocks_by", :method => :get },
{ :controller => "user_blocks", :action => "blocks_by", :display_name => "username" }
)
end
##
# test the index action
def test_index
# The list of blocks should load
get :index
assert_response :success
assert_select "table#block_list", :count => 1 do
assert_select "tr", 4
assert_select "a[href='#{user_block_path(user_blocks(:active_block))}']", 1
assert_select "a[href='#{user_block_path(user_blocks(:expired_block))}']", 1
assert_select "a[href='#{user_block_path(user_blocks(:revoked_block))}']", 1
end
end
##
# test the show action
def test_show
# Viewing a block should fail when no ID is given
assert_raise ActionController::UrlGenerationError do
get :show
end
# Viewing a block should fail when a bogus ID is given
get :show, :id => 99999
assert_response :not_found
assert_template "not_found"
assert_select "p", "Sorry, the user block with ID 99999 could not be found."
# Viewing an expired block should work
get :show, :id => user_blocks(:expired_block)
assert_response :success
# Viewing a revoked block should work
get :show, :id => user_blocks(:revoked_block)
assert_response :success
# Viewing an active block should work, but shouldn't mark it as seen
get :show, :id => user_blocks(:active_block)
assert_response :success
assert_equal true, UserBlock.find(user_blocks(:active_block).id).needs_view
# Login as the blocked user
session[:user] = users(:blocked_user).id
# Now viewing it should mark it as seen
get :show, :id => user_blocks(:active_block)
assert_response :success
assert_equal false, UserBlock.find(user_blocks(:active_block).id).needs_view
end
##
# test the new action
def test_new
# Check that the block creation page requires us to login
get :new, :display_name => users(:normal_user).display_name
assert_redirected_to login_path(:referer => new_user_block_path(:display_name => users(:normal_user).display_name))
# Login as a normal user
session[:user] = users(:public_user).id
# Check that normal users can't load the block creation page
get :new, :display_name => users(:normal_user).display_name
assert_redirected_to user_blocks_path
assert_equal "You need to be a moderator to perform that action.", flash[:error]
# Login as a moderator
session[:user] = users(:moderator_user).id
# Check that the block creation page loads for moderators
get :new, :display_name => users(:normal_user).display_name
assert_response :success
assert_select "form#new_user_block", :count => 1 do
assert_select "textarea#user_block_reason", :count => 1
assert_select "select#user_block_period", :count => 1
assert_select "input#user_block_needs_view[type='checkbox']", :count => 1
assert_select "input#display_name[type='hidden']", :count => 1
assert_select "input[type='submit'][value='Create block']", :count => 1
end
# We should get an error if no user is specified
get :new
assert_response :not_found
assert_template "user/no_such_user"
assert_select "h1", "The user does not exist"
# We should get an error if the user doesn't exist
get :new, :display_name => "non_existent_user"
assert_response :not_found
assert_template "user/no_such_user"
assert_select "h1", "The user non_existent_user does not exist"
end
##
# test the edit action
def test_edit
# Check that the block edit page requires us to login
get :edit, :id => user_blocks(:active_block).id
assert_redirected_to login_path(:referer => edit_user_block_path(:id => user_blocks(:active_block).id))
# Login as a normal user
session[:user] = users(:public_user).id
# Check that normal users can't load the block edit page
get :edit, :id => user_blocks(:active_block).id
assert_redirected_to user_blocks_path
assert_equal "You need to be a moderator to perform that action.", flash[:error]
# Login as a moderator
session[:user] = users(:moderator_user).id
# Check that the block edit page loads for moderators
get :edit, :id => user_blocks(:active_block).id
assert_response :success
assert_select "form#edit_user_block_#{user_blocks(:active_block).id}", :count => 1 do
assert_select "textarea#user_block_reason", :count => 1
assert_select "select#user_block_period", :count => 1
assert_select "input#user_block_needs_view[type='checkbox']", :count => 1
assert_select "input[type='submit'][value='Update block']", :count => 1
end
# We should get an error if no user is specified
assert_raise ActionController::UrlGenerationError do
get :edit
end
# We should get an error if the user doesn't exist
get :edit, :id => 99999
assert_response :not_found
assert_template "not_found"
assert_select "p", "Sorry, the user block with ID 99999 could not be found."
end
##
# test the create action
def test_create
# Not logged in yet, so creating a block should fail
post :create
assert_response :forbidden
# Login as a normal user
session[:user] = users(:public_user).id
# Check that normal users can't create blocks
post :create
assert_response :forbidden
# Login as a moderator
session[:user] = users(:moderator_user).id
# A bogus block period should result in an error
assert_no_difference "UserBlock.count" do
post :create,
:display_name => users(:unblocked_user).display_name,
:user_block_period => "99"
end
assert_redirected_to new_user_block_path(:display_name => users(:unblocked_user).display_name)
assert_equal "The blocking period must be one of the values selectable in the drop-down list.", flash[:error]
# Check that creating a block works
assert_difference "UserBlock.count", 1 do
post :create,
:display_name => users(:unblocked_user).display_name,
:user_block_period => "12",
:user_block => { :needs_view => false, :reason => "Vandalism" }
end
assert_redirected_to user_block_path(:id => 4)
assert_equal "Created a block on user #{users(:unblocked_user).display_name}.", flash[:notice]
b = UserBlock.find(4)
assert_in_delta Time.now, b.created_at, 1
assert_in_delta Time.now, b.updated_at, 1
assert_in_delta Time.now + 12.hour, b.ends_at, 1
assert_equal false, b.needs_view
assert_equal "Vandalism", b.reason
assert_equal "markdown", b.reason_format
assert_equal users(:moderator_user).id, b.creator_id
# We should get an error if no user is specified
post :create
assert_response :not_found
assert_template "user/no_such_user"
assert_select "h1", "The user does not exist"
# We should get an error if the user doesn't exist
post :create, :display_name => "non_existent_user"
assert_response :not_found
assert_template "user/no_such_user"
assert_select "h1", "The user non_existent_user does not exist"
end
##
# test the update action
def test_update
# Not logged in yet, so updating a block should fail
put :update, :id => user_blocks(:active_block).id
assert_response :forbidden
# Login as a normal user
session[:user] = users(:public_user).id
# Check that normal users can't update blocks
put :update, :id => user_blocks(:active_block).id
assert_response :forbidden
# Login as the wrong moderator
session[:user] = users(:second_moderator_user).id
# Check that only the person who created a block can update it
assert_no_difference "UserBlock.count" do
put :update,
:id => user_blocks(:active_block).id,
:user_block_period => "12",
:user_block => { :needs_view => true, :reason => "Vandalism" }
end
assert_redirected_to edit_user_block_path(:id => user_blocks(:active_block).id)
assert_equal "Only the moderator who created this block can edit it.", flash[:error]
# Login as the correct moderator
session[:user] = users(:moderator_user).id
# A bogus block period should result in an error
assert_no_difference "UserBlock.count" do
put :update,
:id => user_blocks(:active_block).id,
:user_block_period => "99"
end
assert_redirected_to edit_user_block_path(:id => user_blocks(:active_block).id)
assert_equal "The blocking period must be one of the values selectable in the drop-down list.", flash[:error]
# Check that updating a block works
assert_no_difference "UserBlock.count" do
put :update,
:id => user_blocks(:active_block).id,
:user_block_period => "12",
:user_block => { :needs_view => true, :reason => "Vandalism" }
end
assert_redirected_to user_block_path(:id => user_blocks(:active_block).id)
assert_equal "Block updated.", flash[:notice]
b = UserBlock.find(user_blocks(:active_block).id)
assert_in_delta Time.now, b.updated_at, 1
assert_equal true, b.needs_view
assert_equal "Vandalism", b.reason
# We should get an error if no block ID is specified
assert_raise ActionController::UrlGenerationError do
put :update
end
# We should get an error if the block doesn't exist
put :update, :id => 99999
assert_response :not_found
assert_template "not_found"
assert_select "p", "Sorry, the user block with ID 99999 could not be found."
end
##
# test the revoke action
def test_revoke
# Check that the block revoke page requires us to login
get :revoke, :id => user_blocks(:active_block).id
assert_redirected_to login_path(:referer => revoke_user_block_path(:id => user_blocks(:active_block).id))
# Login as a normal user
session[:user] = users(:public_user).id
# Check that normal users can't load the block revoke page
get :revoke, :id => user_blocks(:active_block).id
assert_redirected_to user_blocks_path
assert_equal "You need to be a moderator to perform that action.", flash[:error]
# Login as a moderator
session[:user] = users(:moderator_user).id
# Check that the block revoke page loads for moderators
get :revoke, :id => user_blocks(:active_block).id
assert_response :success
assert_template "revoke"
assert_select "form", :count => 1 do
assert_select "input#confirm[type='checkbox']", :count => 1
assert_select "input[type='submit'][value='Revoke!']", :count => 1
end
# Check that revoking a block works
post :revoke, :id => user_blocks(:active_block).id, :confirm => true
assert_redirected_to user_block_path(:id => user_blocks(:active_block).id)
b = UserBlock.find(user_blocks(:active_block).id)
assert_in_delta Time.now, b.ends_at, 1
# We should get an error if no block ID is specified
assert_raise ActionController::UrlGenerationError do
get :revoke
end
# We should get an error if the block doesn't exist
get :revoke, :id => 99999
assert_response :not_found
assert_template "not_found"
assert_select "p", "Sorry, the user block with ID 99999 could not be found."
end
##
# test the blocks_on action
def test_blocks_on
# Asking for a list of blocks with no user name should fail
assert_raise ActionController::UrlGenerationError do
get :blocks_on
end
# Asking for a list of blocks with a bogus user name should fail
get :blocks_on, :display_name => "non_existent_user"
assert_response :not_found
assert_template "user/no_such_user"
assert_select "h1", "The user non_existent_user does not exist"
# Check the list of blocks for a user that has never been blocked
get :blocks_on, :display_name => users(:normal_user).display_name
assert_response :success
assert_select "table#block_list", false
assert_select "p", "#{users(:normal_user).display_name} has not been blocked yet."
# Check the list of blocks for a user that is currently blocked
get :blocks_on, :display_name => users(:blocked_user).display_name
assert_response :success
assert_select "table#block_list", :count => 1 do
assert_select "tr", 3
assert_select "a[href='#{user_block_path(user_blocks(:active_block))}']", 1
assert_select "a[href='#{user_block_path(user_blocks(:revoked_block))}']", 1
end
# Check the list of blocks for a user that has previously been blocked
get :blocks_on, :display_name => users(:unblocked_user).display_name
assert_response :success
assert_select "table#block_list", :count => 1 do
assert_select "tr", 2
assert_select "a[href='#{user_block_path(user_blocks(:expired_block))}']", 1
end
end
##
# test the blocks_by action
def test_blocks_by
# Asking for a list of blocks with no user name should fail
assert_raise ActionController::UrlGenerationError do
get :blocks_by
end
# Asking for a list of blocks with a bogus user name should fail
get :blocks_by, :display_name => "non_existent_user"
assert_response :not_found
assert_template "user/no_such_user"
assert_select "h1", "The user non_existent_user does not exist"
# Check the list of blocks given by one moderator
get :blocks_by, :display_name => users(:moderator_user).display_name
assert_response :success
assert_select "table#block_list", :count => 1 do
assert_select "tr", 2
assert_select "a[href='#{user_block_path(user_blocks(:active_block))}']", 1
end
# Check the list of blocks given by a different moderator
get :blocks_by, :display_name => users(:second_moderator_user).display_name
assert_response :success
assert_select "table#block_list", :count => 1 do
assert_select "tr", 3
assert_select "a[href='#{user_block_path(user_blocks(:expired_block))}']", 1
assert_select "a[href='#{user_block_path(user_blocks(:revoked_block))}']", 1
end
# Check the list of blocks (not) given by a normal user
get :blocks_by, :display_name => users(:normal_user).display_name
assert_response :success
assert_select "table#block_list", false
assert_select "p", "#{users(:normal_user).display_name} has not made any blocks yet."
end
end

View file

@ -0,0 +1,855 @@
require 'test_helper'
class UserControllerTest < ActionController::TestCase
fixtures :users
##
# test all routes which lead to this controller
def test_routes
assert_routing(
{ :path => "/api/0.6/user/1", :method => :get },
{ :controller => "user", :action => "api_read", :id => "1" }
)
assert_routing(
{ :path => "/api/0.6/user/details", :method => :get },
{ :controller => "user", :action => "api_details" }
)
assert_routing(
{ :path => "/api/0.6/user/gpx_files", :method => :get },
{ :controller => "user", :action => "api_gpx_files" }
)
assert_routing(
{ :path => "/login", :method => :get },
{ :controller => "user", :action => "login" }
)
assert_routing(
{ :path => "/login", :method => :post },
{ :controller => "user", :action => "login" }
)
assert_recognizes(
{ :controller => "user", :action => "login", :format => "html" },
{ :path => "/login.html", :method => :get }
)
assert_routing(
{ :path => "/logout", :method => :get },
{ :controller => "user", :action => "logout" }
)
assert_routing(
{ :path => "/logout", :method => :post },
{ :controller => "user", :action => "logout" }
)
assert_recognizes(
{ :controller => "user", :action => "logout", :format => "html" },
{ :path => "/logout.html", :method => :get }
)
assert_routing(
{ :path => "/user/new", :method => :get },
{ :controller => "user", :action => "new" }
)
assert_routing(
{ :path => "/user/new", :method => :post },
{ :controller => "user", :action => "create" }
)
assert_routing(
{ :path => "/user/terms", :method => :get },
{ :controller => "user", :action => "terms" }
)
assert_routing(
{ :path => "/user/save", :method => :post },
{ :controller => "user", :action => "save" }
)
assert_routing(
{ :path => "/user/username/confirm", :method => :get },
{ :controller => "user", :action => "confirm", :display_name => "username" }
)
assert_routing(
{ :path => "/user/username/confirm", :method => :post },
{ :controller => "user", :action => "confirm", :display_name => "username" }
)
assert_routing(
{ :path => "/user/username/confirm/resend", :method => :get },
{ :controller => "user", :action => "confirm_resend", :display_name => "username" }
)
assert_routing(
{ :path => "/user/confirm", :method => :get },
{ :controller => "user", :action => "confirm" }
)
assert_routing(
{ :path => "/user/confirm", :method => :post },
{ :controller => "user", :action => "confirm" }
)
assert_routing(
{ :path => "/user/confirm-email", :method => :get },
{ :controller => "user", :action => "confirm_email" }
)
assert_routing(
{ :path => "/user/confirm-email", :method => :post },
{ :controller => "user", :action => "confirm_email" }
)
assert_routing(
{ :path => "/user/go_public", :method => :post },
{ :controller => "user", :action => "go_public" }
)
assert_routing(
{ :path => "/user/forgot-password", :method => :get },
{ :controller => "user", :action => "lost_password" }
)
assert_routing(
{ :path => "/user/forgot-password", :method => :post },
{ :controller => "user", :action => "lost_password" }
)
assert_routing(
{ :path => "/user/reset-password", :method => :get },
{ :controller => "user", :action => "reset_password" }
)
assert_routing(
{ :path => "/user/reset-password", :method => :post },
{ :controller => "user", :action => "reset_password" }
)
assert_routing(
{ :path => "/user/suspended", :method => :get },
{ :controller => "user", :action => "suspended" }
)
assert_routing(
{ :path => "/user/username", :method => :get },
{ :controller => "user", :action => "view", :display_name => "username" }
)
assert_routing(
{ :path => "/user/username/account", :method => :get },
{ :controller => "user", :action => "account", :display_name => "username" }
)
assert_routing(
{ :path => "/user/username/account", :method => :post },
{ :controller => "user", :action => "account", :display_name => "username" }
)
assert_routing(
{ :path => "/user/username/make_friend", :method => :get },
{ :controller => "user", :action => "make_friend", :display_name => "username" }
)
assert_routing(
{ :path => "/user/username/make_friend", :method => :post },
{ :controller => "user", :action => "make_friend", :display_name => "username" }
)
assert_routing(
{ :path => "/user/username/remove_friend", :method => :get },
{ :controller => "user", :action => "remove_friend", :display_name => "username" }
)
assert_routing(
{ :path => "/user/username/remove_friend", :method => :post },
{ :controller => "user", :action => "remove_friend", :display_name => "username" }
)
assert_routing(
{ :path => "/user/username/set_status", :method => :get },
{ :controller => "user", :action => "set_status", :display_name => "username" }
)
assert_routing(
{ :path => "/user/username/delete", :method => :get },
{ :controller => "user", :action => "delete", :display_name => "username" }
)
assert_routing(
{ :path => "/users", :method => :get },
{ :controller => "user", :action => "list" }
)
assert_routing(
{ :path => "/users", :method => :post },
{ :controller => "user", :action => "list" }
)
assert_routing(
{ :path => "/users/status", :method => :get },
{ :controller => "user", :action => "list", :status => "status" }
)
assert_routing(
{ :path => "/users/status", :method => :post },
{ :controller => "user", :action => "list", :status => "status" }
)
end
# The user creation page loads
def test_user_create_view
get :new
assert_response :redirect
assert_redirected_to user_new_path(:cookie_test => "true")
get :new, { :cookie_test => "true" }, { :cookie_test => true }
assert_response :success
assert_select "html", :count => 1 do
assert_select "head", :count => 1 do
assert_select "title", :text => /Sign Up/, :count => 1
end
assert_select "body", :count => 1 do
assert_select "div#content", :count => 1 do
assert_select "form[action='/user/new'][method=post]", :count => 1 do
assert_select "input[id=user_email]", :count => 1
assert_select "input[id=user_email_confirmation]", :count => 1
assert_select "input[id=user_display_name]", :count => 1
assert_select "input[id=user_pass_crypt][type=password]", :count => 1
assert_select "input[id=user_pass_crypt_confirmation][type=password]", :count => 1
assert_select "input[type=submit][value=Sign Up]", :count => 1
end
end
end
end
end
def new_user
user = User.new
user.status = "pending"
user.display_name = "new_tester"
user.email = "newtester@osm.org"
user.email_confirmation = "newtester@osm.org"
user.pass_crypt = "testtest"
user.pass_crypt_confirmation = "testtest"
user
end
def test_user_create_success
user = new_user
assert_difference('User.count') do
assert_difference('ActionMailer::Base.deliveries.size') do
post :save, {}, {:new_user => user}
end
end
# Check the e-mail
register_email = ActionMailer::Base.deliveries.first
assert_equal register_email.to[0], user.email
assert_match /#{@url}/, register_email.body.to_s
# Check the page
assert_redirected_to :action => 'confirm', :display_name => user.display_name
ActionMailer::Base.deliveries.clear
end
def test_user_create_submit_duplicate_email
user = new_user
user.email = users(:public_user).email
assert_no_difference('User.count') do
assert_no_difference('ActionMailer::Base.deliveries.size') do
post :save, {}, {:new_user => user}
end
end
assert_response :success
assert_template 'new'
assert_select "form > fieldset > div.form-row > input.field_with_errors#user_email"
end
def test_user_create_submit_duplicate_email_uppercase
user = new_user
user.email = users(:public_user).email.upcase
assert_no_difference('User.count') do
assert_no_difference('ActionMailer::Base.deliveries.size') do
post :save, {}, {:new_user => user}
end
end
assert_response :success
assert_template 'new'
assert_select "form > fieldset > div.form-row > input.field_with_errors#user_email"
end
def test_user_create_submit_duplicate_name
user = new_user
user.display_name = users(:public_user).display_name
assert_no_difference('User.count') do
assert_no_difference('ActionMailer::Base.deliveries.size') do
post :save, {}, {:new_user => user}
end
end
assert_response :success
assert_template 'new'
assert_select "form > fieldset > div.form-row > input.field_with_errors#user_display_name"
end
def test_user_create_submit_duplicate_name_uppercase
user = new_user
user.display_name = users(:public_user).display_name.upcase
assert_no_difference('User.count') do
assert_no_difference('ActionMailer::Base.deliveries.size') do
post :save, {}, {:new_user => user}
end
end
assert_response :success
assert_template 'new'
assert_select "form > fieldset > div.form-row > input.field_with_errors#user_display_name"
end
def test_user_save_referer_params
user = new_user
post :save, {}, {:new_user => user,
:referer => '/edit?editor=id#map=1/2/3'}
assert_equal welcome_path(:editor => 'id', :zoom => 1, :lat => 2, :lon => 3),
user.tokens.order("id DESC").first.referer
end
def test_user_confirm_expired_token
user = users(:inactive_user)
token = user.tokens.new
token.expiry = 1.day.ago
token.save!
@request.cookies["_osm_session"] = user.display_name
post :confirm, :confirm_string => token.token
assert_redirected_to :action => 'confirm'
assert_match /expired/, flash[:error]
end
def test_user_already_confirmed
user = users(:normal_user)
token = user.tokens.create
@request.cookies["_osm_session"] = user.display_name
post :confirm, :confirm_string => token.token
assert_redirected_to :action => 'login'
assert_match /confirmed/, flash[:error]
end
def test_user_terms_new_user
get :terms, {}, { "new_user" => User.new }
assert_response :success
assert_template :terms
end
def test_user_terms_seen
user = users(:normal_user)
get :terms, {}, { "user" => user }
assert_response :redirect
assert_redirected_to :action => :account, :display_name => user.display_name
end
def test_user_go_public
post :go_public, {}, { :user => users(:normal_user) }
assert_response :redirect
assert_redirected_to :action => :account, :display_name => users(:normal_user).display_name
assert_equal true, User.find(users(:normal_user).id).data_public
end
def test_user_lost_password
# Test fetching the lost password page
get :lost_password
assert_response :success
assert_template :lost_password
assert_select "div#notice", false
# Test resetting using the address as recorded for a user that has an
# address which is duplicated in a different case by another user
assert_difference('ActionMailer::Base.deliveries.size', 1) do
post :lost_password, :user => { :email => users(:normal_user).email }
end
assert_response :redirect
assert_redirected_to :action => :login
assert_match /^Sorry you lost it/, flash[:notice]
assert_equal users(:normal_user).email, ActionMailer::Base.deliveries.last.to[0]
# Test resetting using an address that matches a different user
# that has the same address in a different case
assert_difference('ActionMailer::Base.deliveries.size', 1) do
post :lost_password, :user => { :email => users(:normal_user).email.upcase }
end
assert_response :redirect
assert_redirected_to :action => :login
assert_match /^Sorry you lost it/, flash[:notice]
assert_equal users(:uppercase_user).email, ActionMailer::Base.deliveries.last.to[0]
# Test resetting using an address that is a case insensitive match
# for more than one user but not an exact match for either
assert_difference('ActionMailer::Base.deliveries.size', 0) do
post :lost_password, :user => { :email => users(:normal_user).email.titlecase }
end
assert_response :success
assert_template :lost_password
assert_select ".error", /^Could not find that email address/
# Test resetting using the address as recorded for a user that has an
# address which is case insensitively unique
assert_difference('ActionMailer::Base.deliveries.size', 1) do
post :lost_password, :user => { :email => users(:public_user).email }
end
assert_response :redirect
assert_redirected_to :action => :login
assert_match /^Sorry you lost it/, flash[:notice]
assert_equal users(:public_user).email, ActionMailer::Base.deliveries.last.to[0]
# Test resetting using an address that matches a user that has the
# same (case insensitively unique) address in a different case
assert_difference('ActionMailer::Base.deliveries.size', 1) do
post :lost_password, :user => { :email => users(:public_user).email.upcase }
end
assert_response :redirect
assert_redirected_to :action => :login
assert_match /^Sorry you lost it/, flash[:notice]
assert_equal users(:public_user).email, ActionMailer::Base.deliveries.last.to[0]
end
def test_reset_password
# Test a request with no token
get :reset_password
assert_response :bad_request
# Test a request with a bogus token
get :reset_password, :token => "made_up_token"
assert_response :redirect
assert_redirected_to :action => :lost_password
# Create a valid token for a user
token = User.find(users(:inactive_user).id).tokens.create
# Test a request with a valid token
get :reset_password, :token => token.token
assert_response :success
assert_template :reset_password
# Test setting a new password
post :reset_password, :token => token.token, :user => { :pass_crypt => "new_password", :pass_crypt_confirmation => "new_password" }
assert_response :redirect
assert_redirected_to :action => :login
user = User.find(users(:inactive_user).id)
assert_equal "active", user.status
assert_equal true, user.email_valid
assert_equal user, User.authenticate(:username => "inactive@openstreetmap.org", :password => "new_password")
end
def test_user_update
# Get a user to work with - note that this user deliberately
# conflicts with uppercase_user in the email and display name
# fields to test that we can change other fields without any
# validation errors being reported
user = users(:normal_user)
# Make sure that you are redirected to the login page when
# you are not logged in
get :account, { :display_name => user.display_name }
assert_response :redirect
assert_redirected_to :controller => :user, :action => "login", :referer => "/user/test/account"
# Make sure that you are blocked when not logged in as the right user
get :account, { :display_name => user.display_name }, { "user" => users(:public_user).id }
assert_response :forbidden
# Make sure we get the page when we are logged in as the right user
get :account, { :display_name => user.display_name }, { "user" => user }
assert_response :success
assert_template :account
# Updating the description should work
user.description = "new description"
post :account, { :display_name => user.display_name, :user => user.attributes }, { "user" => user.id }
assert_response :success
assert_template :account
assert_select "div#errorExplanation", false
assert_select ".notice", /^User information updated successfully/
assert_select "form#accountForm > fieldset > div.form-row > div#user_description_container > div#user_description_content > textarea#user_description", user.description
# Changing name to one that exists should fail
new_attributes = user.attributes.dup.merge(:display_name => users(:public_user).display_name)
post :account, { :display_name => user.display_name, :user => new_attributes }, { "user" => user.id }
assert_response :success
assert_template :account
assert_select ".notice", false
assert_select "div#errorExplanation"
assert_select "form#accountForm > fieldset > div.form-row > input.field_with_errors#user_display_name"
# Changing name to one that exists should fail, regardless of case
new_attributes = user.attributes.dup.merge(:display_name => users(:public_user).display_name.upcase)
post :account, { :display_name => user.display_name, :user => new_attributes }, { "user" => user.id }
assert_response :success
assert_template :account
assert_select ".notice", false
assert_select "div#errorExplanation"
assert_select "form#accountForm > fieldset > div.form-row > input.field_with_errors#user_display_name"
# Changing name to one that doesn't exist should work
new_attributes = user.attributes.dup.merge(:display_name => "new tester")
post :account, { :display_name => user.display_name, :user => new_attributes }, { "user" => user.id }
assert_response :success
assert_template :account
assert_select "div#errorExplanation", false
assert_select ".notice", /^User information updated successfully/
assert_select "form#accountForm > fieldset > div.form-row > input#user_display_name[value=?]", "new tester"
# Record the change of name
user.display_name = "new tester"
# Changing email to one that exists should fail
user.new_email = users(:public_user).email
post :account, { :display_name => user.display_name, :user => user.attributes }, { "user" => user.id }
assert_response :success
assert_template :account
assert_select ".notice", false
assert_select "div#errorExplanation"
assert_select "form#accountForm > fieldset > div.form-row > input.field_with_errors#user_new_email"
# Changing email to one that exists should fail, regardless of case
user.new_email = users(:public_user).email.upcase
post :account, { :display_name => user.display_name, :user => user.attributes }, { "user" => user.id }
assert_response :success
assert_template :account
assert_select ".notice", false
assert_select "div#errorExplanation"
assert_select "form#accountForm > fieldset > div.form-row > input.field_with_errors#user_new_email"
# Changing email to one that doesn't exist should work
user.new_email = "new_tester@example.com"
post :account, { :display_name => user.display_name, :user => user.attributes }, { "user" => user.id }
assert_response :success
assert_template :account
assert_select "div#errorExplanation", false
assert_select ".notice", /^User information updated successfully/
assert_select "form#accountForm > fieldset > div.form-row > input#user_new_email[value=?]", user.new_email
end
# Check that the user account page will display and contains some relevant
# information for the user
def test_user_view_account
# Test a non-existent user
get :view, {:display_name => "unknown"}
assert_response :not_found
# Test a normal user
get :view, {:display_name => "test"}
assert_response :success
assert_select "div#userinformation" do
assert_select "a[href^=/user/test/history]", 1
assert_select "a[href=/user/test/traces]", 1
assert_select "a[href=/user/test/diary]", 1
assert_select "a[href=/user/test/diary/comments]", 1
assert_select "a[href=/user/test/account]", 0
assert_select "a[href=/user/test/blocks]", 0
assert_select "a[href=/user/test/blocks_by]", 0
assert_select "a[href=/blocks/new/test]", 0
end
# Test a user who has been blocked
get :view, {:display_name => "blocked"}
assert_response :success
assert_select "div#userinformation" do
assert_select "a[href^=/user/blocked/history]", 1
assert_select "a[href=/user/blocked/traces]", 1
assert_select "a[href=/user/blocked/diary]", 1
assert_select "a[href=/user/blocked/diary/comments]", 1
assert_select "a[href=/user/blocked/account]", 0
assert_select "a[href=/user/blocked/blocks]", 1
assert_select "a[href=/user/blocked/blocks_by]", 0
assert_select "a[href=/blocks/new/blocked]", 0
end
# Test a moderator who has applied blocks
get :view, {:display_name => "moderator"}
assert_response :success
assert_select "div#userinformation" do
assert_select "a[href^=/user/moderator/history]", 1
assert_select "a[href=/user/moderator/traces]", 1
assert_select "a[href=/user/moderator/diary]", 1
assert_select "a[href=/user/moderator/diary/comments]", 1
assert_select "a[href=/user/moderator/account]", 0
assert_select "a[href=/user/moderator/blocks]", 0
assert_select "a[href=/user/moderator/blocks_by]", 1
assert_select "a[href=/blocks/new/moderator]", 0
end
# Login as a normal user
session[:user] = users(:normal_user).id
# Test the normal user
get :view, {:display_name => "test"}
assert_response :success
assert_select "div#userinformation" do
assert_select "a[href^=/user/test/history]", 1
assert_select "a[href=/traces/mine]", 1
assert_select "a[href=/user/test/diary]", 1
assert_select "a[href=/user/test/diary/comments]", 1
assert_select "a[href=/user/test/account]", 1
assert_select "a[href=/user/test/blocks]", 0
assert_select "a[href=/user/test/blocks_by]", 0
assert_select "a[href=/blocks/new/test]", 0
end
# Login as a moderator
session[:user] = users(:moderator_user).id
# Test the normal user
get :view, {:display_name => "test"}
assert_response :success
assert_select "div#userinformation" do
assert_select "a[href^=/user/test/history]", 1
assert_select "a[href=/user/test/traces]", 1
assert_select "a[href=/user/test/diary]", 1
assert_select "a[href=/user/test/diary/comments]", 1
assert_select "a[href=/user/test/account]", 0
assert_select "a[href=/user/test/blocks]", 0
assert_select "a[href=/user/test/blocks_by]", 0
assert_select "a[href=/blocks/new/test]", 1
end
end
def test_user_api_read
# check that a visible user is returned properly
get :api_read, :id => users(:normal_user).id
assert_response :success
# check the data that is returned
assert_select "description", :count => 1, :text => "test"
assert_select "contributor-terms", :count => 1 do
assert_select "[agreed=true]"
end
assert_select "img", :count => 1
assert_select "roles", :count => 1 do
assert_select "role", :count => 0
end
assert_select "changesets", :count => 1 do
assert_select "[count=0]"
end
assert_select "traces", :count => 1 do
assert_select "[count=0]"
end
assert_select "blocks", :count => 1 do
assert_select "received", :count => 1 do
assert_select "[count=0][active=0]"
end
assert_select "issued", :count => 0
end
# check that we aren't revealing private information
assert_select "contributor-terms[pd]", false
assert_select "home", false
assert_select "languages", false
assert_select "messages", false
# check that a suspended user is not returned
get :api_read, :id => users(:suspended_user).id
assert_response :gone
# check that a deleted user is not returned
get :api_read, :id => users(:deleted_user).id
assert_response :gone
# check that a non-existent user is not returned
get :api_read, :id => 0
assert_response :not_found
end
def test_user_api_details
# check that nothing is returned when not logged in
get :api_details
assert_response :unauthorized
# check that we get a response when logged in
basic_authorization(users(:normal_user).email, "test")
get :api_details
assert_response :success
# check the data that is returned
assert_select "description", :count => 1, :text => "test"
assert_select "contributor-terms", :count => 1 do
assert_select "[agreed=true][pd=false]"
end
assert_select "img", :count => 1
assert_select "roles", :count => 1 do
assert_select "role", :count => 0
end
assert_select "changesets", :count => 1 do
assert_select "[count=0]", :count => 1
end
assert_select "traces", :count => 1 do
assert_select "[count=0]", :count => 1
end
assert_select "blocks", :count => 1 do
assert_select "received", :count => 1 do
assert_select "[count=0][active=0]"
end
assert_select "issued", :count => 0
end
assert_select "home", :count => 1 do
assert_select "[lat=12.1][lon=12.1][zoom=3]"
end
assert_select "languages", :count => 1 do
assert_select "lang", :count => 1, :text => "en"
end
assert_select "messages", :count => 1 do
assert_select "received", :count => 1 do
assert_select "[count=1][unread=0]"
end
assert_select "sent", :count => 1 do
assert_select "[count=1]"
end
end
end
def test_user_make_friend
# Get users to work with
user = users(:normal_user)
friend = users(:second_public_user)
# Check that the users aren't already friends
assert_nil Friend.where(:user_id => user.id, :friend_user_id => friend.id).first
# When not logged in a GET should ask us to login
get :make_friend, {:display_name => friend.display_name}
assert_redirected_to :controller => :user, :action => "login", :referer => make_friend_path(:display_name => friend.display_name)
# When not logged in a POST should error
post :make_friend, {:display_name => friend.display_name}
assert_response :forbidden
assert_nil Friend.where(:user_id => user.id, :friend_user_id => friend.id).first
# When logged in a GET should get a confirmation page
get :make_friend, {:display_name => friend.display_name}, {"user" => user}
assert_response :success
assert_template :make_friend
assert_select "form" do
assert_select "input[type=hidden][name=referer]", 0
assert_select "input[type=submit]", 1
end
assert_nil Friend.where(:user_id => user.id, :friend_user_id => friend.id).first
# The GET should preserve any referer
get :make_friend, {:display_name => friend.display_name, :referer => "/test"}, {"user" => user}
assert_response :success
assert_template :make_friend
assert_select "form" do
assert_select "input[type=hidden][name=referer][value=/test]", 1
assert_select "input[type=submit]", 1
end
assert_nil Friend.where(:user_id => user.id, :friend_user_id => friend.id).first
# When logged in a POST should add the friendship
post :make_friend, {:display_name => friend.display_name}, {"user" => user}
assert_redirected_to user_path(:display_name => friend.display_name)
assert_match /is now your friend/, flash[:notice]
assert Friend.where(:user_id => user.id, :friend_user_id => friend.id).first
# A second POST should report that the friendship already exists
post :make_friend, {:display_name => friend.display_name}, {"user" => user}
assert_redirected_to user_path(:display_name => friend.display_name)
assert_match /You are already friends with/, flash[:warning]
assert Friend.where(:user_id => user.id, :friend_user_id => friend.id).first
end
def test_user_remove_friend
# Get users to work with
user = users(:normal_user)
friend = users(:public_user)
# Check that the users are friends
assert Friend.where(:user_id => user.id, :friend_user_id => friend.id).first
# When not logged in a GET should ask us to login
get :remove_friend, {:display_name => friend.display_name}
assert_redirected_to :controller => :user, :action => "login", :referer => remove_friend_path(:display_name => friend.display_name)
# When not logged in a POST should error
post :remove_friend, {:display_name => friend.display_name}
assert_response :forbidden
assert Friend.where(:user_id => user.id, :friend_user_id => friend.id).first
# When logged in a GET should get a confirmation page
get :remove_friend, {:display_name => friend.display_name}, {"user" => user}
assert_response :success
assert_template :remove_friend
assert_select "form" do
assert_select "input[type=hidden][name=referer]", 0
assert_select "input[type=submit]", 1
end
assert Friend.where(:user_id => user.id, :friend_user_id => friend.id).first
# The GET should preserve any referer
get :remove_friend, {:display_name => friend.display_name, :referer => "/test"}, {"user" => user}
assert_response :success
assert_template :remove_friend
assert_select "form" do
assert_select "input[type=hidden][name=referer][value=/test]", 1
assert_select "input[type=submit]", 1
end
assert Friend.where(:user_id => user.id, :friend_user_id => friend.id).first
# When logged in a POST should remove the friendship
post :remove_friend, {:display_name => friend.display_name}, {"user" => user}
assert_redirected_to user_path(:display_name => friend.display_name)
assert_match /was removed from your friends/, flash[:notice]
assert_nil Friend.where(:user_id => user.id, :friend_user_id => friend.id).first
# A second POST should report that the friendship does not exist
post :remove_friend, {:display_name => friend.display_name}, {"user" => user}
assert_redirected_to user_path(:display_name => friend.display_name)
assert_match /is not one of your friends/, flash[:error]
assert_nil Friend.where(:user_id => user.id, :friend_user_id => friend.id).first
end
def test_set_status
# Try without logging in
get :set_status, {:display_name => users(:normal_user).display_name, :status => "suspended"}
assert_response :redirect
assert_redirected_to :action => :login, :referer => set_status_user_path(:status => "suspended")
# Now try as a normal user
get :set_status, {:display_name => users(:normal_user).display_name, :status => "suspended"}, {:user => users(:normal_user).id}
assert_response :redirect
assert_redirected_to :action => :view, :display_name => users(:normal_user).display_name
# Finally try as an administrator
get :set_status, {:display_name => users(:normal_user).display_name, :status => "suspended"}, {:user => users(:administrator_user).id}
assert_response :redirect
assert_redirected_to :action => :view, :display_name => users(:normal_user).display_name
assert_equal "suspended", User.find(users(:normal_user).id).status
end
def test_delete
# Try without logging in
get :delete, {:display_name => users(:normal_user).display_name, :status => "suspended"}
assert_response :redirect
assert_redirected_to :action => :login, :referer => delete_user_path(:status => "suspended")
# Now try as a normal user
get :delete, {:display_name => users(:normal_user).display_name, :status => "suspended"}, {:user => users(:normal_user).id}
assert_response :redirect
assert_redirected_to :action => :view, :display_name => users(:normal_user).display_name
# Finally try as an administrator
get :delete, {:display_name => users(:normal_user).display_name, :status => "suspended"}, {:user => users(:administrator_user).id}
assert_response :redirect
assert_redirected_to :action => :view, :display_name => users(:normal_user).display_name
# Check that the user was deleted properly
user = User.find(users(:normal_user).id)
assert_equal "user_1", user.display_name
assert_equal "", user.description
assert_nil user.home_lat
assert_nil user.home_lon
assert_equal false, user.image.file?
assert_equal false, user.email_valid
assert_nil user.new_email
assert_nil user.openid_url
assert_equal "deleted", user.status
end
end

View file

@ -0,0 +1,206 @@
require 'test_helper'
class UserPreferenceControllerTest < ActionController::TestCase
fixtures :users, :user_preferences
##
# test all routes which lead to this controller
def test_routes
assert_routing(
{ :path => "/api/0.6/user/preferences", :method => :get },
{ :controller => "user_preference", :action => "read" }
)
assert_routing(
{ :path => "/api/0.6/user/preferences", :method => :put },
{ :controller => "user_preference", :action => "update" }
)
assert_routing(
{ :path => "/api/0.6/user/preferences/key", :method => :get },
{ :controller => "user_preference", :action => "read_one", :preference_key => "key" }
)
assert_routing(
{ :path => "/api/0.6/user/preferences/key", :method => :put },
{ :controller => "user_preference", :action => "update_one", :preference_key => "key" }
)
assert_routing(
{ :path => "/api/0.6/user/preferences/key", :method => :delete },
{ :controller => "user_preference", :action => "delete_one", :preference_key => "key" }
)
end
##
# test read action
def test_read
# first try without auth
get :read
assert_response :unauthorized, "should be authenticated"
# authenticate as a user with no preferences
basic_authorization("test@example.com", "test")
# try the read again
get :read
assert_select "osm" do
assert_select "preferences", :count => 1 do
assert_select "preference", :count => 0
end
end
# authenticate as a user with preferences
basic_authorization("test@openstreetmap.org", "test")
# try the read again
get :read
assert_response :success
assert_equal "text/xml", @response.content_type
assert_select "osm" do
assert_select "preferences", :count => 1 do
assert_select "preference", :count => 2
assert_select "preference[k=\"#{user_preferences(:a).k}\"][v=\"#{user_preferences(:a).v}\"]", :count => 1
assert_select "preference[k=\"#{user_preferences(:two).k}\"][v=\"#{user_preferences(:two).v}\"]", :count => 1
end
end
end
##
# test read_one action
def test_read_one
# try a read without auth
get :read_one, :preference_key => "key"
assert_response :unauthorized, "should be authenticated"
# authenticate as a user with preferences
basic_authorization("test@openstreetmap.org", "test")
# try the read again
get :read_one, :preference_key => "key"
assert_response :success
assert_equal "text/plain", @response.content_type
assert_equal "value", @response.body
# try the read again for a non-existent key
get :read_one, :preference_key => "unknown_key"
assert_response :not_found
end
##
# test update action
def test_update
# try a put without auth
assert_no_difference "UserPreference.count" do
content "<osm><preferences><preference k='key' v='new_value'/><preference k='new_key' v='value'/></preferences></osm>"
put :update
end
assert_response :unauthorized, "should be authenticated"
assert_equal "value", UserPreference.find(1, "key").v
assert_equal "some_value", UserPreference.find(1, "some_key").v
assert_raises ActiveRecord::RecordNotFound do
UserPreference.find(1, "new_key")
end
# authenticate as a user with preferences
basic_authorization("test@openstreetmap.org", "test")
# try the put again
assert_no_difference "UserPreference.count" do
content "<osm><preferences><preference k='key' v='new_value'/><preference k='new_key' v='value'/></preferences></osm>"
put :update
end
assert_response :success
assert_equal "text/plain", @response.content_type
assert_equal "", @response.body
assert_equal "new_value", UserPreference.find(1, "key").v
assert_equal "value", UserPreference.find(1, "new_key").v
assert_raises ActiveRecord::RecordNotFound do
UserPreference.find(1, "some_key")
end
# try a put with duplicate keys
assert_no_difference "UserPreference.count" do
content "<osm><preferences><preference k='key' v='value'/><preference k='key' v='newer_value'/></preferences></osm>"
put :update
end
assert_response :bad_request
assert_equal "text/plain", @response.content_type
assert_equal "Duplicate preferences with key key", @response.body
assert_equal "new_value", UserPreference.find(1, "key").v
# try a put with invalid content
assert_no_difference "UserPreference.count" do
content "nonsense"
put :update
end
assert_response :bad_request
end
##
# test update_one action
def test_update_one
# try a put without auth
assert_no_difference "UserPreference.count" do
content "new_value"
put :update_one, :preference_key => "new_key"
end
assert_response :unauthorized, "should be authenticated"
assert_raises ActiveRecord::RecordNotFound do
UserPreference.find(1, "new_key")
end
# authenticate as a user with preferences
basic_authorization("test@openstreetmap.org", "test")
# try adding a new preference
assert_difference "UserPreference.count", 1 do
content "new_value"
put :update_one, :preference_key => "new_key"
end
assert_response :success
assert_equal "text/plain", @response.content_type
assert_equal "", @response.body
assert_equal "new_value", UserPreference.find(1, "new_key").v
# try changing the value of a preference
assert_no_difference "UserPreference.count" do
content "newer_value"
put :update_one, :preference_key => "new_key"
end
assert_response :success
assert_equal "text/plain", @response.content_type
assert_equal "", @response.body
assert_equal "newer_value", UserPreference.find(1, "new_key").v
end
##
# test delete_one action
def test_delete_one
# try a delete without auth
assert_no_difference "UserPreference.count" do
delete :delete_one, :preference_key => "key"
end
assert_response :unauthorized, "should be authenticated"
assert_equal "value", UserPreference.find(1, "key").v
# authenticate as a user with preferences
basic_authorization("test@openstreetmap.org", "test")
# try the delete again
assert_difference "UserPreference.count", -1 do
get :delete_one, :preference_key => "key"
end
assert_response :success
assert_equal "text/plain", @response.content_type
assert_equal "", @response.body
assert_raises ActiveRecord::RecordNotFound do
UserPreference.find(1, "key")
end
# try the delete again for the same key
assert_no_difference "UserPreference.count" do
get :delete_one, :preference_key => "key"
end
assert_response :not_found
assert_raises ActiveRecord::RecordNotFound do
UserPreference.find(1, "key")
end
end
end

View file

@ -0,0 +1,134 @@
require 'test_helper'
class UserRolesControllerTest < ActionController::TestCase
fixtures :users, :user_roles
##
# test all routes which lead to this controller
def test_routes
assert_routing(
{ :path => "/user/username/role/rolename/grant", :method => :post },
{ :controller => "user_roles", :action => "grant", :display_name => "username", :role => "rolename" }
)
assert_routing(
{ :path => "/user/username/role/rolename/revoke", :method => :post },
{ :controller => "user_roles", :action => "revoke", :display_name => "username", :role => "rolename" }
)
end
##
# test the grant action
def test_grant
# Granting should fail when not logged in
post :grant, :display_name => users(:normal_user).display_name, :role => "moderator"
assert_response :forbidden
# Login as an unprivileged user
session[:user] = users(:public_user).id
# Granting should still fail
post :grant, :display_name => users(:normal_user).display_name, :role => "moderator"
assert_redirected_to user_path(users(:normal_user).display_name)
assert_equal "Only administrators can perform user role management, and you are not an administrator.", flash[:error]
# Login as an administrator
session[:user] = users(:administrator_user).id
UserRole::ALL_ROLES.each do |role|
# Granting a role to a non-existent user should fail
assert_difference "UserRole.count", 0 do
post :grant, :display_name => "non_existent_user", :role => role
end
assert_response :not_found
assert_template "user/no_such_user"
assert_select "h1", "The user non_existent_user does not exist"
# Granting a role from a user that already has it should fail
assert_no_difference "UserRole.count" do
post :grant, :display_name => users(:super_user).display_name, :role => role
end
assert_redirected_to user_path(users(:super_user).display_name)
assert_equal "The user already has role #{role}.", flash[:error]
# Granting a role to a user that doesn't have it should work...
assert_difference "UserRole.count", 1 do
post :grant, :display_name => users(:normal_user).display_name, :role => role
end
assert_redirected_to user_path(users(:normal_user).display_name)
# ...but trying a second time should fail
assert_no_difference "UserRole.count" do
post :grant, :display_name => users(:normal_user).display_name, :role => role
end
assert_redirected_to user_path(users(:normal_user).display_name)
assert_equal "The user already has role #{role}.", flash[:error]
end
# Granting a non-existent role should fail
assert_difference "UserRole.count", 0 do
post :grant, :display_name => users(:normal_user).display_name, :role => "no_such_role"
end
assert_redirected_to user_path(users(:normal_user).display_name)
assert_equal "The string `no_such_role' is not a valid role.", flash[:error]
end
##
# test the revoke action
def test_revoke
# Revoking should fail when not logged in
post :revoke, :display_name => users(:normal_user).display_name, :role => "moderator"
assert_response :forbidden
# Login as an unprivileged user
session[:user] = users(:public_user).id
# Revoking should still fail
post :revoke, :display_name => users(:normal_user).display_name, :role => "moderator"
assert_redirected_to user_path(users(:normal_user).display_name)
assert_equal "Only administrators can perform user role management, and you are not an administrator.", flash[:error]
# Login as an administrator
session[:user] = users(:administrator_user).id
UserRole::ALL_ROLES.each do |role|
# Removing a role from a non-existent user should fail
assert_difference "UserRole.count", 0 do
post :revoke, :display_name => "non_existent_user", :role => role
end
assert_response :not_found
assert_template "user/no_such_user"
assert_select "h1", "The user non_existent_user does not exist"
# Removing a role from a user that doesn't have it should fail
assert_no_difference "UserRole.count" do
post :revoke, :display_name => users(:normal_user).display_name, :role => role
end
assert_redirected_to user_path(users(:normal_user).display_name)
assert_equal "The user does not have role #{role}.", flash[:error]
# Removing a role' from a user that has it should work...
assert_difference "UserRole.count", -1 do
post :revoke, :display_name => users(:super_user).display_name, :role => role
end
assert_redirected_to user_path(users(:super_user).display_name)
# ...but trying a second time should fail
assert_no_difference "UserRole.count" do
post :revoke, :display_name => users(:super_user).display_name, :role => role
end
assert_redirected_to user_path(users(:super_user).display_name)
assert_equal "The user does not have role #{role}.", flash[:error]
end
# Revoking a non-existent role should fail
assert_difference "UserRole.count", 0 do
post :revoke, :display_name => users(:normal_user).display_name, :role => "no_such_role"
end
assert_redirected_to user_path(users(:normal_user).display_name)
assert_equal "The string `no_such_role' is not a valid role.", flash[:error]
end
end

View file

@ -0,0 +1,536 @@
require 'test_helper'
require 'way_controller'
class WayControllerTest < ActionController::TestCase
api_fixtures
##
# test all routes which lead to this controller
def test_routes
assert_routing(
{ :path => "/api/0.6/way/create", :method => :put },
{ :controller => "way", :action => "create" }
)
assert_routing(
{ :path => "/api/0.6/way/1/full", :method => :get },
{ :controller => "way", :action => "full", :id => "1" }
)
assert_routing(
{ :path => "/api/0.6/way/1", :method => :get },
{ :controller => "way", :action => "read", :id => "1" }
)
assert_routing(
{ :path => "/api/0.6/way/1", :method => :put },
{ :controller => "way", :action => "update", :id => "1" }
)
assert_routing(
{ :path => "/api/0.6/way/1", :method => :delete },
{ :controller => "way", :action => "delete", :id => "1" }
)
assert_routing(
{ :path => "/api/0.6/ways", :method => :get },
{ :controller => "way", :action => "ways" }
)
end
# -------------------------------------
# Test reading ways.
# -------------------------------------
def test_read
# check that a visible way is returned properly
get :read, :id => current_ways(:visible_way).id
assert_response :success
# check that an invisible way is not returned
get :read, :id => current_ways(:invisible_way).id
assert_response :gone
# check chat a non-existent way is not returned
get :read, :id => 0
assert_response :not_found
end
##
# check the "full" mode
def test_full
Way.all.each do |way|
get :full, :id => way.id
# full call should say "gone" for non-visible ways...
unless way.visible
assert_response :gone
next
end
# otherwise it should say success
assert_response :success
# Check the way is correctly returned
assert_select "osm way[id=#{way.id}][version=#{way.version}][visible=#{way.visible}]", 1
# check that each node in the way appears once in the output as a
# reference and as the node element.
way.nodes.each do |n|
count = (way.nodes - (way.nodes - [n])).length
assert_select "osm way nd[ref=#{n.id}]", count
assert_select "osm node[id=#{n.id}][version=#{n.version}][lat=#{n.lat}][lon=#{n.lon}]", 1
end
end
end
##
# test fetching multiple ways
def test_ways
# check error when no parameter provided
get :ways
assert_response :bad_request
# check error when no parameter value provided
get :ways, :ways => ""
assert_response :bad_request
# test a working call
get :ways, :ways => "1,2,4,6"
assert_response :success
assert_select "osm" do
assert_select "way", :count => 4
assert_select "way[id=1][visible=true]", :count => 1
assert_select "way[id=2][visible=false]", :count => 1
assert_select "way[id=4][visible=true]", :count => 1
assert_select "way[id=6][visible=true]", :count => 1
end
# check error when a non-existent way is included
get :ways, :ways => "1,2,4,6,400"
assert_response :not_found
end
# -------------------------------------
# Test simple way creation.
# -------------------------------------
def test_create
## First check that it fails when creating a way using a non-public user
nid1 = current_nodes(:used_node_1).id
nid2 = current_nodes(:used_node_2).id
basic_authorization users(:normal_user).email, "test"
# use the first user's open changeset
changeset_id = changesets(:normal_user_first_change).id
# create a way with pre-existing nodes
content "<osm><way changeset='#{changeset_id}'>" +
"<nd ref='#{nid1}'/><nd ref='#{nid2}'/>" +
"<tag k='test' v='yes' /></way></osm>"
put :create
# hope for success
assert_response :forbidden,
"way upload did not return success status"
# read id of created way and search for it
wayid = @response.body
## Now use a public user
nid1 = current_nodes(:used_node_1).id
nid2 = current_nodes(:used_node_2).id
basic_authorization users(:public_user).email, "test"
# use the first user's open changeset
changeset_id = changesets(:public_user_first_change).id
# create a way with pre-existing nodes
content "<osm><way changeset='#{changeset_id}'>" +
"<nd ref='#{nid1}'/><nd ref='#{nid2}'/>" +
"<tag k='test' v='yes' /></way></osm>"
put :create
# hope for success
assert_response :success,
"way upload did not return success status"
# read id of created way and search for it
wayid = @response.body
checkway = Way.find(wayid)
assert_not_nil checkway,
"uploaded way not found in data base after upload"
# compare values
assert_equal checkway.nds.length, 2,
"saved way does not contain exactly one node"
assert_equal checkway.nds[0], nid1,
"saved way does not contain the right node on pos 0"
assert_equal checkway.nds[1], nid2,
"saved way does not contain the right node on pos 1"
assert_equal checkway.changeset_id, changeset_id,
"saved way does not belong to the correct changeset"
assert_equal users(:public_user).id, checkway.changeset.user_id,
"saved way does not belong to user that created it"
assert_equal true, checkway.visible,
"saved way is not visible"
end
# -------------------------------------
# Test creating some invalid ways.
# -------------------------------------
def test_create_invalid
## First test with a private user to make sure that they are not authorized
basic_authorization users(:normal_user).email, "test"
# use the first user's open changeset
open_changeset_id = changesets(:normal_user_first_change).id
closed_changeset_id = changesets(:normal_user_closed_change).id
nid1 = current_nodes(:used_node_1).id
# create a way with non-existing node
content "<osm><way changeset='#{open_changeset_id}'>" +
"<nd ref='0'/><tag k='test' v='yes' /></way></osm>"
put :create
# expect failure
assert_response :forbidden,
"way upload with invalid node using a private user did not return 'forbidden'"
# create a way with no nodes
content "<osm><way changeset='#{open_changeset_id}'>" +
"<tag k='test' v='yes' /></way></osm>"
put :create
# expect failure
assert_response :forbidden,
"way upload with no node using a private userdid not return 'forbidden'"
# create a way inside a closed changeset
content "<osm><way changeset='#{closed_changeset_id}'>" +
"<nd ref='#{nid1}'/></way></osm>"
put :create
# expect failure
assert_response :forbidden,
"way upload to closed changeset with a private user did not return 'forbidden'"
## Now test with a public user
basic_authorization users(:public_user).email, "test"
# use the first user's open changeset
open_changeset_id = changesets(:public_user_first_change).id
closed_changeset_id = changesets(:public_user_closed_change).id
nid1 = current_nodes(:used_node_1).id
# create a way with non-existing node
content "<osm><way changeset='#{open_changeset_id}'>" +
"<nd ref='0'/><tag k='test' v='yes' /></way></osm>"
put :create
# expect failure
assert_response :precondition_failed,
"way upload with invalid node did not return 'precondition failed'"
assert_equal "Precondition failed: Way requires the nodes with id in (0), which either do not exist, or are not visible.", @response.body
# create a way with no nodes
content "<osm><way changeset='#{open_changeset_id}'>" +
"<tag k='test' v='yes' /></way></osm>"
put :create
# expect failure
assert_response :precondition_failed,
"way upload with no node did not return 'precondition failed'"
assert_equal "Precondition failed: Cannot create way: data is invalid.", @response.body
# create a way inside a closed changeset
content "<osm><way changeset='#{closed_changeset_id}'>" +
"<nd ref='#{nid1}'/></way></osm>"
put :create
# expect failure
assert_response :conflict,
"way upload to closed changeset did not return 'conflict'"
# create a way with a tag which is too long
content "<osm><way changeset='#{open_changeset_id}'>" +
"<nd ref='#{nid1}'/>" +
"<tag k='foo' v='#{'x'*256}'/>" +
"</way></osm>"
put :create
# expect failure
assert_response :bad_request,
"way upload to with too long tag did not return 'bad_request'"
end
# -------------------------------------
# Test deleting ways.
# -------------------------------------
def test_delete
# first try to delete way without auth
delete :delete, :id => current_ways(:visible_way).id
assert_response :unauthorized
# now set auth using the private user
basic_authorization(users(:normal_user).email, "test");
# this shouldn't work as with the 0.6 api we need pay load to delete
delete :delete, :id => current_ways(:visible_way).id
assert_response :forbidden
# Now try without having a changeset
content "<osm><way id='#{current_ways(:visible_way).id}'/></osm>"
delete :delete, :id => current_ways(:visible_way).id
assert_response :forbidden
# try to delete with an invalid (closed) changeset
content update_changeset(current_ways(:visible_way).to_xml,
changesets(:normal_user_closed_change).id)
delete :delete, :id => current_ways(:visible_way).id
assert_response :forbidden
# try to delete with an invalid (non-existent) changeset
content update_changeset(current_ways(:visible_way).to_xml,0)
delete :delete, :id => current_ways(:visible_way).id
assert_response :forbidden
# Now try with a valid changeset
content current_ways(:visible_way).to_xml
delete :delete, :id => current_ways(:visible_way).id
assert_response :forbidden
# check the returned value - should be the new version number
# valid delete should return the new version number, which should
# be greater than the old version number
#assert @response.body.to_i > current_ways(:visible_way).version,
# "delete request should return a new version number for way"
# this won't work since the way is already deleted
content current_ways(:invisible_way).to_xml
delete :delete, :id => current_ways(:invisible_way).id
assert_response :forbidden
# this shouldn't work as the way is used in a relation
content current_ways(:used_way).to_xml
delete :delete, :id => current_ways(:used_way).id
assert_response :forbidden,
"shouldn't be able to delete a way used in a relation (#{@response.body}), when done by a private user"
# this won't work since the way never existed
delete :delete, :id => 0
assert_response :forbidden
### Now check with a public user
# now set auth
basic_authorization(users(:public_user).email, "test");
# this shouldn't work as with the 0.6 api we need pay load to delete
delete :delete, :id => current_ways(:visible_way).id
assert_response :bad_request
# Now try without having a changeset
content "<osm><way id='#{current_ways(:visible_way).id}'/></osm>"
delete :delete, :id => current_ways(:visible_way).id
assert_response :bad_request
# try to delete with an invalid (closed) changeset
content update_changeset(current_ways(:visible_way).to_xml,
changesets(:public_user_closed_change).id)
delete :delete, :id => current_ways(:visible_way).id
assert_response :conflict
# try to delete with an invalid (non-existent) changeset
content update_changeset(current_ways(:visible_way).to_xml,0)
delete :delete, :id => current_ways(:visible_way).id
assert_response :conflict
# Now try with a valid changeset
content current_ways(:visible_way).to_xml
delete :delete, :id => current_ways(:visible_way).id
assert_response :success
# check the returned value - should be the new version number
# valid delete should return the new version number, which should
# be greater than the old version number
assert @response.body.to_i > current_ways(:visible_way).version,
"delete request should return a new version number for way"
# this won't work since the way is already deleted
content current_ways(:invisible_way).to_xml
delete :delete, :id => current_ways(:invisible_way).id
assert_response :gone
# this shouldn't work as the way is used in a relation
content current_ways(:used_way).to_xml
delete :delete, :id => current_ways(:used_way).id
assert_response :precondition_failed,
"shouldn't be able to delete a way used in a relation (#{@response.body})"
assert_equal "Precondition failed: Way 3 is still used by relations 1.", @response.body
# this won't work since the way never existed
delete :delete, :id => 0
assert_response :not_found
end
# ------------------------------------------------------------
# test tags handling
# ------------------------------------------------------------
##
# Try adding a duplicate of an existing tag to a way
def test_add_duplicate_tags
## Try with the non-public user
# setup auth
basic_authorization(users(:normal_user).email, "test")
# add an identical tag to the way
tag_xml = XML::Node.new("tag")
tag_xml['k'] = current_way_tags(:t1).k
tag_xml['v'] = current_way_tags(:t1).v
# add the tag into the existing xml
way_xml = current_ways(:visible_way).to_xml
way_xml.find("//osm/way").first << tag_xml
# try and upload it
content way_xml
put :update, :id => current_ways(:visible_way).id
assert_response :forbidden,
"adding a duplicate tag to a way for a non-public should fail with 'forbidden'"
## Now try with the public user
# setup auth
basic_authorization(users(:public_user).email, "test")
# add an identical tag to the way
tag_xml = XML::Node.new("tag")
tag_xml['k'] = current_way_tags(:t1).k
tag_xml['v'] = current_way_tags(:t1).v
# add the tag into the existing xml
way_xml = current_ways(:visible_way).to_xml
way_xml.find("//osm/way").first << tag_xml
# try and upload it
content way_xml
put :update, :id => current_ways(:visible_way).id
assert_response :bad_request,
"adding a duplicate tag to a way should fail with 'bad request'"
assert_equal "Element way/#{current_ways(:visible_way).id} has duplicate tags with key #{current_way_tags(:t1).k}", @response.body
end
##
# Try adding a new duplicate tags to a way
def test_new_duplicate_tags
## First test with the non-public user so should be rejected
# setup auth
basic_authorization(users(:normal_user).email, "test")
# create duplicate tag
tag_xml = XML::Node.new("tag")
tag_xml['k'] = "i_am_a_duplicate"
tag_xml['v'] = "foobar"
# add the tag into the existing xml
way_xml = current_ways(:visible_way).to_xml
# add two copies of the tag
way_xml.find("//osm/way").first << tag_xml.copy(true) << tag_xml
# try and upload it
content way_xml
put :update, :id => current_ways(:visible_way).id
assert_response :forbidden,
"adding new duplicate tags to a way using a non-public user should fail with 'forbidden'"
## Now test with the public user
# setup auth
basic_authorization(users(:public_user).email, "test")
# create duplicate tag
tag_xml = XML::Node.new("tag")
tag_xml['k'] = "i_am_a_duplicate"
tag_xml['v'] = "foobar"
# add the tag into the existing xml
way_xml = current_ways(:visible_way).to_xml
# add two copies of the tag
way_xml.find("//osm/way").first << tag_xml.copy(true) << tag_xml
# try and upload it
content way_xml
put :update, :id => current_ways(:visible_way).id
assert_response :bad_request,
"adding new duplicate tags to a way should fail with 'bad request'"
assert_equal "Element way/#{current_ways(:visible_way).id} has duplicate tags with key i_am_a_duplicate", @response.body
end
##
# Try adding a new duplicate tags to a way.
# But be a bit subtle - use unicode decoding ambiguities to use different
# binary strings which have the same decoding.
def test_invalid_duplicate_tags
## First make sure that you can't with a non-public user
# setup auth
basic_authorization(users(:normal_user).email, "test")
# add the tag into the existing xml
way_str = "<osm><way changeset='1'>"
way_str << "<tag k='addr:housenumber' v='1'/>"
way_str << "<tag k='addr:housenumber' v='2'/>"
way_str << "</way></osm>";
# try and upload it
content way_str
put :create
assert_response :forbidden,
"adding new duplicate tags to a way with a non-public user should fail with 'forbidden'"
## Now do it with a public user
# setup auth
basic_authorization(users(:public_user).email, "test")
# add the tag into the existing xml
way_str = "<osm><way changeset='1'>"
way_str << "<tag k='addr:housenumber' v='1'/>"
way_str << "<tag k='addr:housenumber' v='2'/>"
way_str << "</way></osm>";
# try and upload it
content way_str
put :create
assert_response :bad_request,
"adding new duplicate tags to a way should fail with 'bad request'"
assert_equal "Element way/ has duplicate tags with key addr:housenumber", @response.body
end
##
# test that a call to ways_for_node returns all ways that contain the node
# and none that don't.
def test_ways_for_node
# in current fixtures ways 1 and 3 all use node 3. ways 2 and 4
# *used* to use it but doesn't.
get :ways_for_node, :id => current_nodes(:used_node_1).id
assert_response :success
ways_xml = XML::Parser.string(@response.body).parse
assert_not_nil ways_xml, "failed to parse ways_for_node response"
# check that the set of IDs match expectations
expected_way_ids = [ current_ways(:visible_way).id,
current_ways(:used_way).id
]
found_way_ids = ways_xml.find("//osm/way").collect { |w| w["id"].to_i }
assert_equal expected_way_ids.sort, found_way_ids.sort,
"expected ways for node #{current_nodes(:used_node_1).id} did not match found"
# check the full ways to ensure we're not missing anything
expected_way_ids.each do |id|
way_xml = ways_xml.find("//osm/way[@id=#{id}]").first
assert_ways_are_equal(Way.find(id),
Way.from_xml_node(way_xml))
end
end
##
# update the changeset_id of a node element
def update_changeset(xml, changeset_id)
xml_attr_rewrite(xml, 'changeset', changeset_id)
end
##
# update an attribute in the node element
def xml_attr_rewrite(xml, name, value)
xml.find("//osm/way").first[name] = value.to_s
return xml
end
end