]> git.openstreetmap.org Git - rails.git/commitdiff
Merge remote-tracking branch 'upstream/pull/5597'
authorTom Hughes <tom@compton.nu>
Wed, 5 Feb 2025 19:09:37 +0000 (19:09 +0000)
committerTom Hughes <tom@compton.nu>
Wed, 5 Feb 2025 19:09:37 +0000 (19:09 +0000)
21 files changed:
app/abilities/api_ability.rb
app/assets/javascripts/index.js
app/assets/javascripts/index/history.js
app/assets/javascripts/index/layers/notes.js
app/assets/javascripts/index/query.js
app/assets/javascripts/leaflet.layers.js
app/assets/javascripts/leaflet.share.js
app/assets/javascripts/router.js
app/controllers/api/relations_controller.rb
app/controllers/api/ways_controller.rb
app/views/api/relations/full.json.jbuilder [deleted file]
app/views/api/relations/full.xml.builder [deleted file]
app/views/api/relations/show.json.jbuilder
app/views/api/relations/show.xml.builder
app/views/api/ways/full.json.jbuilder [deleted file]
app/views/api/ways/full.xml.builder [deleted file]
app/views/api/ways/show.json.jbuilder
app/views/api/ways/show.xml.builder
config/routes.rb
test/controllers/api/relations_controller_test.rb
test/controllers/api/ways_controller_test.rb

index c74a4d0996adedcebd66ec59d47d696b01ddd28c..97b461b1f602282669b706f1ef4421d5e5f8b96e 100644 (file)
@@ -16,8 +16,8 @@ class ApiAbility
       can :read, Tracepoint
       can :read, User
       can :read, Node
-      can [:read, :full, :ways_for_node], Way
-      can [:read, :full, :relations_for_node, :relations_for_way, :relations_for_relation], Relation
+      can [:read, :ways_for_node], Way
+      can [:read, :relations_for_node, :relations_for_way, :relations_for_relation], Relation
       can [:history, :read], [OldNode, OldWay, OldRelation]
       can :read, UserBlock
 
index ad34479d32f93b46a739e898f081e7c3cffc65ed..8ef067740d6025bc6ad0f0f988d69cfcb18f3baa 100644 (file)
@@ -97,9 +97,7 @@ $(document).ready(function () {
   var position = $("html").attr("dir") === "rtl" ? "topleft" : "topright";
 
   function addControlGroup(controls) {
-    controls.forEach(function (control) {
-      control.addTo(map);
-    });
+    for (const control of controls) control.addTo(map);
 
     var firstContainer = controls[0].getContainer();
     $(firstContainer).find(".control-button").first()
index ae8f027ed8727586f2b48d317f473f6fc8f1fe67..3c7101c7408095d3f45be0f6e0fa263cadfb39ba 100644 (file)
@@ -96,7 +96,7 @@ OSM.History = function (map) {
   function updateBounds() {
     group.clearLayers();
 
-    changesets.forEach(function (changeset) {
+    for (const changeset of changesets) {
       var bottomLeft = map.project(L.latLng(changeset.bbox.minlat, changeset.bbox.minlon)),
           topRight = map.project(L.latLng(changeset.bbox.maxlat, changeset.bbox.maxlon)),
           width = topRight.x - bottomLeft.x,
@@ -115,16 +115,15 @@ OSM.History = function (map) {
 
       changeset.bounds = L.latLngBounds(map.unproject(bottomLeft),
                                         map.unproject(topRight));
-    });
+    }
 
     changesets.sort(function (a, b) {
       return b.bounds.getSize() - a.bounds.getSize();
     });
 
-    for (var i = 0; i < changesets.length; ++i) {
-      var changeset = changesets[i],
-          rect = L.rectangle(changeset.bounds,
-                             { weight: 2, color: "#FF9500", opacity: 1, fillColor: "#FFFFAF", fillOpacity: 0 });
+    for (const changeset of changesets) {
+      const rect = L.rectangle(changeset.bounds,
+                               { weight: 2, color: "#FF9500", opacity: 1, fillColor: "#FFFFAF", fillOpacity: 0 });
       rect.id = changeset.id;
       rect.addTo(group);
     }
index 24bf969b3380581e9e3b07f35873b36a9fe6a170..1bc3714f0472af0e9c9bd43c5621dd6750b7ebdc 100644 (file)
@@ -84,9 +84,7 @@ OSM.initializeNotesLayer = function (map) {
     function success(json) {
       var oldNotes = notes;
       notes = {};
-      json.features.forEach(updateMarkers);
-
-      function updateMarkers(feature) {
+      for (const feature of json.features) {
         var marker = oldNotes[feature.properties.id];
         delete oldNotes[feature.properties.id];
         notes[feature.properties.id] = updateMarker(marker, feature);
index 3874dbdbb3ca5931068c6fb96a1b29c0f9f6e077..5c8ee88760ceb549adb01ed81efdfb2797bae47d 100644 (file)
@@ -109,9 +109,9 @@ OSM.Query = function (map) {
     var tags = feature.tags,
         locales = OSM.preferred_languages;
 
-    for (var i = 0; i < locales.length; i++) {
-      if (tags["name:" + locales[i]]) {
-        return tags["name:" + locales[i]];
+    for (const locale of locales) {
+      if (tags["name:" + locale]) {
+        return tags["name:" + locale];
       }
     }
 
@@ -193,22 +193,20 @@ OSM.Query = function (map) {
           elements = elements.sort(compare);
         }
 
-        for (var i = 0; i < elements.length; i++) {
-          var element = elements[i];
-
-          if (interestingFeature(element)) {
-            var $li = $("<li>")
-              .addClass("list-group-item list-group-item-action")
-              .text(featurePrefix(element) + " ")
-              .appendTo($ul);
-
-            $("<a>")
-              .addClass("stretched-link")
-              .attr("href", "/" + element.type + "/" + element.id)
-              .data("geometry", featureGeometry(element))
-              .text(featureName(element))
-              .appendTo($li);
-          }
+        for (const element of elements) {
+          if (!interestingFeature(element)) continue;
+
+          var $li = $("<li>")
+            .addClass("list-group-item list-group-item-action")
+            .text(featurePrefix(element) + " ")
+            .appendTo($ul);
+
+          $("<a>")
+            .addClass("stretched-link")
+            .attr("href", "/" + element.type + "/" + element.id)
+            .data("geometry", featureGeometry(element))
+            .text(featureName(element))
+            .appendTo($li);
         }
 
         if (results.remark) {
index 3f577b532d3ba707dbf487277ce17d2bb1592883..a7a2335f3d843fedff03c1816aea7cc00184dd23 100644 (file)
@@ -60,11 +60,11 @@ L.OSM.layers = function (options) {
       });
 
       input.on("click", function () {
-        layers.forEach(function (other) {
+        for (const other of layers) {
           if (other !== layer) {
             map.removeLayer(other);
           }
-        });
+        }
         map.addLayer(layer);
       });
 
index 1eed2151a9ed3a9adb7d4fa7e63dc63f1458a04d..7d8462f4614662c20900595ff23f891ec7b008da 100644 (file)
@@ -201,41 +201,31 @@ L.OSM.share = function (options) {
             .attr("class", "form-check-input")
             .bind("change", toggleFilter))));
 
-    ["minlon", "minlat", "maxlon", "maxlat", "lat", "lon"].forEach(function (name) {
+    const mapnikNames = ["minlon", "minlat", "maxlon", "maxlat", "lat", "lon"];
+
+    for (const name of mapnikNames) {
       $("<input>")
         .attr("id", "mapnik_" + name)
         .attr("name", name)
         .attr("type", "hidden")
         .appendTo($form);
-    });
-
-    $("<input>")
-      .attr("id", "map_format")
-      .attr("name", "format")
-      .attr("value", "mapnik")
-      .attr("type", "hidden")
-      .appendTo($form);
-
-    $("<input>")
-      .attr("id", "map_zoom")
-      .attr("name", "zoom")
-      .attr("value", map.getZoom())
-      .attr("type", "hidden")
-      .appendTo($form);
+    }
 
-    $("<input>")
-      .attr("id", "map_width")
-      .attr("name", "width")
-      .attr("value", 0)
-      .attr("type", "hidden")
-      .appendTo($form);
+    const hiddenExportDefaults = {
+      format: "mapnik",
+      zoom: map.getZoom(),
+      width: 0,
+      height: 0
+    };
 
-    $("<input>")
-      .attr("id", "map_height")
-      .attr("name", "height")
-      .attr("value", 0)
-      .attr("type", "hidden")
-      .appendTo($form);
+    for (const name in hiddenExportDefaults) {
+      $("<input>")
+        .attr("id", "map_" + name)
+        .attr("name", name)
+        .attr("value", hiddenExportDefaults[name])
+        .attr("type", "hidden")
+        .appendTo($form);
+    }
 
     var csrf_param = $("meta[name=csrf-param]").attr("content"),
         csrf_token = $("meta[name=csrf-token]").attr("content");
index a8659d308762024606b7f1aa0df85398839326a6..30a71e0f179d6dd1bd3fc0c0f228ab675573cce6 100644 (file)
@@ -84,14 +84,12 @@ OSM.Router = function (map, rts) {
     return route;
   }
 
-  var routes = [];
-  for (var r in rts) {
-    routes.push(new Route(r, rts[r]));
-  }
+  const routes = Object.entries(rts)
+    .map(([r, t]) => new Route(r, t));
 
   routes.recognize = function (path) {
-    for (var i = 0; i < this.length; i++) {
-      if (this[i].match(path)) return this[i];
+    for (const route of this) {
+      if (route.match(path)) return route;
     }
   };
 
index f712534f001aebdb747234abf27d1f68a87ce982..006b3e8a624f88d9536e500d7f034c3bf6cb6cf8 100644 (file)
@@ -26,9 +26,64 @@ module Api
     end
 
     def show
-      @relation = Relation.find(params[:id])
-      response.last_modified = @relation.timestamp
-      if @relation.visible
+      relation = Relation.find(params[:id])
+
+      response.last_modified = relation.timestamp unless params[:full]
+
+      @nodes = []
+      @ways = []
+      @relations = []
+
+      if relation.visible
+        if params[:full]
+          # with parameter :full
+          # returns representation of one relation object plus all its
+          # members, plus all nodes part of member ways
+
+          # first find the ids of nodes, ways and relations referenced by this
+          # relation - note that we exclude this relation just in case.
+
+          node_ids = relation.members.select { |m| m[0] == "Node" }.pluck(1)
+          way_ids = relation.members.select { |m| m[0] == "Way" }.pluck(1)
+          relation_ids = relation.members.select { |m| m[0] == "Relation" && m[1] != relation.id }.pluck(1)
+
+          # next load the relations and the ways.
+
+          relations = Relation.where(:id => relation_ids).includes(:relation_tags)
+          ways = Way.where(:id => way_ids).includes(:way_nodes, :way_tags)
+
+          # now additionally collect nodes referenced by ways. Note how we
+          # recursively evaluate ways but NOT relations.
+
+          way_node_ids = ways.collect do |way|
+            way.way_nodes.collect(&:node_id)
+          end
+          node_ids += way_node_ids.flatten
+          nodes = Node.where(:id => node_ids.uniq).includes(:node_tags)
+
+          @nodes = []
+          nodes.each do |node|
+            next unless node.visible? # should be unnecessary if data is consistent.
+
+            @nodes << node
+          end
+
+          ways.each do |way|
+            next unless way.visible? # should be unnecessary if data is consistent.
+
+            @ways << way
+          end
+
+          relations.each do |rel|
+            next unless rel.visible? # should be unnecessary if data is consistent.
+
+            @relations << rel
+          end
+        end
+
+        # finally add self
+        @relations << relation
+
         # Render the result
         respond_to do |format|
           format.xml
@@ -68,74 +123,6 @@ module Api
       end
     end
 
-    # -----------------------------------------------------------------
-    # full
-    #
-    # input parameters: id
-    #
-    # returns XML representation of one relation object plus all its
-    # members, plus all nodes part of member ways
-    # -----------------------------------------------------------------
-    def full
-      relation = Relation.find(params[:id])
-
-      if relation.visible
-
-        # first find the ids of nodes, ways and relations referenced by this
-        # relation - note that we exclude this relation just in case.
-
-        node_ids = relation.members.select { |m| m[0] == "Node" }.pluck(1)
-        way_ids = relation.members.select { |m| m[0] == "Way" }.pluck(1)
-        relation_ids = relation.members.select { |m| m[0] == "Relation" && m[1] != relation.id }.pluck(1)
-
-        # next load the relations and the ways.
-
-        relations = Relation.where(:id => relation_ids).includes(:relation_tags)
-        ways = Way.where(:id => way_ids).includes(:way_nodes, :way_tags)
-
-        # now additionally collect nodes referenced by ways. Note how we
-        # recursively evaluate ways but NOT relations.
-
-        way_node_ids = ways.collect do |way|
-          way.way_nodes.collect(&:node_id)
-        end
-        node_ids += way_node_ids.flatten
-        nodes = Node.where(:id => node_ids.uniq).includes(:node_tags)
-
-        @nodes = []
-        nodes.each do |node|
-          next unless node.visible? # should be unnecessary if data is consistent.
-
-          @nodes << node
-        end
-
-        @ways = []
-        ways.each do |way|
-          next unless way.visible? # should be unnecessary if data is consistent.
-
-          @ways << way
-        end
-
-        @relations = []
-        relations.each do |rel|
-          next unless rel.visible? # should be unnecessary if data is consistent.
-
-          @relations << rel
-        end
-
-        # finally add self
-        @relations << relation
-
-        # Render the result
-        respond_to do |format|
-          format.xml
-          format.json
-        end
-      else
-        head :gone
-      end
-    end
-
     def relations_for_way
       relations_for_object("Way")
     end
index 285ed46046041af296b1dc223e9320293fcd14d5..b1bc8d799b0747c3f35dc3b36bdadcadd21f26e7 100644 (file)
@@ -26,12 +26,21 @@ module Api
     end
 
     def show
-      @way = Way.find(params[:id])
+      @way = Way
+      @way = @way.includes(:nodes => :node_tags) if params[:full]
+      @way = @way.find(params[:id])
 
-      response.last_modified = @way.timestamp
+      response.last_modified = @way.timestamp unless params[:full]
 
       if @way.visible
-        # Render the result
+        if params[:full]
+          @nodes = []
+
+          @way.nodes.uniq.each do |node|
+            @nodes << node if node.visible
+          end
+        end
+
         respond_to do |format|
           format.xml
           format.json
@@ -72,26 +81,6 @@ module Api
       end
     end
 
-    def full
-      @way = Way.includes(:nodes => :node_tags).find(params[:id])
-
-      if @way.visible
-        @nodes = []
-
-        @way.nodes.uniq.each do |node|
-          @nodes << node if node.visible
-        end
-
-        # Render the result
-        respond_to do |format|
-          format.xml
-          format.json
-        end
-      else
-        head :gone
-      end
-    end
-
     ##
     # returns all the ways which are currently using the node given in the
     # :id parameter. note that this used to return deleted ways as well, but
diff --git a/app/views/api/relations/full.json.jbuilder b/app/views/api/relations/full.json.jbuilder
deleted file mode 100644 (file)
index 16331a8..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-json.partial! "api/root_attributes"
-
-json.elements do
-  json.array! @nodes, :partial => "/api/nodes/node", :as => :node
-  json.array! @ways, :partial => "/api/ways/way", :as => :way
-  json.array! @relations, :partial => "/api/relations/relation", :as => :relation
-end
diff --git a/app/views/api/relations/full.xml.builder b/app/views/api/relations/full.xml.builder
deleted file mode 100644 (file)
index e230617..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-xml.instruct!
-
-xml.osm(OSM::API.new.xml_root_attributes) do |osm|
-  osm << (render(@nodes) || "")
-  osm << (render(@ways) || "")
-  osm << (render(@relations) || "")
-end
index e5da7cd3f48fa4553f70a2b2adb6cdf2c2d41214..16331a89e6fd9aac3226a8b273877cb5fbea78b0 100644 (file)
@@ -1,5 +1,7 @@
 json.partial! "api/root_attributes"
 
 json.elements do
-  json.array! [@relation], :partial => "relation", :as => :relation
+  json.array! @nodes, :partial => "/api/nodes/node", :as => :node
+  json.array! @ways, :partial => "/api/ways/way", :as => :way
+  json.array! @relations, :partial => "/api/relations/relation", :as => :relation
 end
index 555eb4db5f73d5a53bcd41b9222bac4f758e6003..e23061727c4c1d2756d5a5a3e4cd08836a3ea71e 100644 (file)
@@ -1,5 +1,7 @@
 xml.instruct!
 
 xml.osm(OSM::API.new.xml_root_attributes) do |osm|
-  osm << (render(@relation) || "")
+  osm << (render(@nodes) || "")
+  osm << (render(@ways) || "")
+  osm << (render(@relations) || "")
 end
diff --git a/app/views/api/ways/full.json.jbuilder b/app/views/api/ways/full.json.jbuilder
deleted file mode 100644 (file)
index 1bd127d..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-json.partial! "api/root_attributes"
-
-json.elements do
-  json.array! @nodes, :partial => "/api/nodes/node", :as => :node
-  json.array! [@way], :partial => "/api/ways/way", :as => :way
-end
diff --git a/app/views/api/ways/full.xml.builder b/app/views/api/ways/full.xml.builder
deleted file mode 100644 (file)
index 0252916..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-xml.instruct!
-
-xml.osm(OSM::API.new.xml_root_attributes) do |osm|
-  osm << (render(@nodes) || "")
-  osm << (render(@way) || "")
-end
index 92e570d869f300204bb8d92eb9a20190b242f4de..adf8beab2d3d1b2196a6281a6b68f0ed9a4a2ab5 100644 (file)
@@ -1,5 +1,6 @@
 json.partial! "api/root_attributes"
 
 json.elements do
+  json.array! @nodes, :partial => "/api/nodes/node", :as => :node if @nodes
   json.array! [@way], :partial => "way", :as => :way
 end
index d520a08444376f96f25a5eb93099fb43e70bd526..72b22e7374c97a6b56e06a7228085e5ec95c29ff 100644 (file)
@@ -1,5 +1,6 @@
 xml.instruct!
 
 xml.osm(OSM::API.new.xml_root_attributes) do |osm|
+  osm << (render(@nodes) || "") if @nodes
   osm << (render(@way) || "")
 end
index b562ca9f4a0c60b6d1984b5db21acf80aec0153a..bc06e5f38e123a787de5084a818e1714e79eabb3 100644 (file)
@@ -37,14 +37,12 @@ OpenStreetMap::Application.routes.draw do
     get "node/:id/:version" => "old_nodes#show", :as => :api_old_node, :id => /\d+/, :version => /\d+/
 
     get "way/:id/history" => "old_ways#history", :as => :api_way_history, :id => /\d+/
-    get "way/:id/full" => "ways#full", :as => :way_full, :id => /\d+/
     get "way/:id/relations" => "relations#relations_for_way", :as => :way_relations, :id => /\d+/
     post "way/:id/:version/redact" => "old_ways#redact", :as => :way_version_redact, :version => /\d+/, :id => /\d+/
     get "way/:id/:version" => "old_ways#show", :as => :api_old_way, :id => /\d+/, :version => /\d+/
 
     get "relation/:id/relations" => "relations#relations_for_relation", :as => :relation_relations, :id => /\d+/
     get "relation/:id/history" => "old_relations#history", :as => :api_relation_history, :id => /\d+/
-    get "relation/:id/full" => "relations#full", :as => :relation_full, :id => /\d+/
     post "relation/:id/:version/redact" => "old_relations#redact", :as => :relation_version_redact, :version => /\d+/, :id => /\d+/
     get "relation/:id/:version" => "old_relations#show", :as => :api_old_relation, :id => /\d+/, :version => /\d+/
   end
@@ -55,11 +53,19 @@ OpenStreetMap::Application.routes.draw do
     put "node/create" => "nodes#create", :as => nil
 
     resources :ways, :only => [:index, :create]
-    resources :ways, :path => "way", :id => /\d+/, :only => [:show, :update, :destroy]
+    resources :ways, :path => "way", :id => /\d+/, :only => [:show, :update, :destroy] do
+      member do
+        get :full, :action => :show, :full => true, :as => nil
+      end
+    end
     put "way/create" => "ways#create", :as => nil
 
     resources :relations, :only => [:index, :create]
-    resources :relations, :path => "relation", :id => /\d+/, :only => [:show, :update, :destroy]
+    resources :relations, :path => "relation", :id => /\d+/, :only => [:show, :update, :destroy] do
+      member do
+        get :full, :action => :show, :full => true, :as => nil
+      end
+    end
     put "relation/create" => "relations#create", :as => nil
 
     resource :map, :only => :show
index 34953f7b7ac62841a1e27002ab383a9130393574..803a57acf52995448e082e6177a2f6184ab469d3 100644 (file)
@@ -27,11 +27,11 @@ module Api
       )
       assert_routing(
         { :path => "/api/0.6/relation/1/full", :method => :get },
-        { :controller => "api/relations", :action => "full", :id => "1" }
+        { :controller => "api/relations", :action => "show", :full => true, :id => "1" }
       )
       assert_routing(
         { :path => "/api/0.6/relation/1/full.json", :method => :get },
-        { :controller => "api/relations", :action => "full", :id => "1", :format => "json" }
+        { :controller => "api/relations", :action => "show", :full => true, :id => "1", :format => "json" }
       )
       assert_routing(
         { :path => "/api/0.6/relation/1", :method => :put },
@@ -149,19 +149,19 @@ module Api
     end
 
     def test_full_not_found
-      get relation_full_path(999999)
+      get api_relation_path(999999, :full => true)
       assert_response :not_found
     end
 
     def test_full_deleted
-      get relation_full_path(create(:relation, :deleted))
+      get api_relation_path(create(:relation, :deleted), :full => true)
       assert_response :gone
     end
 
     def test_full_empty
       relation = create(:relation)
 
-      get relation_full_path(relation)
+      get api_relation_path(relation, :full => true)
 
       assert_response :success
       assert_dom "relation", :count => 1 do
@@ -174,7 +174,7 @@ module Api
       node = create(:node)
       create(:relation_member, :relation => relation, :member => node)
 
-      get relation_full_path(relation)
+      get api_relation_path(relation, :full => true)
 
       assert_response :success
       assert_dom "node", :count => 1 do
@@ -190,7 +190,7 @@ module Api
       way = create(:way_with_nodes)
       create(:relation_member, :relation => relation, :member => way)
 
-      get relation_full_path(relation)
+      get api_relation_path(relation, :full => true)
 
       assert_response :success
       assert_dom "node", :count => 1 do
@@ -204,6 +204,30 @@ module Api
       end
     end
 
+    def test_full_with_node_member_json
+      relation = create(:relation)
+      node = create(:node)
+      create(:relation_member, :relation => relation, :member => node)
+
+      get api_relation_path(relation, :full => true, :format => "json")
+
+      assert_response :success
+      js = ActiveSupport::JSON.decode(@response.body)
+      assert_not_nil js
+      assert_equal 2, js["elements"].count
+
+      js_relations = js["elements"].filter { |e| e["type"] == "relation" }
+      assert_equal 1, js_relations.count
+      assert_equal relation.id, js_relations[0]["id"]
+      assert_equal 1, js_relations[0]["members"].count
+      assert_equal "node", js_relations[0]["members"][0]["type"]
+      assert_equal node.id, js_relations[0]["members"][0]["ref"]
+
+      js_nodes = js["elements"].filter { |e| e["type"] == "node" }
+      assert_equal 1, js_nodes.count
+      assert_equal node.id, js_nodes[0]["id"]
+    end
+
     ##
     # check that all relations containing a particular node, and no extra
     # relations, are returned from the relations_for_node call.
index 2ff5e6f29f786a94b3c7080535fcc371ce9150d3..191f9a82037b14c8f2437c0e1bb5f9661953dd81 100644 (file)
@@ -27,11 +27,11 @@ module Api
       )
       assert_routing(
         { :path => "/api/0.6/way/1/full", :method => :get },
-        { :controller => "api/ways", :action => "full", :id => "1" }
+        { :controller => "api/ways", :action => "show", :full => true, :id => "1" }
       )
       assert_routing(
         { :path => "/api/0.6/way/1/full.json", :method => :get },
-        { :controller => "api/ways", :action => "full", :id => "1", :format => "json" }
+        { :controller => "api/ways", :action => "show", :full => true, :id => "1", :format => "json" }
       )
       assert_routing(
         { :path => "/api/0.6/way/1", :method => :put },
@@ -136,10 +136,10 @@ module Api
 
     ##
     # check the "full" mode
-    def test_full
+    def test_show_full
       way = create(:way_with_nodes, :nodes_count => 3)
 
-      get way_full_path(way)
+      get api_way_path(way, :full => true)
 
       assert_response :success
 
@@ -154,10 +154,42 @@ module Api
       end
     end
 
-    def test_full_deleted
+    def test_show_full_json
+      way = create(:way_with_nodes, :nodes_count => 3)
+
+      get api_way_path(way, :full => true, :format => "json")
+
+      assert_response :success
+
+      # Check the way is correctly returned
+      js = ActiveSupport::JSON.decode(@response.body)
+      assert_not_nil js
+      assert_equal 4, js["elements"].count
+      js_ways = js["elements"].filter { |e| e["type"] == "way" }
+      assert_equal 1, js_ways.count
+      assert_equal way.id, js_ways[0]["id"]
+      assert_equal 1, js_ways[0]["version"]
+
+      # check that each node in the way appears once in the output as a
+      # reference and as the node element.
+      js_nodes = js["elements"].filter { |e| e["type"] == "node" }
+      assert_equal 3, js_nodes.count
+
+      way.nodes.each_with_index do |n, i|
+        assert_equal n.id, js_ways[0]["nodes"][i]
+        js_nodes_with_id = js_nodes.filter { |e| e["id"] == n.id }
+        assert_equal 1, js_nodes_with_id.count
+        assert_equal n.id, js_nodes_with_id[0]["id"]
+        assert_equal 1, js_nodes_with_id[0]["version"]
+        assert_equal n.lat, js_nodes_with_id[0]["lat"]
+        assert_equal n.lon, js_nodes_with_id[0]["lon"]
+      end
+    end
+
+    def test_show_full_deleted
       way = create(:way, :deleted)
 
-      get way_full_path(way)
+      get api_way_path(way, :full => true)
 
       assert_response :gone
     end