1 | var test = require('tape')
|
2 | var contentType = require('content-type')
|
3 | var parsexml = require('xml-parser')
|
4 | var hyperquest = require('hyperquest')
|
5 | var concat = require('concat-stream')
|
6 |
|
7 | var base
|
8 | var server
|
9 | var changeId
|
10 | var createServer = require('./lib/test_server.js')
|
11 |
|
12 | test('many_types.js: setup server', function (t) {
|
13 | createServer(function (d) {
|
14 | base = d.base
|
15 | server = d.server
|
16 | t.end()
|
17 | })
|
18 | })
|
19 |
|
20 | test('create changeset', function (t) {
|
21 | t.plan(4)
|
22 | var href = base + 'changeset/create'
|
23 | var hq = hyperquest.put(href, {
|
24 | headers: { 'content-type': 'text/xml' }
|
25 | })
|
26 | hq.once('response', function (res) {
|
27 | t.equal(res.statusCode, 200, 'create 200 ok')
|
28 | var contentObj = contentType.parse(res)
|
29 | t.equal(contentObj.type, 'text/plain', 'media type correct')
|
30 | t.equal(contentObj.parameters.charset.toLowerCase(), 'utf-8', 'charset correct')
|
31 | })
|
32 | hq.pipe(concat({ encoding: 'string' }, function (body) {
|
33 | changeId = body.trim()
|
34 | t.ok(/^[0-9A-Fa-f]+$/.test(changeId), 'expected changeset id response')
|
35 | }))
|
36 | hq.end(`<osm>
|
37 | <changeset>
|
38 | <tag k="comment" v="whatever"/>
|
39 | </changeset>
|
40 | <changeset>
|
41 | <tag k="cool" v="beans"/>
|
42 | <tag k="comment" v="wow"/>
|
43 | </changeset>
|
44 | </osm>`)
|
45 | })
|
46 |
|
47 | var uploaded = {}
|
48 | var keys = {}
|
49 |
|
50 | test('add docs to changeset', function (t) {
|
51 | var docs = [
|
52 | { id: 'A', type: 'node', lat: 64.5, lon: -121.5, changeset: changeId },
|
53 | { id: 'B', type: 'node', lat: 63.9, lon: -120.9, changeset: changeId },
|
54 | { id: 'C', type: 'node', lat: 64.3, lon: -122.1, changeset: changeId },
|
55 | { id: 'D', type: 'node', lat: 65.1, lon: -120.9, changeset: changeId },
|
56 | { id: 'E', type: 'node', lat: 65.3, lon: -120.8, changeset: changeId },
|
57 | { id: 'F', type: 'node', lat: 60.6, lon: -122.3, changeset: changeId },
|
58 | { id: 'G', type: 'way', refs: ['A', 'B', 'C'], changeset: changeId },
|
59 | { id: 'H', type: 'way', refs: ['D', 'E'], changeset: changeId },
|
60 | { id: 'I',
|
61 | type: 'relation',
|
62 | changeset: changeId,
|
63 | members: [
|
64 | { type: 'node', ref: 'F' },
|
65 | { type: 'way', ref: 'G' },
|
66 | { type: 'way', ref: 'H' }
|
67 | ]
|
68 | }
|
69 | ]
|
70 | t.plan(docs.length * 4)
|
71 | ;(function next () {
|
72 | if (docs.length === 0) return
|
73 | var doc = docs.shift()
|
74 | var key = doc.id
|
75 | delete doc.id
|
76 |
|
77 | ;(doc.refs || []).forEach(function (ref, i) {
|
78 | if (keys[ref]) doc.refs[i] = keys[ref]
|
79 | })
|
80 | ;(doc.members || []).forEach(function (member) {
|
81 | if (keys[member.ref]) member.ref = keys[member.ref]
|
82 | })
|
83 |
|
84 | var href = base + doc.type + '/create'
|
85 | var hq = hyperquest.put(href, {
|
86 | headers: { 'content-type': 'text/xml' }
|
87 | })
|
88 | hq.once('response', function (res) {
|
89 | t.equal(res.statusCode, 200)
|
90 | var contentObj = contentType.parse(res)
|
91 | t.equal(contentObj.type, 'text/plain', 'media type correct')
|
92 | t.equal(contentObj.parameters.charset.toLowerCase(), 'utf-8', 'charset correct')
|
93 | })
|
94 | hq.pipe(concat({ encoding: 'string' }, function (body) {
|
95 | t.ok(/^[0-9A-Fa-f]+$/.test(body.trim()))
|
96 | uploaded[doc.lon + ',' + doc.lat] = body.trim()
|
97 | keys[key] = body.trim()
|
98 | next()
|
99 | }))
|
100 | if (doc.type === 'node') {
|
101 | hq.end(`<osm>
|
102 | <node changeset="${doc.changeset}"
|
103 | lat="${doc.lat}" lon="${doc.lon}"
|
104 | id="IGNOREME">
|
105 | </node>
|
106 | </osm>`)
|
107 | } else if (doc.type === 'way') {
|
108 | hq.end(`<osm><way changeset="${doc.changeset}">
|
109 | ${doc.refs.map(function (ref) {
|
110 | return `<nd ref="${ref}" />`
|
111 | }).join('')}
|
112 | </way></osm>`)
|
113 | } else if (doc.type === 'relation') {
|
114 | hq.end(`<osm><relation changeset="${doc.changeset}">
|
115 | ${doc.members.map(function (member) {
|
116 | return `<member type="${member.type}" ref="${member.ref}" />`
|
117 | }).join('')}
|
118 | </relation></osm>`)
|
119 | }
|
120 | })()
|
121 | })
|
122 |
|
123 | test('multi-fetch ways', function (t) {
|
124 | t.plan(7)
|
125 | var href = base + 'ways?ways=' + keys.G + ',' + keys.H
|
126 | var hq = hyperquest(href, {
|
127 | headers: { 'content-type': 'text/xml' }
|
128 | })
|
129 | hq.once('response', function (res) {
|
130 | t.equal(res.statusCode, 200)
|
131 | var contentObj = contentType.parse(res)
|
132 | t.equal(contentObj.type, 'text/xml', 'media type correct')
|
133 | t.equal(contentObj.parameters.charset.toLowerCase(), 'utf-8', 'charset correct')
|
134 | })
|
135 | hq.pipe(concat({ encoding: 'string' }, function (body) {
|
136 | var xml = parsexml(body)
|
137 | t.equal(xml.root.name, 'osm')
|
138 | t.equal(xml.root.children[0].name, 'way')
|
139 | t.equal(xml.root.children[1].name, 'way')
|
140 | var xids = xml.root.children.map(function (x) {
|
141 | return x.attributes.id
|
142 | })
|
143 | t.deepEqual(xids, [keys.G, keys.H], 'id comparison')
|
144 | }))
|
145 | })
|
146 |
|
147 | test('get relation', function (t) {
|
148 | t.plan(6)
|
149 | var href = base + 'relation/' + keys.I
|
150 | var hq = hyperquest(href, {
|
151 | headers: { 'content-type': 'text/xml' }
|
152 | })
|
153 | hq.once('response', function (res) {
|
154 | t.equal(res.statusCode, 200)
|
155 | var contentObj = contentType.parse(res)
|
156 | t.equal(contentObj.type, 'text/xml', 'media type correct')
|
157 | t.equal(contentObj.parameters.charset.toLowerCase(), 'utf-8', 'charset correct')
|
158 | })
|
159 | hq.pipe(concat({ encoding: 'string' }, function (body) {
|
160 | var xml = parsexml(body)
|
161 | t.equal(xml.root.name, 'osm')
|
162 | t.equal(xml.root.children[0].name, 'relation')
|
163 | var members = xml.root.children[0].children.map(function (x) {
|
164 | return { name: x.name, attributes: x.attributes }
|
165 | })
|
166 | t.deepEqual(members, [
|
167 | { name: 'member', attributes: { type: 'node', ref: keys.F, role: '' } },
|
168 | { name: 'member', attributes: { type: 'way', ref: keys.G, role: '' } },
|
169 | { name: 'member', attributes: { type: 'way', ref: keys.H, role: '' } }
|
170 | ], 'relation members')
|
171 | }))
|
172 | })
|
173 |
|
174 | test('get osmchange doc', function (t) {
|
175 | t.plan(4)
|
176 | var href = base + 'changeset/' + changeId + '/download'
|
177 | var hq = hyperquest(href, {
|
178 | headers: { 'content-type': 'text/xml' }
|
179 | })
|
180 | hq.pipe(concat({ encoding: 'string' }, function (body) {
|
181 | var xml = parsexml(body)
|
182 | t.equal(xml.root.name, 'osmChange')
|
183 | t.equal(xml.root.children.length, 1)
|
184 | t.equal(xml.root.children[0].name, 'create')
|
185 | xml.root.children[0].children.forEach(function (c) {
|
186 | delete c.attributes.timestamp
|
187 | })
|
188 | t.deepEqual(chfilter(xml.root.children[0].children).sort(cmpch), [
|
189 | { name: 'node',
|
190 | attributes: { id: keys.A, changeset: changeId, lat: '64.5', lon: '-121.5' },
|
191 | children: []
|
192 | },
|
193 | {
|
194 | name: 'node',
|
195 | attributes: { id: keys.B, changeset: changeId, lat: '63.9', lon: '-120.9' },
|
196 | children: []
|
197 | },
|
198 | {
|
199 | name: 'node',
|
200 | attributes: { id: keys.C, changeset: changeId, lat: '64.3', lon: '-122.1' },
|
201 | children: []
|
202 | },
|
203 | {
|
204 | name: 'node',
|
205 | attributes: { id: keys.D, changeset: changeId, lat: '65.1', lon: '-120.9' },
|
206 | children: []
|
207 | },
|
208 | {
|
209 | name: 'node',
|
210 | attributes: { id: keys.E, changeset: changeId, lat: '65.3', lon: '-120.8' },
|
211 | children: []
|
212 | },
|
213 | {
|
214 | name: 'node',
|
215 | attributes: { id: keys.F, changeset: changeId, lat: '60.6', lon: '-122.3' },
|
216 | children: []
|
217 | },
|
218 | {
|
219 | name: 'way',
|
220 | attributes: { id: keys.G, changeset: changeId },
|
221 | children: [
|
222 | { name: 'nd', attributes: { ref: keys.A }, children: [] },
|
223 | { name: 'nd', attributes: { ref: keys.B }, children: [] },
|
224 | { name: 'nd', attributes: { ref: keys.C }, children: [] }
|
225 | ],
|
226 | content: ''
|
227 | },
|
228 | {
|
229 | name: 'way',
|
230 | attributes: { id: keys.H, changeset: changeId },
|
231 | children: [
|
232 | { name: 'nd', attributes: { ref: keys.D }, children: [] },
|
233 | { name: 'nd', attributes: { ref: keys.E }, children: [] }
|
234 | ],
|
235 | content: ''
|
236 | },
|
237 | {
|
238 | name: 'relation',
|
239 | attributes: { id: keys.I, changeset: changeId },
|
240 | children: [
|
241 | { name: 'member', attributes: { type: 'node', ref: keys.F, role: '' }, children: [] },
|
242 | { name: 'member', attributes: { type: 'way', ref: keys.G, role: '' }, children: [] },
|
243 | { name: 'member', attributes: { type: 'way', ref: keys.H, role: '' }, children: [] }
|
244 | ],
|
245 | content: ''
|
246 | }
|
247 | ].sort(cmpch))
|
248 | }))
|
249 | })
|
250 |
|
251 | test('many_types.js: teardown server', function (t) {
|
252 | server.cleanup(function () {
|
253 | t.end()
|
254 | })
|
255 | })
|
256 |
|
257 | function cmpch (a, b) {
|
258 | return a.attributes.id < b.attributes.id ? -1 : 1
|
259 | }
|
260 |
|
261 | function chfilter (children) {
|
262 | children.forEach(function (c) {
|
263 | chfilter(c.children)
|
264 | delete c.attributes.version
|
265 | })
|
266 | return children
|
267 | }
|