UNPKG

34.5 kBJavaScriptView Raw
1/*
2 * Licensed under the Apache License, Version 2.0 (the "License");
3 * you may not use this file except in compliance with the License.
4 * You may obtain a copy of the License at
5 *
6 * http://www.apache.org/licenses/LICENSE-2.0
7 *
8 * Unless required by applicable law or agreed to in writing, software
9 * distributed under the License is distributed on an "AS IS" BASIS,
10 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 * See the License for the specific language governing permissions and
12 * limitations under the License.
13 */
14
15'use strict';
16
17const JavascriptParser = require('../lib/javascriptparser');
18const fs = require('fs');
19const path = require('path');
20const doctrine = require('doctrine');
21const acorn = require('acorn');
22const chai = require('chai');
23chai.should();
24chai.use(require('chai-as-promised'));
25chai.use(require('chai-things'));
26const sinon = require('sinon');
27
28const readTestExample = function(exampleName) {
29 const exampleFile = path.resolve(__dirname, './data/commentparsing/', exampleName);
30 return fs.readFileSync(exampleFile).toString();
31};
32
33describe('JavascriptParser', () => {
34 let sandbox;
35
36 beforeEach(() => {
37 sandbox = sinon.createSandbox();
38 });
39
40 afterEach(() => {
41 sandbox.restore();
42 });
43
44
45 describe('#constructor', () => {
46 let sandbox;
47
48 beforeEach(() => {
49 sandbox = sinon.createSandbox();
50 });
51
52 afterEach(() => {
53 sandbox.restore();
54 });
55 it('should use a default ECMAScript version of 7', () => {
56 const contents = `
57 let num = 3 ** 2;
58 num **= 2;
59 [ 81 ].includes(num);
60 `;
61
62 const parser = new JavascriptParser(contents);
63 parser.should.exist;
64 });
65
66 it('should accept a non-default ECMAScript version of 5', () => {
67 const contents = `
68 class cls { }
69 `;
70
71 (() => {
72 new JavascriptParser(contents, false, 5);
73 }).should.throw(/The keyword .*class.* is reserved/);
74 });
75
76
77 it('should accept a non-default ECMAScript version of 5', () => {
78 const contents = `
79 `;
80
81 sandbox.stub(acorn.Parser.prototype,'startNode').returns({body:[]});
82 sandbox.stub(acorn.Parser.prototype,'finishNode').returns({body:[]});
83 new JavascriptParser(contents, false, 5);
84
85 });
86
87 it('should accept a non-default ECMAScript version of 5', () => {
88
89
90 new JavascriptParser('', false, 5);
91
92 });
93
94 it('should accept and return private methods', () => {
95 const contents = `
96 /**
97 * @private
98 */
99 function findAnimalsByOwnerId(farmerId) {
100 return query('select a from Animal a where a.owner == :farmerId');
101 }
102
103 `;
104
105 (() => {
106 new JavascriptParser(contents, true);
107 });
108 });
109
110 it('should accept and return private methods', () => {
111 const contents = `
112 /**
113 * @private
114 */
115 function findAnimalsByOwnerId(farmerId) {
116 return query('select a from Animal a where a.owner == :farmerId');
117 }
118
119 `;
120
121 (() => {
122 new JavascriptParser(contents, false);
123 });
124 });
125
126 it('should accept and return private classes & methods', () => {
127 const contents = `
128 /**
129 * @private
130 */
131 class P extends S{
132
133 /**
134 * @private
135 */
136 findAnimalsByOwnerId(farmerId) {
137 return query('select a from Animal a where a.owner == :farmerId');
138 }
139
140 }
141
142 `;
143
144 (() => {
145 new JavascriptParser(contents, true);
146 });
147 });
148 it('should accept and not return private classes & methods', () => {
149 const contents = `
150 /**
151 * @private
152 */
153 class P extends S{
154 /**
155 * @private
156 */
157 findAnimalsByOwnerId(farmerId) {
158 return query('select a from Animal a where a.owner == :farmerId');
159 }
160 }
161 `;
162
163 (() => {
164 new JavascriptParser(contents, false);
165 });
166 });
167 it('should accept and return private classes & methods', () => {
168 const contents = `
169 const r = require('./fred');
170 const t = require('bill');
171 /**
172 * @private
173 */
174 class P extends S{
175
176
177 /**
178 * @private
179 */
180 findAnimalsByOwnerId(farmerId) {
181 return query('select a from Animal a where a.owner == :farmerId');
182 }
183 }
184 `;
185
186 (() => {
187 new JavascriptParser(contents, true);
188 });
189 });
190
191 });
192
193 describe('#getClasses', () => {
194 it('should return the classes', () => {
195 const contents = `
196 class cls {
197 }
198 `;
199
200 const parser = new JavascriptParser(contents);
201 parser.getClasses().should.deep.equal([{ name: 'cls', methods: [],commentData:[] }]);
202 });
203 });
204
205 describe('#getFunctions', () => {
206 it('should return the functions', () => {
207 const contents = `
208 /**
209 * Get the Animals, but do not resolve contained relationships
210 * @query
211 * @param {String} farmerId - the email of the farmer
212 * @returns {Animal[]} - the animals that belong to the farmer
213 */
214 function findAnimalsByOwnerId(farmerId) {
215 return query('select a from Animal a where a.owner == :farmerId');
216 }
217 `;
218
219 const parser = new JavascriptParser(contents);
220 parser.getFunctions().should.deep.equal([{
221 'commentData': { 'description': 'Get the Animals, but do not resolve contained relationships',
222 'tags':
223 [ { 'title': 'query', 'description': null },
224 { 'title': 'param', 'description': 'the email of the farmer', 'type': {
225 'name': 'String',
226 'type': 'NameExpression'
227 },
228 'name': 'farmerId' },
229 { 'title': 'returns',
230 'description': 'the animals that belong to the farmer',
231 'type': {
232 'applications': [
233 {
234 'name': 'Animal',
235 'type': 'NameExpression'
236 }
237 ],
238 'expression': {
239 'name': 'Array',
240 'type': 'NameExpression'
241 },
242 'type': 'TypeApplication'
243 }
244 } ] },
245 'decorators': [
246 'query',
247 'param',
248 'returns',
249 ],
250 'example': '',
251 'functionText': 'function findAnimalsByOwnerId(farmerId) {\n return query(\'select a from Animal a where a.owner == :farmerId\');\n }',
252 'name': 'findAnimalsByOwnerId',
253 'parameterNames': [
254 'farmerId'
255 ],
256 'parameterTypes': [
257 'String'
258 ],
259 'returnType': 'Animal[]',
260 'throws': '',
261 'visibility': '+',
262 }]);
263 });
264 });
265
266 describe('#getTokens', () => {
267 afterEach(() => {
268 delete global.composerJavaScriptParserNoTokens;
269 });
270
271 it('should return all of the tokens', () => {
272 const contents = 'eval(true)';
273 const parser = new JavascriptParser(contents);
274 const tokens = parser.getTokens();
275 tokens.should.have.lengthOf(5);
276 tokens.should.all.have.property('loc');
277 });
278
279 it('should return no tokens if token collection is disabled', () => {
280 global.composerJavaScriptParserNoTokens = true;
281 const contents = 'eval(true)';
282 const parser = new JavascriptParser(contents);
283 const tokens = parser.getTokens();
284 tokens.should.have.lengthOf(0);
285 });
286 });
287
288 describe('#getText', () => {
289 it('should use the substring method correctly', () => {
290 JavascriptParser.getText(0, 6, 'strings are cool').should.equal('string');
291 });
292 });
293
294 describe('#getIncludes', () => {
295 it('call the method', () => {
296 const code = readTestExample('BasicExample.js.txt');
297 const parser = new JavascriptParser(code);
298 parser.getIncludes();
299 });
300 });
301
302 describe('#searchForComment', () => {
303 let commentSpy;
304 beforeEach(() => {
305 commentSpy = sandbox.spy(JavascriptParser, 'searchForComment');
306 });
307
308 it('should handle comments not directly before function', () => {
309 const code = readTestExample('CommentNotDirectlyBeforeFunction.js.txt');
310 sinon.assert.notCalled(commentSpy);
311 const parser = new JavascriptParser(code);
312 parser.getFunctions().length.should.equal(1);
313 const func = parser.getFunctions()[0];
314 func.decorators.should.deep.equal(['param', 'transaction']);
315 func.parameterTypes.length.should.equal(1);
316 func.parameterTypes[0].should.equal('org.acme.mynetwork.Trade');
317 func.name.should.equal('tradeCommodity');
318 sinon.assert.called(commentSpy);
319 });
320
321 it('should handle the basic of examples', () => {
322 const code = readTestExample('BasicExample.js.txt');
323 sinon.assert.notCalled(commentSpy);
324 const parser = new JavascriptParser(code);
325 parser.getFunctions().length.should.equal(1);
326 const func = parser.getFunctions()[0];
327 func.decorators.should.deep.equal(['param', 'transaction']);
328 func.parameterTypes.length.should.equal(1);
329 func.parameterTypes[0].should.equal('org.acme.mynetwork.Trade');
330 func.name.should.equal('tradeCommodity');
331 sinon.assert.called(commentSpy);
332 });
333
334 it('should handle the uncommented function following commented function', () => {
335 const code = readTestExample('UncommentedFollowingCommented.js.txt');
336 sinon.assert.notCalled(commentSpy);
337 const parser = new JavascriptParser(code);
338 parser.getFunctions().length.should.equal(2);
339 const func = parser.getFunctions()[0];
340 func.decorators.should.deep.equal(['param', 'transaction']);
341 func.name.should.equal('tradeCommodity');
342 func.parameterTypes.length.should.equal(1);
343 func.parameterTypes[0].should.equal('org.acme.mynetwork.Trade');
344 const func2 = parser.getFunctions()[1];
345 func2.decorators.length.should.equal(0);
346 func2.parameterTypes.length.should.equal(0);
347 sinon.assert.called(commentSpy);
348 });
349
350 it('should handle the class methods', () => {
351 const code = readTestExample('ClassExample.js.txt');
352 sinon.assert.notCalled(commentSpy);
353 const parser = new JavascriptParser(code, false, 7, true);
354 const clazz = parser.getClasses();
355 clazz.length.should.equal(1);
356 const methods = clazz[0].methods;
357 methods.length.should.equal(3);
358 methods[0].decorators.length.should.equal(0);
359 methods[1].decorators.should.deep.equal(['param', 'transaction']);
360 methods[2].decorators.length.should.equal(0);
361 sinon.assert.called(commentSpy);
362 });
363
364 it('should handle the a complex example', () => {
365 const code = readTestExample('ComplexExample.js.txt');
366 sinon.assert.notCalled(commentSpy);
367 const parser = new JavascriptParser(code);
368 const funcs = parser.getFunctions();
369 funcs.length.should.equal(12);
370 const noDecorators = [0, 1, 2, 3, 5, 6, 9, 10];
371 const allDecorators = [7, 8, 11];
372 noDecorators.forEach((value) => {
373 funcs[value].decorators.length.should.equal(0);
374 });
375 allDecorators.forEach((value) => {
376 funcs[value].decorators.length.should.equal(2);
377 funcs[value].decorators.should.deep.equal(['param', 'transaction']);
378 });
379 funcs[4].decorators.length.should.equal(1);
380 funcs[4].decorators[0].should.equal('transaction');
381 sinon.assert.called(commentSpy);
382 });
383
384 });
385
386
387 describe('#findCommentBefore', () => {
388 let commentSpy;
389 beforeEach(() => {
390 commentSpy = sandbox.spy(JavascriptParser, 'findCommentBefore');
391 });
392
393 it('should handle the basic of examples', () => {
394 const code = readTestExample('BasicExample.js.txt');
395 sinon.assert.notCalled(commentSpy);
396 const parser = new JavascriptParser(code,null,null,false);
397 parser.getFunctions().length.should.equal(1);
398 const func = parser.getFunctions()[0];
399 func.decorators.should.deep.equal(['param', 'transaction']);
400 func.parameterTypes.length.should.equal(1);
401 func.parameterTypes[0].should.equal('org.acme.mynetwork.Trade');
402 func.name.should.equal('tradeCommodity');
403 sinon.assert.called(commentSpy);
404 });
405
406 it('should handle the uncommented function following commented function', () => {
407 const code = readTestExample('UncommentedFollowingCommented.js.txt');
408 sinon.assert.notCalled(commentSpy);
409 const parser = new JavascriptParser(code,null,null,false);
410 parser.getFunctions().length.should.equal(2);
411 const func = parser.getFunctions()[0];
412 func.decorators.should.deep.equal(['param', 'transaction']);
413 func.name.should.equal('tradeCommodity');
414 func.parameterTypes.length.should.equal(1);
415 func.parameterTypes[0].should.equal('org.acme.mynetwork.Trade');
416 const func2 = parser.getFunctions()[1];
417 func2.decorators.length.should.equal(0);
418 func2.parameterTypes.length.should.equal(0);
419 sinon.assert.called(commentSpy);
420 });
421
422 it('should handle the class methods', () => {
423 const code = readTestExample('ClassExample.js.txt');
424 sinon.assert.notCalled(commentSpy);
425 const parser = new JavascriptParser(code, false, 7, false);
426 const clazz = parser.getClasses();
427 clazz.length.should.equal(1);
428 const methods = clazz[0].methods;
429 methods.length.should.equal(3);
430 methods[0].decorators.length.should.equal(0);
431 methods[1].decorators.should.deep.equal(['param', 'transaction']);
432 methods[2].decorators.length.should.equal(0);
433 sinon.assert.called(commentSpy);
434 });
435
436 it('should handle the a complex example', () => {
437 const code = readTestExample('ComplexExample.js.txt');
438 sinon.assert.notCalled(commentSpy);
439 const parser = new JavascriptParser(code,null,null,false);
440 const funcs = parser.getFunctions();
441 funcs.length.should.equal(12);
442 const noDecorators = [0, 1, 2, 3, 5, 6, 9, 10];
443 const allDecorators = [7, 8, 11];
444 noDecorators.forEach((value) => {
445 funcs[value].decorators.length.should.equal(0);
446 });
447 allDecorators.forEach((value) => {
448 funcs[value].decorators.length.should.equal(2);
449 funcs[value].decorators.should.deep.equal(['param', 'transaction']);
450 });
451 funcs[4].decorators.length.should.equal(1);
452 funcs[4].decorators[0].should.equal('transaction');
453 sinon.assert.called(commentSpy);
454 });
455
456 });
457
458 describe('#getDecorators', () => {
459 it('should return all decorators in the comment', () => {
460 const comment = `
461 /**
462 * Get the Animals, but do not resolve contained relationships
463 * @query
464 * @private
465 * @param {String} farmerId - the email of the farmer
466 * @returns {Animal[]} - the animals that belong to the farmer
467 * @throws {Error} - Description
468 */
469 `;
470
471 const returns = JavascriptParser.getDecorators(comment);
472 returns.should.deep.equal(['query', 'private', 'param', 'returns', 'throws']);
473 });
474 });
475
476 describe('#getVisibility', () => {
477 it('should return the visibility as private (-)', () => {
478 const comment = `
479 /**
480 * Get the Animals, but do not resolve contained relationships
481 * @query
482 * @private
483 * @param {String} farmerId - the email of the farmer
484 * @returns {Animal[]} - the animals that belong to the farmer
485 * @throws {Error} - Description
486 */
487 `;
488
489 const returns = JavascriptParser.getVisibility(comment);
490 returns.should.equal('-');
491 });
492
493 it('should return the visibility as public (+)', () => {
494 const comment = `
495 /**
496 * Get the Animals, but do not resolve contained relationships
497 * @query
498 * @public
499 * @param {String} farmerId - the email of the farmer
500 * @returns {Animal[]} - the animals that belong to the farmer
501 * @throws {Error} - Description
502 */
503 `;
504
505 const returns = JavascriptParser.getVisibility(comment);
506 returns.should.equal('+');
507 });
508 });
509
510 describe('#getReturnType', () => {
511 let sandbox;
512
513 beforeEach(() => {
514 sandbox = sinon.createSandbox();
515 });
516
517 afterEach(() => {
518 sandbox.restore();
519 });
520
521 it('should return the returns tag', () => {
522 const comment = `
523 /**
524 * Get the Animals, but do not resolve contained relationships
525 * @query
526 * @param {String} farmerId - the email of the farmer
527 * @returns {Animal[]} - the animals that belong to the farmer
528 * @throws {Error} - Description
529 */
530 `;
531
532 const returns = JavascriptParser.getReturnType(comment);
533 returns.should.equal('Animal[]');
534 });
535
536 it('should return the return tag', () => {
537 const comment = `
538 /**
539 * Get the Animals, but do not resolve contained relationships
540 * @query
541 * @param {String} farmerId - the email of the farmer
542 * @return {Animal[]} - the animals that belong to the farmer
543 * @throws {Error} - Description
544 */
545 `;
546
547 const returns = JavascriptParser.getReturnType(comment);
548 returns.should.equal('Animal[]');
549 });
550
551 it('should throw if there is more than one return/returns tag', () => {
552 const comment = `
553 /**
554 * Get the Animals, but do not resolve contained relationships
555 * @query
556 * @param {String} farmerId - the email of the farmer
557 * @return {Animal[]} - the animals that belong to the farmer
558 * @returns {Animal[]} - the animals that belong to the farmer
559 * @throws {Error} - Description
560 */
561 `;
562
563 (() => {
564 JavascriptParser.getReturnType(comment);
565 }).should.throw(Error);
566 });
567
568 it('should throw if there is more than one return/returns tag', () => {
569 const comment = `
570 /**
571 * Get the Animals, but do not resolve contained relationships
572 * @query
573 * @param {String} farmerId - the email of the farmer
574 * @return {Animal[]} - the animals that belong to the farmer
575 * @returns {Animal[]} - the animals that belong to the farmer
576 * @throws {Error} - Description
577 */
578 `;
579
580 (() => {
581 JavascriptParser.getReturnType(comment);
582 }).should.throw(Error);
583 });
584
585 it('should throw if there no return type', () => {
586 const comment = `
587 /**
588 * Get the Animals, but do not resolve contained relationships
589 * @query
590 * @param {String} farmerId - the email of the farmer
591 * @return - the animals that belong to the farmer
592 * @throws {Error} - Description
593 */
594 `;
595
596 (() => {
597 JavascriptParser.getReturnType(comment);
598 }).should.throw(Error);
599 });
600
601 it('should throw if there no return type name', () => {
602 const comment = `
603 /**
604 * Get the Animals, but do not resolve contained relationships
605 * @query
606 * @param {String} farmerId - the email of the farmer
607 * @return - the animals that belong to the farmer
608 * @throws {Error} - Description
609 */
610 `;
611
612 (() => {
613 JavascriptParser.getReturnType(comment);
614 }).should.throw(Error);
615 });
616 // slight concern that the codebase is doing checks that are unrequired
617 // following tests exercise this in coverage terms
618 it('Cope with different types of tag type:applications', () => {
619 const comment = `
620 /**
621 * @Something valid
622 */
623 `;
624 sandbox.stub(doctrine,'parse').returns(
625 {
626 tags:[
627 {
628 type:
629 {
630 applications:['somename']
631 }
632
633 }
634 ]
635 });
636 JavascriptParser.getReturnType(comment);
637
638 });
639 it('Cope with different types of tag type:name', () => {
640 const comment = `
641 /**
642 * @Something valid
643 */
644 `;
645 sandbox.stub(doctrine,'parse').returns(
646 {
647 tags:[
648 {
649 type:
650 {
651 name:'somename'
652 }
653
654 }
655 ]
656 });
657 JavascriptParser.getReturnType(comment);
658
659 });
660 it('Cope with different types of tag type:expression', () => {
661 const comment = `
662 /**
663 * @Something valid
664 */
665 `;
666 sandbox.stub(doctrine,'parse').returns(
667 {
668 tags:[
669 {
670 type:
671 {
672 expression:{name:'somename'}
673 }
674
675 }
676 ]
677 });
678 JavascriptParser.getReturnType(comment);
679
680 });
681 it('Cope with different types of tag type:somethingelse', () => {
682 const comment = `
683 /**
684 * @Something valid
685 */
686 `;
687 sandbox.stub(doctrine,'parse').returns(
688 {
689 tags:[
690 {
691 type:
692 {
693 wibble:{name:'wobble'}
694 }
695
696 }
697 ]
698 });
699 JavascriptParser.getReturnType(comment);
700
701 });
702 });
703
704
705 describe('#getThrows', () => {
706 let sandbox;
707
708 beforeEach(() => {
709 sandbox = sinon.createSandbox();
710 });
711
712 afterEach(() => {
713 sandbox.restore();
714 });
715 it('should return the throws tag', () => {
716 const comment = `
717 /**
718 * Get the Animals, but do not resolve contained relationships
719 * @query
720 * @param {String} farmerId - the email of the farmer
721 * @returns {Animal[]} - the animals that belong to the farmer
722 * @throws {Error} - Description
723 */
724 `;
725
726 const throws = JavascriptParser.getThrows(comment);
727 throws.should.equal('Error');
728 });
729
730 it('should throw if there is more then one throws/exception tag', () => {
731 const comment = `
732 /**
733 * Get the Animals, but do not resolve contained relationships
734 * @query
735 * @param {String} farmerId - the email of the farmer
736 * @returns {Animal[]} - the animals that belong to the farmer
737 * @throws {Error} - Description
738 * @exception {Error} - Description
739 */
740 `;
741 (() => {
742 JavascriptParser.getThrows(comment);
743 }).should.throw(Error);
744 });
745
746 it('should throw if a type isn\'t included', () => {
747 const comment = `
748 /**
749 * Get the Animals, but do not resolve contained relationships
750 * @query
751 * @param {String} farmerId - the email of the farmer
752 * @returns {Animal[]} - the animals that belong to the farmer
753 * @throws - Description
754 */
755 `;
756 (() => {
757 JavascriptParser.getThrows(comment);
758 }).should.throw(Error);
759 });
760
761 it('should throw if there is no type name', () => {
762 const comment = `
763 /**
764 * Get the Animals, but do not resolve contained relationships
765 * @query
766 * @param {String} farmerId - the email of the farmer
767 * @returns {Animal[]} - the animals that belong to the farmer
768 * @throws {} - Description
769 */`;
770
771 (() => {
772 JavascriptParser.getThrows(comment);
773 }).should.throw(Error);
774 });
775
776 // slight concern that the codebase is doing checks that are unrequired
777 // following tests exercise this in coverage terms
778 it('error if the type name / type ends up being null (somehow)', () => {
779 const comment = `
780 /**
781 * @returns {Animal[]} Something valid
782 */
783 `;
784 sandbox.stub(doctrine,'parse').returns({tags:[ {type:{none:' '} } ] });
785 (()=>{JavascriptParser.getThrows(comment);})
786 .should.throws(/Malformed JSDoc comment/);
787 });
788 });
789
790 describe('#getMethodArguments', () => {
791 let sandbox;
792
793 beforeEach(() => {
794 sandbox = sinon.createSandbox();
795 });
796
797 afterEach(() => {
798 sandbox.restore();
799 });
800
801 it('should return the correct method arguments defined in the comment', () => {
802 const comment = `
803 /**
804 * Get the Animals, but do not resolve contained relationships
805 * @query
806 * @param {String} farmerId - the email of the farmer
807 * @param {String[]} farmerTest - test @param
808 * @param {Animal[]} animalTest - test @param
809 * @returns {Animal[]} - the animals that belong to the farmer
810 */
811 `;
812
813 const argTypes = JavascriptParser.getMethodArguments(comment);
814
815 argTypes.should.deep.equal(['String', 'String[]', 'Animal[]']);
816 });
817
818 it('should return the correct method argument defined in the comment', () => {
819 const comment = `
820 /**
821 * Get the Animals, but do not resolve contained relationships
822 * @query
823 * @param {String} farmerId - the email of the farmer
824 * @returns {Animal[]} - the animals that belong to the farmer
825 */
826 `;
827
828 const argTypes = JavascriptParser.getMethodArguments(comment);
829
830 argTypes.should.deep.equal(['String']);
831 });
832
833 it('throws an error if type name contains a space', () => {
834 const comment = `
835 /**
836 * Get the Animals, but do not resolve contained relationships
837 * @query
838 * @param {Silly String} farmerId - the email of the farmer
839 * @returns {Animal[]} - the animals that belong to the farmer
840 */
841 `;
842
843 (() => {
844 JavascriptParser.getMethodArguments(comment);
845 }).should.throw(Error);
846 });
847
848 it('throws an error if there is no closing curly brace', () => {
849 const comment = `
850 /**
851 * Get the Animals, but do not resolve contained relationships
852 * @query
853 * @param {String farmerId - the email of the farmer
854 * @returns {Animal[]} - the animals that belong to the farmer
855 */
856 `;
857
858 (() => {
859 JavascriptParser.getMethodArguments(comment);
860 }).should.throw(Error);
861 });
862
863 it('throws an error if there is a random }', () => {
864 const comment = `
865 /**
866 * Get the Animals, but do not resolve contained relationships
867 * @query
868 * @param {String} farmerId - }the email of the farmer
869 * @returns {Animal[]} - the animals that belong to the farmer
870 */
871 `;
872
873 (() => {
874 JavascriptParser.getMethodArguments(comment);
875 }).should.throw(Error);
876 });
877
878
879 it ('doesn\'t throw an error if no description is given', () => {
880 const comment = `
881 /**
882 * Get the Animals, but do not resolve contained relationships
883 * @query
884 * @param {String} farmerId
885 * @returns {Animal[]}
886 */
887 `;
888
889 JavascriptParser.getMethodArguments(comment);
890 });
891
892 // slight concern that the codebase is doing checks that are unrequired
893 // following tests exercise this in coverage terms
894 it('error if the type name ends up being null (somehow)', () => {
895 const comment = `
896 /**
897 * @returns {Animal[]} Something valid
898 */
899 `;
900 sandbox.stub(doctrine,'parse').returns({tags:[ {type:{name:' '} } ] });
901 (()=>{JavascriptParser.getMethodArguments(comment);})
902 .should.throws(/Malformed JSDoc comment/);
903 });
904
905 it('Cope with different types of tag type', () => {
906 const comment = `
907 /**
908 * @returns {Animal[]} Something valid
909 */
910 `;
911 sandbox.stub(doctrine,'parse').returns(
912 {
913 tags:[
914 {
915 type:
916 {
917 applications:['somename']
918 }
919
920 },
921 {
922 type:
923 {
924 expression: {name:'somename'}
925 }
926
927 },
928 {
929 type:
930 {
931 wibble: {name:'somename'}
932 }
933
934 }
935 ]
936 });
937 JavascriptParser.getMethodArguments(comment);
938
939 });
940 });
941
942 describe('#getExample', () => {
943 it('should return the example in the jsdoc', () => {
944 const comment = `
945 /**
946 * Get the Animals, but do not resolve contained relationships
947 * @query
948 * @example
949 * let test = 'test';
950 * return test;
951 * @param {String} farmerId - the email of the farmer
952 * @returns {Animal[]} - the animals that belong to the farmer
953 */
954 `;
955
956 const example = JavascriptParser.getExample(comment);
957
958 example.should.equal('let test = \'test\';\nreturn test;');
959 });
960
961 // test excluded as the new examples in the doc using async await are not correctly
962 // handled
963 xit('should throw an error if the javascript syntax aren\'t valid', () => {
964 const comment = `
965 /**
966 * Get the Animals, but do not resolve contained relationships
967 * @query
968 * @example
969 * let test != 'test';
970 * return test;
971 * @param {String} farmerId - the email of the farmer
972 * @returns {Animal[]} - the animals that belong to the farmer
973 */
974 `;
975
976 (() => {
977 JavascriptParser.getExample(comment);
978 }).should.throw(Error);
979 });
980 });
981
982});