UNPKG

5.5 kBJavaScriptView Raw
1var test = require('tape')
2var contentType = require('content-type')
3var parsexml = require('xml-parser')
4var hyperquest = require('hyperquest')
5var concat = require('concat-stream')
6var isISODate = require('isostring')
7
8var base
9var server
10
11var createServer = require('./lib/test_server.js')
12
13test('history.js: setup server', function (t) {
14 createServer(function (d) {
15 base = d.base
16 server = d.server
17 t.end()
18 })
19})
20
21var ids = {}
22var versions = {}
23var changesets = []
24test('create history', function (t) {
25 var updates = [
26 [
27 { type: 'node', lat: 64.5, lon: -121.5, id: 'A' },
28 { type: 'node', lat: 63.9, lon: -120.9, id: 'B' }
29 ],
30 [
31 { type: 'node', lat: 64.3, lon: -121.4, id: 'A' }
32 ],
33 [
34 { type: 'node', lat: 64.2, lon: -121.4, id: 'A', tags: { beep: 'boop' } }
35 ],
36 [
37 { type: 'node', lat: 63.9, lon: -120.8, id: 'B' }
38 ]
39 ]
40 t.plan(7 * updates.length)
41 var exists = {}
42 var versionId = {}
43 ;(function next () {
44 if (updates.length === 0) return
45 var update = updates.shift()
46 var hq = hyperquest.put(base + 'changeset/create', {
47 headers: { 'content-type': 'text/xml' }
48 })
49 hq.once('response', function (res) {
50 t.equal(res.statusCode, 200, 'create 200 ok')
51 var contentObj = contentType.parse(res)
52 t.equal(contentObj.type, 'text/plain', 'media type correct')
53 t.equal(contentObj.parameters.charset.toLowerCase(), 'utf-8', 'charset correct')
54 })
55 hq.pipe(concat({ encoding: 'string' }, function (body) {
56 var changeId = body.trim()
57 t.ok(/^[0-9A-Fa-f]+$/.test(changeId), 'expected changeset id response')
58 changesets.push(changeId)
59 upload(changeId, update, next)
60 }))
61 hq.end('<osm><changeset></changeset></osm>')
62 })()
63
64 function upload (changeId, update, next) {
65 var hq = hyperquest.post(base + 'changeset/' + changeId + '/upload', {
66 headers: { 'content-type': 'text/xml' }
67 })
68 hq.once('response', function (res) {
69 t.equal(res.statusCode, 200, 'create 200 ok')
70 t.equal(res.headers['content-type'], 'text/xml; charset=utf-8', 'upload content type')
71 })
72 hq.pipe(concat({ encoding: 'string' }, function (body) {
73 var xml = parsexml(body)
74 t.equal(xml.root.name, 'diffResult')
75 xml.root.children.forEach(function (c) {
76 var key
77 if (/^-\d+/.test(c.attributes.old_id)) {
78 key = update[-1 - Number(c.attributes.old_id)].id
79 ids[key] = c.attributes.new_id
80 versionId[c.attributes.new_id] = key
81 } else {
82 key = versionId[c.attributes.old_id]
83 versionId[c.attributes.new_id] = key
84 }
85 if (!versions[key]) versions[key] = []
86 versions[key].push(c.attributes.new_version)
87 })
88 next()
89 }))
90 hq.end(`<osmChange version="1.0" generator="acme osm editor">
91 <create>
92 ${update.filter(notExistFilter).map(createMap)}
93 </create>
94 <modify>
95 ${update.filter(existFilter).map(modifyMap)}
96 </modify>
97 </osmChange>`)
98 update.forEach(function (doc) { exists[doc.id] = true })
99
100 function createMap (doc, i) {
101 return `<node id="-${i + 1}"
102 lat="${doc.lat}"
103 lon="${doc.lon}"
104 changeset="${changeId}"
105 >${Object.keys(doc.tags || {}).map(function (key) {
106 return `<tag k="${key}" v="${doc.tags[key]}"/>`
107 }).join('')}
108 </node>`
109 }
110 function modifyMap (doc) {
111 return `<node id="${ids[doc.id]}"
112 lat="${doc.lat}" lon="${doc.lon}"
113 changeset="${changeId}"
114 >${Object.keys(doc.tags || {}).map(function (key) {
115 return `<tag k="${key}" v="${doc.tags[key]}"/>`
116 }).join('')}
117 </node>`
118 }
119 function existFilter (doc) { return exists[doc.id] }
120 function notExistFilter (doc) { return !exists[doc.id] }
121 }
122})
123
124test('history route', function (t) {
125 t.plan(8)
126 var expected = [
127 {
128 name: 'node',
129 attributes: {
130 changeset: changesets[2],
131 id: ids.A,
132 lat: '64.2',
133 lon: '-121.4',
134 version: versions.A[2]
135 },
136 children: [
137 {
138 name: 'tag',
139 attributes: {
140 k: 'beep',
141 v: 'boop'
142 },
143 children: []
144 }
145 ],
146 content: ''
147 },
148 {
149 name: 'node',
150 attributes: {
151 changeset: changesets[1],
152 id: ids.A,
153 lat: '64.3',
154 lon: '-121.4',
155 version: versions.A[1]
156 },
157 children: []
158 },
159 {
160 name: 'node',
161 attributes: {
162 changeset: changesets[0],
163 id: ids.A,
164 lat: '64.5',
165 lon: '-121.5',
166 version: versions.A[0]
167 },
168 children: []
169 }
170 ]
171 var hq = hyperquest(base + 'node/' + ids.A + '/history', {
172 headers: { 'content-type': 'text/xml' }
173 })
174 hq.on('response', function (res) {
175 t.equal(res.statusCode, 200)
176 var contentObj = contentType.parse(res)
177 t.equal(contentObj.type, 'text/xml', 'media type correct')
178 t.equal(contentObj.parameters.charset.toLowerCase(), 'utf-8', 'charset correct')
179 })
180 hq.pipe(concat({ encoding: 'string' }, function (body) {
181 var xml = parsexml(body)
182 t.equal(xml.root.name, 'osm')
183 xml.root.children.forEach(function (c) {
184 t.true(isISODate(c.attributes.timestamp))
185 delete c.attributes.timestamp
186 })
187 t.deepEqual(xml.root.children, expected)
188 }))
189})
190
191test('history.js: teardown server', function (t) {
192 server.cleanup(function () {
193 t.end()
194 })
195})