UNPKG

18 kBJavaScriptView Raw
1// TODO: if status is 0 then THROW ASSERTION!!
2const assert = require('assert');
3const fs = require('fs');
4const rimraf = require('rimraf');
5
6const AUTHENTICATION_TOKEN = 'ec25fc7b-6ee2-4bda-b57c-6c9867b30ff4';
7const AJAX_AUTHORIZATION_HEADERS = {
8 'Content-Type': 'application/json', 'Authorization': `Token ${AUTHENTICATION_TOKEN}`
9};
10
11process.setMaxListeners(0);
12
13describe('MemServer.Server Parameters and Query Parameters', function() {
14 before(function() {
15 fs.mkdirSync(`./memserver`);
16 fs.mkdirSync(`./memserver/models`);
17 fs.writeFileSync(`${process.cwd()}/memserver/models/user.js`, `
18 import Model from '${process.cwd()}/lib/model';
19
20 export default Model({
21 findFromHeaderToken(headers) {
22 const authorizationHeader = headers.Authorization;
23 const token = authorizationHeader ? authorizationHeader.slice(6) : false;
24
25 return this.findBy({ authentication_token: token }) || false;
26 }
27 });
28 `);
29 fs.writeFileSync(`${process.cwd()}/memserver/models/photo.js`, `
30 import Model from '${process.cwd()}/lib/model';
31
32 export default Model({
33 defaultAttributes: {
34 is_public: true,
35 name() {
36 return 'Some default name';
37 }
38 }
39 });
40 `);
41 fs.writeFileSync(`${process.cwd()}/memserver/models/photo-comment.js`, `
42 import Model from '${process.cwd()}/lib/model';
43
44 export default Model({
45 defaultAttributes: {
46 inserted_at() {
47 return '2017-10-25T20:54:04.447Z';
48 },
49 is_important: true
50 }
51 });
52 `);
53 fs.mkdirSync(`./memserver/fixtures`);
54 fs.writeFileSync(`${process.cwd()}/memserver/fixtures/users.js`, `export default [
55 {
56 id: 1,
57 email: 'contact@izelnakri.com',
58 username: 'izelnakri',
59 authentication_token: '${AUTHENTICATION_TOKEN}'
60 }
61 ];`);
62 fs.writeFileSync(`${process.cwd()}/memserver/fixtures/photos.js`, `export default [
63 {
64 id: 1,
65 name: 'Ski trip',
66 href: 'ski-trip.jpeg',
67 is_public: false,
68 user_id: 1
69 },
70 {
71 id: 2,
72 name: 'Family photo',
73 href: 'family-photo.jpeg',
74 is_public: true,
75 user_id: 1
76 },
77 {
78 id: 3,
79 name: 'Selfie',
80 href: 'selfie.jpeg',
81 is_public: false,
82 user_id: 1
83 }
84 ];`);
85 fs.writeFileSync(`${process.cwd()}/memserver/fixtures/photo-comments.js`, `export default [
86 {
87 uuid: '499ec646-493f-4eea-b92e-e383d94182f4',
88 content: 'What a nice photo!',
89 photo_id: 1,
90 user_id: 1
91 },
92 {
93 uuid: '77653ad3-47e4-4ec2-b49f-57ea36a627e7',
94 content: 'I agree',
95 photo_id: 1,
96 user_id: 2
97 },
98 {
99 uuid: 'd351963d-e725-4092-a37c-1ca1823b57d3',
100 content: 'I was kidding',
101 photo_id: 1,
102 user_id: 1
103 },
104 {
105 uuid: '374c7f4a-85d6-429a-bf2a-0719525f5f29',
106 content: 'Interesting indeed',
107 photo_id: 2,
108 user_id: 1
109 }
110 ];`);
111 });
112
113 beforeEach(function() {
114 Object.keys(require.cache).forEach((key) => delete require.cache[key]);
115 });
116
117 after(function(done) {
118 if (fs.existsSync(`${process.cwd()}/memserver`)) {
119 rimraf.sync(`${process.cwd()}/memserver`);
120 }
121
122 done();
123 });
124
125 describe('server can process custom queryParams and responses', function() {
126 before(function(){
127 fs.writeFileSync(`${process.cwd()}/memserver/server.js`, `
128 import Response from '../lib/response';
129
130 export default function({ User, Photo }) {
131 this.post('/photos', ({ headers, params, queryParams }) => {
132 const user = User.findFromHeaderToken(headers);
133
134 if (!user || !queryParams.is_admin) {
135 return Response(401, { error: 'Unauthorized' });
136 }
137
138 const photo = Photo.insert(Object.assign({}, params.photo, { user_id: user.id }));
139
140 return { photo: Photo.serializer(photo) };
141 });
142
143 this.get('/photos', ({ headers, queryParams }) => {
144 const user = User.findFromHeaderToken(headers);
145
146 if (!user) {
147 return Response(404, { error: 'Not found' });
148 }
149
150 const photos = Photo.findAll(Object.assign({}, { user_id: user.id }, queryParams));
151
152 if (!photos || photos.length === 0) {
153 return Response(404, { error: 'Not found' });
154 }
155
156 return { photos: Photo.serializer(photos) };
157 });
158
159 this.get('/photos/:id', ({ headers, params, queryParams }) => {
160 const user = User.findFromHeaderToken(headers);
161
162 if (!user) {
163 return Response(401, { error: 'Unauthorized' });
164 } else if (queryParams.nonce === 123123123) {
165 const photo = Photo.findBy({ id: params.id, user_id: user.id });
166
167 return photo ? { photo: Photo.serializer(photo) } : Response(404, { error: 'Not found' });
168 }
169
170 return Response(404, { error: 'Not found' });
171 });
172
173 this.put('/photos/:id', ({ headers, params, queryParams }) => {
174 const user = User.findFromHeaderToken(headers);
175 const validRequest = user && queryParams.nonce === 123123123 &&
176 Photo.findBy({ id: params.id, user_id: user.id });
177
178 if (validRequest) {
179 return { photo: Photo.serializer(Photo.update(params.photo)) };
180 }
181
182 return Response(500, { error: 'Unexpected error occured' });
183 });
184
185 this.delete('/photos/:id', ({ headers, params, queryParams }) => {
186 const user = User.findFromHeaderToken(headers);
187
188 if (!(queryParams.nonce === 123123123)) {
189 return Response(500, { error: 'Invalid nonce to delete a photo' });
190 } else if (!user && !Photo.findBy({ id: params.id, user_id: user.id })) {
191 return Response(404, { error: 'Not found' });
192 }
193
194 Photo.delete({ id: params.id }); // NOTE: what to do with this response
195 });
196 }
197 `);
198 });
199
200 it('POST /resources work with custom headers, queryParams and responses', async function() {
201 this.timeout(10000);
202
203 const MemServer = require('../../lib/index.js');
204 const { Photo } = MemServer.Models;
205
206 MemServer.start();
207 window.$ = require('jquery');
208
209 assert.equal(Photo.count(), 3);
210
211 await window.$.ajax({
212 type: 'POST', url: '/photos', headers: { 'Content-Type': 'application/json' }
213 }).catch((jqXHR) => {
214 assert.equal(jqXHR.status, 401);
215 assert.deepEqual(jqXHR.responseJSON, { error: 'Unauthorized' });
216 });
217
218 await window.$.ajax({
219 type: 'POST', url: '/photos', headers: AJAX_AUTHORIZATION_HEADERS
220 }).catch((jqXHR) => {
221 assert.equal(jqXHR.status, 401);
222 assert.deepEqual(jqXHR.responseJSON, { error: 'Unauthorized' });
223 });
224
225 await window.$.ajax({
226 type: 'POST', url: '/photos?is_admin=true', headers: AJAX_AUTHORIZATION_HEADERS
227 }).then((data, textStatus, jqXHR) => {
228 assert.equal(jqXHR.status, 201);
229 assert.deepEqual(data, { photo: Photo.serializer(Photo.find(4)) });
230 assert.equal(Photo.count(), 4);
231 });
232 });
233
234 it('GET /resources works with custom headers, queryParams and responses', async function() {
235 const MemServer = require('../../lib/index.js');
236 const { Photo } = MemServer.Models;
237
238 MemServer.start();
239 window.$ = require('jquery');
240
241 await window.$.ajax({
242 type: 'GET', url: '/photos', headers: { 'Content-Type': 'application/json' }
243 }).catch((jqXHR) => {
244 assert.equal(jqXHR.status, 404);
245 assert.deepEqual(jqXHR.responseJSON, { error: 'Not found' });
246 });
247
248 await window.$.ajax({
249 type: 'GET', url: '/photos?is_public=false', headers: AJAX_AUTHORIZATION_HEADERS
250 }).then((data, textStatus, jqXHR) => {
251 assert.equal(jqXHR.status, 200);
252 assert.deepEqual(data, { photos: Photo.serializer(Photo.findAll({ is_public: false })) });
253 });
254
255 await window.$.ajax({
256 type: 'GET', url: '/photos?href=family-photo.jpeg', headers: AJAX_AUTHORIZATION_HEADERS
257 }).then((data, textStatus, jqXHR) => {
258 assert.equal(jqXHR.status, 200);
259 assert.deepEqual(data, { photos: Photo.serializer(Photo.findAll({ href: 'family-photo.jpeg' })) });
260 });
261 });
262
263 it('GET /resources/:id works with custom headers, queryParams and responses', async function() {
264 const MemServer = require('../../lib/index.js');
265 const { Photo } = MemServer.Models;
266
267 MemServer.start();
268 window.$ = require('jquery');
269
270 await window.$.ajax({
271 type: 'GET', url: '/photos/1', headers: AJAX_AUTHORIZATION_HEADERS
272 }).catch((jqXHR) => {
273 assert.equal(jqXHR.status, 404);
274 assert.deepEqual(jqXHR.responseJSON, { error: 'Not found' });
275 });
276
277 await window.$.ajax({
278 type: 'GET', url: '/photos/1?nonce=123123123', headers: AJAX_AUTHORIZATION_HEADERS
279 }).then((data, textStatus, jqXHR) => {
280 assert.equal(jqXHR.status, 200);
281 assert.deepEqual(data, { photo: Photo.serializer(Photo.find(1)) });
282 });
283 });
284
285 it('PUT /resources/:id works with custom headers, queryParams and responses', async function() {
286 const MemServer = require('../../lib/index.js');
287 const { Photo } = MemServer.Models;
288
289 MemServer.start();
290 window.$ = require('jquery');
291
292 await window.$.ajax({
293 type: 'PUT', url: '/photos/1', headers: AJAX_AUTHORIZATION_HEADERS,
294 data: JSON.stringify({ photo: { id: 1, name: 'Life' } })
295 }).catch((jqXHR) => {
296 assert.equal(jqXHR.status, 500);
297 assert.deepEqual(jqXHR.responseJSON, { error: 'Unexpected error occured' });
298 });
299
300 await window.$.ajax({
301 type: 'PUT', url: '/photos/1?nonce=123123123', headers: AJAX_AUTHORIZATION_HEADERS,
302 data: JSON.stringify({ photo: { id: 1, name: 'Life' } })
303 }).then((data, textStatus, jqXHR) => {
304 assert.equal(jqXHR.status, 200);
305 assert.deepEqual(data, { photo: Photo.serializer(Photo.find(1)) });
306 });
307 });
308
309 it('DELETE /resources/:id works with custom headers, queryParams and responses', async function() {
310 const MemServer = require('../../lib/index.js');
311 const { Photo } = MemServer.Models;
312
313 MemServer.start();
314 window.$ = require('jquery');
315
316 await window.$.ajax({
317 type: 'DELETE', url: '/photos/1', headers: AJAX_AUTHORIZATION_HEADERS
318 }).catch((jqXHR) => {
319 assert.equal(jqXHR.status, 500);
320 assert.deepEqual(jqXHR.responseJSON, { error: 'Invalid nonce to delete a photo' });
321 });
322
323 await window.$.ajax({
324 type: 'DELETE', url: '/photos/1?nonce=123123123', headers: AJAX_AUTHORIZATION_HEADERS
325 }).then((data, textStatus, jqXHR) => {
326 assert.equal(jqXHR.status, 204);
327 });
328 });
329 });
330
331 describe('some edge cases', function() {
332 before(function() {
333 fs.writeFileSync(`${process.cwd()}/memserver/models/ethereum-account.js`, `
334 import Model from '${process.cwd()}/lib/model';
335
336 export default Model({
337 });
338 `);
339 fs.writeFileSync(`${process.cwd()}/memserver/fixtures/ethereum-accounts.js`, `export default [
340 {
341 id: 1,
342 address: '0x7be8315acfef37816c9ad4dc5e82195f2a52934c5d0c74883f9978675e26d600'
343 }
344 ];`);
345
346 fs.writeFileSync(`${process.cwd()}/memserver/server.js`, `
347 import Response from '../lib/response';
348
349 export default function({ EthereumAccount, Photo, PhotoComment }) {
350 this.get('/ethereum-accounts', ({ queryParams }) => {
351 const ethereumAccounts = EthereumAccount.findAll({ address: queryParams.address });
352
353 return { ethereum_accounts: EthereumAccount.serializer(ethereumAccounts) };
354 });
355
356 this.get('/ethereum-accounts/:address', ({ params }) => {
357 const ethereumAccount = EthereumAccount.findBy({ address: params.address });
358
359 return { ethereum_account: EthereumAccount.serializer(ethereumAccount) };
360 });
361
362 this.get('/photos', ({ queryParams }) => {
363 const photos = Photo.find(queryParams.ids || []);
364
365 if (!photos || photos.length === 0) {
366 return Response(404, { error: 'Not found' });
367 }
368
369 return { photos: Photo.serializer(photos) };
370 });
371
372 this.get('/photo-comments/:uuid', ({ params }) => {
373 const photoComment = PhotoComment.findBy({ uuid: params.uuid });
374
375 return { photo_comment: PhotoComment.serializer(photoComment) };
376 });
377
378 this.get('/photo-comments', ({ queryParams }) => {
379 const photoComments = PhotoComment.findAll({ uuid: queryParams.uuid });
380
381 return { photo_comments: PhotoComment.serializer(photoComments) };
382 });
383 }
384 `);
385 });
386
387 it('works for coalasceFindRequests routes', async function() {
388 const MemServer = require('../../lib/index.js');
389 const { Photo } = MemServer.Models;
390
391 MemServer.start();
392 window.$ = require('jquery');
393
394 await window.$.ajax({
395 type: 'GET', url: '/photos', headers: { 'Content-Type': 'application/json' }
396 }).catch((jqXHR) => {
397 assert.equal(jqXHR.status, 404);
398 assert.deepEqual(jqXHR.responseJSON, { error: 'Not found' });
399 });
400
401 await window.$.ajax({
402 type: 'GET', url: '/photos?ids[]=1&ids[]=2', headers: { 'Content-Type': 'application/json' }
403 }).then((data, textStatus, jqXHR) => {
404 assert.equal(jqXHR.status, 200);
405 assert.deepEqual(jqXHR.responseJSON, { photos: Photo.serializer(Photo.find([1, 2])) });
406 });
407
408 await window.$.ajax({
409 type: 'GET', url: '/photos?ids[]=2&ids[]=3', headers: { 'Content-Type': 'application/json' }
410 }).then((data, textStatus, jqXHR) => {
411 assert.equal(jqXHR.status, 200);
412 assert.deepEqual(jqXHR.responseJSON, { photos: Photo.serializer(Photo.find([2, 3])) });
413 });
414 });
415
416 it('converts empty strings to null in request and formats query params', async function() {
417 const MemServer = require('../../lib/index.js');
418 const { Photo } = MemServer.Models;
419
420 MemServer.start();
421 window.$ = require('jquery');
422
423 MemServer.Server.post('/photos', ({ params, queryParams }) => {
424 assert.deepEqual(params, { name: null, title: 'Cool' });
425 assert.deepEqual(queryParams, { is_important: true, filter: 32 });
426
427 return { photo: Photo.serializer(Photo.insert(params)) };
428 });
429
430 await window.$.ajax({
431 type: 'POST', url: '/photos?is_important=true&filter=32', data: { name: '', title: 'Cool' }
432 }).then((data, textStatus, jqXHR) => {
433 assert.equal(jqXHR.status, 201);
434 assert.equal(Photo.count(), 4);
435 });
436 });
437
438 it('casts uuids correctly as params', async function() {
439 const MemServer = require('../../lib/index.js');
440 const { PhotoComment } = MemServer.Models;
441
442 MemServer.start();
443 window.$ = require('jquery');
444
445 const targetComment = PhotoComment.findBy({ uuid: '499ec646-493f-4eea-b92e-e383d94182f4' });
446
447 await window.$.ajax({
448 type: 'GET', url: '/photo-comments/499ec646-493f-4eea-b92e-e383d94182f4'
449 }).then((data, textStatus, jqXHR) => {
450 assert.equal(jqXHR.status, 200);
451 assert.deepEqual(data, { photo_comment: PhotoComment.serializer(targetComment) });
452 });
453 });
454
455 it('casts uuids correctly as queryParams', async function() {
456 const MemServer = require('../../lib/index.js');
457 const { PhotoComment } = MemServer.Models;
458
459 MemServer.start();
460 window.$ = require('jquery');
461
462 const targetComments = PhotoComment.findAll({ uuid: '499ec646-493f-4eea-b92e-e383d94182f4' });
463
464 await window.$.ajax({
465 type: 'GET', url: '/photo-comments?uuid=499ec646-493f-4eea-b92e-e383d94182f4'
466 }).then((data, textStatus, jqXHR) => {
467 assert.equal(jqXHR.status, 200);
468 assert.deepEqual(data, { photo_comments: PhotoComment.serializer(targetComments) });
469 });
470 });
471
472 it('casts ethereum addresses correctly as string request.params', async function() {
473 this.timeout(10000);
474
475 const MemServer = require('../../lib/index.js');
476 const { EthereumAccount } = MemServer.Models;
477
478 MemServer.start();
479 window.$ = require('jquery');
480
481 const targetAccount = EthereumAccount.findBy({
482 address: '0x7be8315acfef37816c9ad4dc5e82195f2a52934c5d0c74883f9978675e26d600'
483 });
484
485 await window.$.ajax({
486 type: 'GET',
487 url: '/ethereum-accounts/0x7be8315acfef37816c9ad4dc5e82195f2a52934c5d0c74883f9978675e26d600'
488 }).then((data, textStatus, jqXHR) => {
489 assert.equal(jqXHR.status, 200);
490 assert.deepEqual(data, { ethereum_account: EthereumAccount.serializer(targetAccount) });
491 });
492 });
493
494 it('casts ethereum addresses correctly as string request.queryParams', async function() {
495 this.timeout(10000);
496
497 const MemServer = require('../../lib/index.js');
498 const { EthereumAccount } = MemServer.Models;
499
500 MemServer.start();
501 window.$ = require('jquery');
502
503 const targetAccounts = EthereumAccount.findAll({
504 address: '0x7be8315acfef37816c9ad4dc5e82195f2a52934c5d0c74883f9978675e26d600'
505 });
506
507 await window.$.ajax({
508 type: 'GET',
509 url: '/ethereum-accounts?address=0x7be8315acfef37816c9ad4dc5e82195f2a52934c5d0c74883f9978675e26d600'
510 }).then((data, textStatus, jqXHR) => {
511 assert.equal(jqXHR.status, 200);
512 assert.deepEqual(data, { ethereum_accounts: EthereumAccount.serializer(targetAccounts) });
513 });
514
515 });
516 });
517});