Best JavaScript code snippet using playwright-internal
parse.tag.doctrine.js
Source:parse.tag.doctrine.js  
...42    });43  });44  describe('parse', () => {45    it('alias', () => {46      let res = comments.parseComment('/** @alias */', {47        unwrap: true48      });49      assert.equal(res.tags.length, 0);50    });51    it('alias with name', () => {52      let res = comments.parseComment('/** @alias aliasName */', {53        unwrap: true54      });55      assert.equal(res.tags.length, 1);56      assert(hasProperty(res.tags[0], 'title', 'alias'));57      assert(hasProperty(res.tags[0], 'name', 'aliasName'));58    });59    it('alias with namepath', () => {60      let res = comments.parseComment('/** @alias aliasName.OK */', {61        unwrap: true62      });63      assert.equal(res.tags.length, 1);64      assert(hasProperty(res.tags[0], 'title', 'alias'));65      assert(hasProperty(res.tags[0], 'name', 'aliasName.OK'));66    });67    it('alias with namepath', () => {68      let res = comments.parseComment('/** @alias module:mymodule/mymodule.init */', {69        unwrap: true70      });71      assert.equal(res.tags.length, 1);72      assert(hasProperty(res.tags[0], 'title', 'alias'));73      assert(hasProperty(res.tags[0], 'name', 'module:mymodule/mymodule.init'));74    });75    it('alias with namepath with hyphen in it', () => {76      let res = comments.parseComment('/** @alias module:mymodule/my-module */', {77        unwrap: true78      });79      assert.equal(res.tags.length, 1);80      assert(hasProperty(res.tags[0], 'title', 'alias'));81      assert(hasProperty(res.tags[0], 'name', 'module:mymodule/my-module'));82    });83    it('const', () => {84      let res = comments.parseComment('/** @const */', {85        unwrap: true86      });87      assert.equal(res.tags.length, 1);88      assert(hasProperty(res.tags[0], 'title', 'const'));89    });90    it('const with name', () => {91      let res = comments.parseComment('/** @const constname */', {92        unwrap: true93      });94      assert.equal(res.tags.length, 1);95      assert(hasProperty(res.tags[0], 'title', 'const'));96      assert(hasProperty(res.tags[0], 'name', 'constname'));97    });98    it('constant with name', () => {99      let res = comments.parseComment('/** @constant constname */', {100        unwrap: true101      });102      assert.equal(res.tags.length, 1);103      assert(hasProperty(res.tags[0], 'title', 'constant'));104      assert(hasProperty(res.tags[0], 'name', 'constname'));105    });106    it('const with type and name', () => {107      let res = comments.parseComment('/** @const {String} constname */', {108        unwrap: true109      });110      assert.equal(res.tags.length, 1);111      assert(hasProperty(res.tags[0], 'title', 'const'));112      assert(hasProperty(res.tags[0], 'name', 'constname'));113      assert(hasProperty(res.tags[0], 'type'));114      assert.deepEqual(res.tags[0].type, {115        type: 'NameExpression',116        name: 'String'117      });118    });119    it('Const with type and name', () => {120      let res = comments.parseComment('/** @Const {String} constname */', {121        unwrap: true122      });123      assert.equal(res.tags.length, 1);124      assert(hasProperty(res.tags[0], 'title', 'Const'));125      assert(hasProperty(res.tags[0], 'name', 'constname'));126      assert(hasProperty(res.tags[0], 'type'));127      assert.deepEqual(res.tags[0].type, {128        type: 'NameExpression',129        name: 'String'130      });131    });132    it('constant with type and name', () => {133      let res = comments.parseComment('/** @constant {String} constname */', {134        unwrap: true135      });136      assert.equal(res.tags.length, 1);137      assert(hasProperty(res.tags[0], 'title', 'constant'));138      assert(hasProperty(res.tags[0], 'name', 'constname'));139      assert(hasProperty(res.tags[0], 'type'));140      assert.deepEqual(res.tags[0].type, {141        type: 'NameExpression',142        name: 'String'143      });144    });145    it('const multiple', () => {146      let res = comments.parseComment('/**@const\n @const*/', {147        unwrap: true148      });149      assert.equal(res.tags.length, 2);150      assert(hasProperty(res.tags[0], 'title', 'const'));151      assert(hasProperty(res.tags[1], 'title', 'const'));152    });153    it('const double', () => {154      let res = comments.parseComment('/**@const\n @const*/', {155        unwrap: true156      });157      assert.equal(res.tags.length, 2);158      assert(hasProperty(res.tags[0], 'title', 'const'));159      assert(hasProperty(res.tags[1], 'title', 'const'));160    });161    it('const triple', () => {162      let res = comments.parseComment(163        ['/**', ' * @const @const', ' * @const @const', ' * @const @const', ' */'].join('\n'),164        {165          unwrap: true166        }167      );168      assert.equal(res.tags.length, 3);169      assert(hasProperty(res.tags[0], 'title', 'const'));170      assert(hasProperty(res.tags[1], 'title', 'const'));171      assert(hasProperty(res.tags[2], 'title', 'const'));172    });173    it('constructor', () => {174      let res = comments.parseComment('/** @constructor */', {175        unwrap: true176      });177      assert.equal(res.tags.length, 1);178      assert(hasProperty(res.tags[0], 'title', 'constructor'));179    });180    it('constructor with type', () => {181      let res = comments.parseComment('/** @constructor {Object} */', {182        unwrap: true183      });184      assert.equal(res.tags.length, 1);185      assert(hasProperty(res.tags[0], 'title', 'constructor'));186      assert.deepEqual(res.tags[0].type, {187        type: 'NameExpression',188        name: 'Object'189      });190    });191    it('constructor with type and name', () => {192      let res = comments.parseComment('/** @constructor {Object} objName */', {193        unwrap: true194      });195      assert.equal(res.tags.length, 1);196      assert(hasProperty(res.tags[0], 'title', 'constructor'));197      assert(hasProperty(res.tags[0], 'name', 'objName'));198      assert.deepEqual(res.tags[0].type, {199        type: 'NameExpression',200        name: 'Object'201      });202    });203    it('class', () => {204      let res = comments.parseComment('/** @class */', {205        unwrap: true206      });207      assert.equal(res.tags.length, 1);208      assert(hasProperty(res.tags[0], 'title', 'class'));209    });210    it('class with type', () => {211      let res = comments.parseComment('/** @class {Object} */', {212        unwrap: true213      });214      assert.equal(res.tags.length, 1);215      assert(hasProperty(res.tags[0], 'title', 'class'));216      assert.deepEqual(res.tags[0].type, {217        type: 'NameExpression',218        name: 'Object'219      });220    });221    it('class with type and name', () => {222      let res = comments.parseComment('/** @class {Object} objName */', {223        unwrap: true224      });225      assert.equal(res.tags.length, 1);226      assert(hasProperty(res.tags[0], 'title', 'class'));227      assert(hasProperty(res.tags[0], 'name', 'objName'));228      assert.deepEqual(res.tags[0].type, {229        type: 'NameExpression',230        name: 'Object'231      });232    });233    it('deprecated', () => {234      let res = comments.parseComment('/** @deprecated */', {235        unwrap: true236      });237      assert.equal(res.tags.length, 1);238      assert(hasProperty(res.tags[0], 'title', 'deprecated'));239    });240    it('deprecated', () => {241      let res = comments.parseComment('/** @deprecated some text here describing why it is deprecated */', {242        unwrap: true243      });244      assert.equal(res.tags.length, 1);245      assert(hasProperty(res.tags[0], 'title', 'deprecated'));246      assert(hasProperty(res.tags[0], 'description', 'some text here describing why it is deprecated'));247    });248    it('func', () => {249      let res = comments.parseComment('/** @func */', {250        unwrap: true251      });252      assert.equal(res.tags.length, 1);253      assert(hasProperty(res.tags[0], 'title', 'func'));254    });255    it('func with name', () => {256      let res = comments.parseComment('/** @func thingName.func */', {257        unwrap: true258      });259      assert.equal(res.tags.length, 1);260      assert(hasProperty(res.tags[0], 'title', 'func'));261      assert(hasProperty(res.tags[0], 'name', 'thingName.func'));262    });263    it('func with type', () => {264      let res = comments.parseComment('/** @func {Object} thingName.func */', {265        unwrap: true266      });267      assert.equal(res.tags.length, 0);268      // func does not accept type269    });270    it('function', () => {271      let res = comments.parseComment('/** @function */', {272        unwrap: true273      });274      assert.equal(res.tags.length, 1);275      assert(hasProperty(res.tags[0], 'title', 'function'));276    });277    it('function with name', () => {278      let res = comments.parseComment('/** @function thingName.function */', {279        unwrap: true280      });281      assert.equal(res.tags.length, 1);282      assert(hasProperty(res.tags[0], 'title', 'function'));283      assert(hasProperty(res.tags[0], 'name', 'thingName.function'));284    });285    it('function with type', () => {286      let res = comments.parseComment('/** @function {Object} thingName.function */', {287        unwrap: true288      });289      assert.equal(res.tags.length, 0);290      // function does not accept type291    });292    it('member', () => {293      let res = comments.parseComment('/** @member */', {294        unwrap: true295      });296      assert.equal(res.tags.length, 1);297      assert(hasProperty(res.tags[0], 'title', 'member'));298    });299    it('member with name', () => {300      let res = comments.parseComment('/** @member thingName.name */', {301        unwrap: true302      });303      assert.equal(res.tags.length, 1);304      assert(hasProperty(res.tags[0], 'title', 'member'));305      assert(hasProperty(res.tags[0], 'name', 'thingName.name'));306    });307    it('member with type', () => {308      let res = comments.parseComment('/** @member {Object} thingName.name */', {309        unwrap: true310      });311      assert.equal(res.tags.length, 1);312      assert(hasProperty(res.tags[0], 'title', 'member'));313      assert(hasProperty(res.tags[0], 'name', 'thingName.name'));314      assert(hasProperty(res.tags[0], 'type'));315      assert.deepEqual(res.tags[0].type, {316        type: 'NameExpression',317        name: 'Object'318      });319    });320    it('method', () => {321      let res = comments.parseComment('/** @method */', {322        unwrap: true323      });324      assert.equal(res.tags.length, 1);325      assert(hasProperty(res.tags[0], 'title', 'method'));326    });327    it('method with name', () => {328      let res = comments.parseComment('/** @method thingName.function */', {329        unwrap: true330      });331      assert.equal(res.tags.length, 1);332      assert(hasProperty(res.tags[0], 'title', 'method'));333      assert(hasProperty(res.tags[0], 'name', 'thingName.function'));334    });335    it('method with type', () => {336      let res = comments.parseComment('/** @method {Object} thingName.function */', {337        unwrap: true338      });339      assert.equal(res.tags.length, 0);340      // method does not accept type341    });342    it('mixes', () => {343      let res = comments.parseComment('/** @mixes */', {344        unwrap: true345      });346      assert.equal(res.tags.length, 0);347    });348    it('mixes with name', () => {349      let res = comments.parseComment('/** @mixes thingName */', {350        unwrap: true351      });352      assert.equal(res.tags.length, 1);353      assert(hasProperty(res.tags[0], 'title', 'mixes'));354      assert(hasProperty(res.tags[0], 'name', 'thingName'));355    });356    it('mixes with namepath', () => {357      let res = comments.parseComment('/** @mixes thingName.name */', {358        unwrap: true359      });360      assert.equal(res.tags.length, 1);361      assert(hasProperty(res.tags[0], 'title', 'mixes'));362      assert(hasProperty(res.tags[0], 'name', 'thingName.name'));363    });364    it('mixin', () => {365      let res = comments.parseComment('/** @mixin */', {366        unwrap: true367      });368      assert.equal(res.tags.length, 1);369      assert(hasProperty(res.tags[0], 'title', 'mixin'));370    });371    it('mixin with name', () => {372      let res = comments.parseComment('/** @mixin thingName */', {373        unwrap: true374      });375      assert.equal(res.tags.length, 1);376      assert(hasProperty(res.tags[0], 'title', 'mixin'));377      assert(hasProperty(res.tags[0], 'name', 'thingName'));378    });379    it('mixin with namepath', () => {380      let res = comments.parseComment('/** @mixin thingName.name */', {381        unwrap: true382      });383      assert.equal(res.tags.length, 1);384      assert(hasProperty(res.tags[0], 'title', 'mixin'));385      assert(hasProperty(res.tags[0], 'name', 'thingName.name'));386    });387    it('module', () => {388      let res = comments.parseComment('/** @module */', {389        unwrap: true390      });391      assert.equal(res.tags.length, 1);392      assert(hasProperty(res.tags[0], 'title', 'module'));393    });394    it('module with name', () => {395      let res = comments.parseComment('/** @module thingName.name */', {396        unwrap: true397      });398      assert.equal(res.tags.length, 1);399      assert(hasProperty(res.tags[0], 'title', 'module'));400      assert(hasProperty(res.tags[0], 'name', 'thingName.name'));401    });402    it('module with name that has a hyphen in it', () => {403      let res = comments.parseComment('/** @module thingName-name */', {404        unwrap: true405      });406      assert.equal(res.tags.length, 1);407      assert(hasProperty(res.tags[0], 'title', 'module'));408      assert(hasProperty(res.tags[0], 'name', 'thingName-name'));409    });410    it('module with type', () => {411      let res = comments.parseComment('/** @module {Object} thingName.name */', {412        unwrap: true413      });414      assert.equal(res.tags.length, 1);415      assert(hasProperty(res.tags[0], 'title', 'module'));416      assert(hasProperty(res.tags[0], 'name', 'thingName.name'));417      assert(hasProperty(res.tags[0], 'type'));418      assert.deepEqual(res.tags[0].type, {419        type: 'NameExpression',420        name: 'Object'421      });422    });423    it('module with path', () => {424      let res = comments.parseComment('/** @module path/to/thingName.name */', {425        unwrap: true426      });427      assert.equal(res.tags.length, 1);428      assert(hasProperty(res.tags[0], 'title', 'module'));429      assert(hasProperty(res.tags[0], 'name', 'path/to/thingName.name'));430    });431    it('name', () => {432      let res = comments.parseComment('/** @name thingName.name */', {433        unwrap: true434      });435      assert.equal(res.tags.length, 1);436      assert(hasProperty(res.tags[0], 'title', 'name'));437      assert(hasProperty(res.tags[0], 'name', 'thingName.name'));438    });439    it('name', () => {440      let res = comments.parseComment('/** @name thingName#name */', {441        unwrap: true442      });443      assert.equal(res.tags.length, 1);444      assert(hasProperty(res.tags[0], 'title', 'name'));445      assert(hasProperty(res.tags[0], 'name', 'thingName#name'));446    });447    it('name', () => {448      let res = comments.parseComment('/** @name thingName~name */', {449        unwrap: true450      });451      assert.equal(res.tags.length, 1);452      assert(hasProperty(res.tags[0], 'title', 'name'));453      assert(hasProperty(res.tags[0], 'name', 'thingName~name'));454    });455    it('name', () => {456      let res = comments.parseComment('/** @name {thing} thingName.name */', {457        unwrap: true458      });459      // name does not accept type460      assert.equal(res.tags.length, 0);461    });462    it('namespace', () => {463      let res = comments.parseComment('/** @namespace */', {464        unwrap: true465      });466      assert.equal(res.tags.length, 1);467      assert(hasProperty(res.tags[0], 'title', 'namespace'));468    });469    it('namespace with name', () => {470      let res = comments.parseComment('/** @namespace thingName.name */', {471        unwrap: true472      });473      assert.equal(res.tags.length, 1);474      assert(hasProperty(res.tags[0], 'title', 'namespace'));475      assert(hasProperty(res.tags[0], 'name', 'thingName.name'));476    });477    it('namespace with type', () => {478      let res = comments.parseComment('/** @namespace {Object} thingName.name */', {479        unwrap: true480      });481      assert.equal(res.tags.length, 1);482      assert(hasProperty(res.tags[0], 'title', 'namespace'));483      assert(hasProperty(res.tags[0], 'name', 'thingName.name'));484      assert(hasProperty(res.tags[0], 'type'));485      assert.deepEqual(res.tags[0].type, {486        type: 'NameExpression',487        name: 'Object'488      });489    });490    it('param', () => {491      let res = comments.parseComment(['/**', ' * @param {String} userName', '*/'].join('\n'), {492        unwrap: true493      });494      assert.equal(res.tags.length, 1);495      assert(hasProperty(res.tags[0], 'title', 'param'));496      assert(hasProperty(res.tags[0], 'name', 'userName'));497      assert(hasProperty(res.tags[0], 'type'));498      assert.deepEqual(res.tags[0].type, {499        type: 'NameExpression',500        name: 'String'501      });502    });503    it('param with properties', () => {504      let res = comments.parseComment(['/**', ' * @param {String} user.name', '*/'].join('\n'), {505        unwrap: true506      });507      assert.equal(res.tags.length, 1);508      assert(hasProperty(res.tags[0], 'title', 'param'));509      assert(hasProperty(res.tags[0], 'name', 'user.name'));510      assert(hasProperty(res.tags[0], 'type'));511      assert.deepEqual(res.tags[0].type, {512        type: 'NameExpression',513        name: 'String'514      });515    });516    it('param with properties with description', () => {517      let res = comments.parseComment(['/**', ' * @param {String} user.name - hi', '*/'].join('\n'), {518        unwrap: true519      });520      assert.equal(res.tags.length, 1);521      assert(hasProperty(res.tags[0], 'title', 'param'));522      assert(hasProperty(res.tags[0], 'name', 'user.name'));523      assert(hasProperty(res.tags[0], 'description', 'hi'));524      assert(hasProperty(res.tags[0], 'type'));525      assert.deepEqual(res.tags[0].type, {526        type: 'NameExpression',527        name: 'String'528      });529    });530    it('param with array properties with description', () => {531      let res = comments.parseComment(['/**', ' * @param {string} employee[].name - hi', ' */'].join('\n'), {532        unwrap: true533      });534      assert.equal(res.tags.length, 1);535      assert(hasProperty(res.tags[0], 'title', 'param'));536      assert(hasProperty(res.tags[0], 'name', 'employee[].name'));537      assert(hasProperty(res.tags[0], 'description', 'hi'));538      assert(hasProperty(res.tags[0], 'type'));539      assert.deepEqual(res.tags[0].type, {540        type: 'NameExpression',541        name: 'string'542      });543    });544    it('param with array properties without description', () => {545      let res = comments.parseComment(['/**', ' * @param {string} employee[].name', ' */'].join('\n'), {546        unwrap: true547      });548      assert.equal(res.tags.length, 1);549      assert(hasProperty(res.tags[0], 'title', 'param'));550      assert(hasProperty(res.tags[0], 'name', 'employee[].name'));551      assert(hasProperty(res.tags[0], 'description', null));552      assert(hasProperty(res.tags[0], 'type'));553      assert.deepEqual(res.tags[0].type, {554        type: 'NameExpression',555        name: 'string'556      });557    });558    it('arg with properties', () => {559      let res = comments.parseComment(['/**', ' * @arg {String} user.name', '*/'].join('\n'), {560        unwrap: true561      });562      assert.equal(res.tags.length, 1);563      assert(hasProperty(res.tags[0], 'title', 'arg'));564      assert(hasProperty(res.tags[0], 'name', 'user.name'));565      assert(hasProperty(res.tags[0], 'type'));566      assert.deepEqual(res.tags[0].type, {567        type: 'NameExpression',568        name: 'String'569      });570    });571    it('argument with properties', () => {572      let res = comments.parseComment(['/**', ' * @argument {String} user.name', '*/'].join('\n'), {573        unwrap: true574      });575      assert.equal(res.tags.length, 1);576      assert(hasProperty(res.tags[0], 'title', 'argument'));577      assert(hasProperty(res.tags[0], 'name', 'user.name'));578      assert(hasProperty(res.tags[0], 'type'));579      assert.deepEqual(res.tags[0].type, {580        type: 'NameExpression',581        name: 'String'582      });583    });584    it('param typeless', () => {585      let res = comments.parseComment(['/**', ' * @param something [bye] hi', '*/'].join('\n'), {586        unwrap: true,587        sloppy: true588      });589      assert.equal(res.tags.length, 1);590      assert.deepEqual(res.tags[0], {591        title: 'param',592        type: undefined,593        name: 'something',594        description: '[bye] hi'595      });596      res = comments.parseComment(['/**', ' * @param userName', '*/'].join('\n'), {597        unwrap: true598      });599      assert.equal(res.tags.length, 1);600      assert.deepEqual(res.tags[0], {601        title: 'param',602        type: null,603        name: 'userName',604        description: null605      });606      res = comments.parseComment(['/**', ' * @param userName Something descriptive', '*/'].join('\n'), {607        unwrap: true608      });609      assert.equal(res.tags.length, 1);610      assert.deepEqual(res.tags[0], {611        title: 'param',612        type: null,613        name: 'userName',614        description: 'Something descriptive'615      });616      res = comments.parseComment(['/**', ' * @param user.name Something descriptive', '*/'].join('\n'), {617        unwrap: true618      });619      assert.equal(res.tags.length, 1);620      assert.deepEqual(res.tags[0], {621        title: 'param',622        type: null,623        name: 'user.name',624        description: 'Something descriptive'625      });626    });627    it('param broken', () => {628      let res = comments.parseComment(629        ['/**', ' * @param {String} userName', ' * @param {String userName', '*/'].join('\n'),630        {631          unwrap: true632        }633      );634      assert.equal(res.tags.length, 1);635      assert(hasProperty(res.tags[0], 'title', 'param'));636      assert(hasProperty(res.tags[0], 'name', 'userName'));637      assert(hasProperty(res.tags[0], 'type'));638      assert.deepEqual(res.tags[0].type, {639        type: 'NameExpression',640        name: 'String'641      });642    });643    it('param record', () => {644      let res = comments.parseComment(['/**', ' * @param {{ok:String}} userName', '*/'].join('\n'), {645        unwrap: true646      });647      assert.equal(res.tags.length, 1);648      assert(hasProperty(res.tags[0], 'title', 'param'));649      assert(hasProperty(res.tags[0], 'name', 'userName'));650      assert(hasProperty(res.tags[0], 'type'));651      assert.deepEqual(res.tags[0].type, {652        type: 'RecordType',653        fields: [654          {655            type: 'FieldType',656            key: 'ok',657            value: {658              type: 'NameExpression',659              name: 'String'660            }661          }662        ]663      });664    });665    it('param record broken', () => {666      let res = comments.parseComment(['/**', ' * @param {{ok:String} userName', '*/'].join('\n'), {667        unwrap: true668      });669      assert.equal(res.tags.length, 0);670    });671    it('param multiple lines', () => {672      let res = comments.parseComment(673        ['/**', ' * @param {string|', ' *     number} userName', ' * }}', '*/'].join('\n'),674        {675          unwrap: true676        }677      );678      assert.equal(res.tags.length, 1);679      assert(hasProperty(res.tags[0], 'title', 'param'));680      assert(hasProperty(res.tags[0], 'name', 'userName'));681      assert(hasProperty(res.tags[0], 'type'));682      assert.deepEqual(res.tags[0].type, {683        type: 'UnionType',684        elements: [685          {686            type: 'NameExpression',687            name: 'string'688          },689          {690            type: 'NameExpression',691            name: 'number'692          }693        ]694      });695    });696    it('param without braces', () => {697      let res = comments.parseComment(['/**', ' * @param string name description', '*/'].join('\n'), {698        unwrap: true699      });700      assert.equal(res.tags.length, 1);701      assert(hasProperty(res.tags[0], 'title', 'param'));702      assert(hasProperty(res.tags[0], 'name', 'string'));703      assert(hasProperty(res.tags[0], 'type', null));704      assert(hasProperty(res.tags[0], 'description', 'name description'));705    });706    it('param w/ hyphen before description', () => {707      let res = comments.parseComment(['/**', ' * @param {string} name - description', '*/'].join('\n'), {708        unwrap: true709      });710      assert.equal(res.tags.length, 1);711      assert.deepEqual(res.tags[0], {712        title: 'param',713        type: {714          type: 'NameExpression',715          name: 'string'716        },717        name: 'name',718        description: 'description'719      });720    });721    it('param w/ hyphen + leading space before description', () => {722      let res = comments.parseComment(['/**', ' * @param {string} name -   description', '*/'].join('\n'), {723        unwrap: true724      });725      assert.equal(res.tags.length, 1);726      assert.deepEqual(res.tags[0], {727        title: 'param',728        type: {729          type: 'NameExpression',730          name: 'string'731        },732        name: 'name',733        description: '  description'734      });735    });736    it('description and param separated by blank line', () => {737      let res = comments.parseComment(738        ['/**', ' * Description', ' * blah blah blah', ' *', ' * @param {string} name description', '*/'].join('\n'),739        {740          unwrap: true741        }742      );743      assert.deepEqual(res.description, 'Description\nblah blah blah');744      assert.equal(res.tags.length, 1);745      assert(hasProperty(res.tags[0], 'title', 'param'));746      assert(hasProperty(res.tags[0], 'name', 'name'));747      assert(hasProperty(res.tags[0], 'type'));748      assert.deepEqual(res.tags[0].type, {749        type: 'NameExpression',750        name: 'string'751      });752      assert(hasProperty(res.tags[0], 'description', 'description'));753    });754    it('regular block comment instead of jsdoc-style block comment', () => {755      let res = comments.parseComment(['/*', ' * Description', ' * blah blah blah', '*/'].join('\n'), {756        unwrap: true757      });758      assert.deepEqual(res.description, 'Description\nblah blah blah');759    });760    it('augments', () => {761      let res = comments.parseComment('/** @augments */', {762        unwrap: true763      });764      assert.equal(res.tags.length, 1);765    });766    it('augments with name', () => {767      let res = comments.parseComment('/** @augments ClassName */', {768        unwrap: true769      });770      assert.equal(res.tags.length, 1);771      assert(hasProperty(res.tags[0], 'title', 'augments'));772      assert(hasProperty(res.tags[0], 'name', 'ClassName'));773    });774    it('augments with type', () => {775      let res = comments.parseComment('/** @augments {ClassName} */', {776        unwrap: true777      });778      assert.equal(res.tags.length, 1);779      assert(hasProperty(res.tags[0], 'title', 'augments'));780      assert(hasProperty(res.tags[0], 'type', {781        type: 'NameExpression',782        name: 'ClassName'783      }));784    });785    it('augments with name', () => {786      let res = comments.parseComment('/** @augments ClassName.OK */', {787        unwrap: true788      });789      assert.equal(res.tags.length, 1);790      assert(hasProperty(res.tags[0], 'title', 'augments'));791      assert(hasProperty(res.tags[0], 'name', 'ClassName.OK'));792    });793    it('extends', () => {794      let res = comments.parseComment('/** @extends */', {795        unwrap: true796      });797      assert.equal(res.tags.length, 1);798    });799    it('extends with name', () => {800      let res = comments.parseComment('/** @extends ClassName */', {801        unwrap: true802      });803      assert.equal(res.tags.length, 1);804      assert(hasProperty(res.tags[0], 'title', 'extends'));805      assert(hasProperty(res.tags[0], 'name', 'ClassName'));806    });807    it('extends with type', () => {808      let res = comments.parseComment('/** @extends {ClassName} */', {809        unwrap: true810      });811      assert.equal(res.tags.length, 1);812      assert(hasProperty(res.tags[0], 'title', 'extends'));813      assert(hasProperty(res.tags[0], 'type', {814        type: 'NameExpression',815        name: 'ClassName'816      }));817    });818    it('extends with namepath', () => {819      let res = comments.parseComment('/** @extends ClassName.OK */', {820        unwrap: true821      });822      assert.equal(res.tags.length, 1);823      assert(hasProperty(res.tags[0], 'title', 'extends'));824      assert(hasProperty(res.tags[0], 'name', 'ClassName.OK'));825    });826    it('extends with namepath', () => {827      let res = comments.parseComment('/** @extends module:path/ClassName~OK */', {828        unwrap: true829      });830      assert.equal(res.tags.length, 1);831      assert(hasProperty(res.tags[0], 'title', 'extends'));832      assert(hasProperty(res.tags[0], 'name', 'module:path/ClassName~OK'));833    });834    it('prop', () => {835      let res = comments.parseComment(['/**', ' * @prop {string} thingName - does some stuff', '*/'].join('\n'), {836        unwrap: true837      });838      assert.equal(res.tags.length, 1);839      assert(hasProperty(res.tags[0], 'title', 'prop'));840      assert(hasProperty(res.tags[0], 'description', 'does some stuff'));841      assert(hasProperty(res.tags[0].type, 'name', 'string'));842      assert(hasProperty(res.tags[0], 'name', 'thingName'));843    });844    it('prop without type', () => {845      let res = comments.parseComment(['/**', ' * @prop thingName - does some stuff', '*/'].join('\n'), {846        unwrap: true847      });848      assert.equal(res.tags.length, 0);849    });850    it('property', () => {851      let res = comments.parseComment(['/**', ' * @property {string} thingName - does some stuff', '*/'].join('\n'), {852        unwrap: true853      });854      assert.equal(res.tags.length, 1);855      assert(hasProperty(res.tags[0], 'title', 'property'));856      assert(hasProperty(res.tags[0], 'description', 'does some stuff'));857      assert(hasProperty(res.tags[0].type, 'name', 'string'));858      assert(hasProperty(res.tags[0], 'name', 'thingName'));859    });860    it('property without type', () => {861      let res = comments.parseComment(['/**', ' * @property thingName - does some stuff', '*/'].join('\n'), {862        unwrap: true863      });864      assert.equal(res.tags.length, 0);865    });866    it('property with optional type', () => {867      let res = comments.parseComment(868        ['/**', '* testtypedef', '* @typedef {object} abc', '* @property {String} [val] value description', '*/'].join(869          '\n'870        ),871        {872          unwrap: true,873          sloppy: true874        }875      );876      assert(hasProperty(res.tags[1], 'title', 'property'));877      assert(hasProperty(res.tags[1], 'type'));878      assert(hasProperty(res.tags[1]['type'], 'type', 'OptionalType'));879    });880    it('property with nested name', () => {881      let res = comments.parseComment(882        ['/**', ' * @property {string} thingName.name - does some stuff', '*/'].join('\n'),883        {884          unwrap: true885        }886      );887      assert.equal(res.tags.length, 1);888      assert(hasProperty(res.tags[0], 'title', 'property'));889      assert(hasProperty(res.tags[0], 'description', 'does some stuff'));890      assert(hasProperty(res.tags[0].type, 'name', 'string'));891      assert(hasProperty(res.tags[0], 'name', 'thingName.name'));892    });893    it('throws', () => {894      let res = comments.parseComment(['/**', ' * @throws {Error} if something goes wrong', ' */'].join('\n'), {895        unwrap: true896      });897      assert.equal(res.tags.length, 1);898      assert(hasProperty(res.tags[0], 'title', 'throws'));899      assert(hasProperty(res.tags[0], 'description', 'if something goes wrong'));900      assert(hasProperty(res.tags[0].type, 'name', 'Error'));901    });902    it('throws without type', () => {903      let res = comments.parseComment(['/**', ' * @throws if something goes wrong', ' */'].join('\n'), {904        unwrap: true905      });906      assert.equal(res.tags.length, 1);907      assert(hasProperty(res.tags[0], 'title', 'throws'));908      assert(hasProperty(res.tags[0], 'description', 'if something goes wrong'));909    });910    it('kind', () => {911      let res = comments.parseComment('/** @kind class */', {912        unwrap: true913      });914      assert.equal(res.tags.length, 1);915      assert(hasProperty(res.tags[0], 'title', 'kind'));916      assert(hasProperty(res.tags[0], 'kind', 'class'));917    });918    it('kind error', () => {919      let res = comments.parseComment('/** @kind ng */', {920        unwrap: true,921        recoverable: true922      });923      assert.equal(res.tags.length, 1);924      assert(hasProperty(res.tags[0], 'errors'));925      assert.equal(res.tags[0].errors.length, 1);926      assert.equal(res.tags[0].errors[0], "Invalid kind name 'ng'");927    });928    it('todo', () => {929      let res = comments.parseComment('/** @todo Write the documentation */', {930        unwrap: true931      });932      assert.equal(res.tags.length, 1);933      assert(hasProperty(res.tags[0], 'title', 'todo'));934      assert(hasProperty(res.tags[0], 'description', 'Write the documentation'));935    });936    it('typedef', () => {937      let res = comments.parseComment('/** @typedef {Object} NumberLike */', {938        unwrap: true939      });940      assert.equal(res.tags.length, 1);941      assert(hasProperty(res.tags[0], 'type'));942      assert.deepEqual(res.tags[0].type, {943        type: 'NameExpression',944        name: 'Object'945      });946      assert(hasProperty(res.tags[0], 'name', 'NumberLike'));947    });948    it('summary', () => {949      // japanese lang950      let res = comments.parseComment('/** @summary ãããã3æããã§ã¨ã¼ */', {951        unwrap: true952      });953      assert.equal(res.tags.length, 1);954      assert(hasProperty(res.tags[0], 'title', 'summary'));955      assert(hasProperty(res.tags[0], 'description', 'ãããã3æããã§ã¨ã¼'));956    });957    it('variation', () => {958      let res = comments.parseComment('/** @variation 42 */', {959        unwrap: true960      });961      assert.equal(res.tags.length, 1);962      assert(hasProperty(res.tags[0], 'title', 'variation'));963      assert(hasProperty(res.tags[0], 'variation', 42));964    });965    it('variation error', () => {966      let res = comments.parseComment('/** @variation Animation */', {967        unwrap: true,968        recoverable: true969      });970      assert.equal(res.tags.length, 1);971      assert(hasProperty(res.tags[0], 'errors'));972      assert.equal(res.tags[0].errors.length, 1);973      assert.equal(res.tags[0].errors[0], "Invalid variation 'Animation'");974    });975    it('access', () => {976      let res = comments.parseComment('/** @access public */', {977        unwrap: true978      });979      assert.equal(res.tags.length, 1);980      assert(hasProperty(res.tags[0], 'title', 'access'));981      assert(hasProperty(res.tags[0], 'access', 'public'));982    });983    it('access error', () => {984      let res = comments.parseComment('/** @access ng */', {985        unwrap: true,986        recoverable: true987      });988      assert.equal(res.tags.length, 1);989      assert(hasProperty(res.tags[0], 'errors'));990      assert.equal(res.tags[0].errors.length, 1);991      assert.equal(res.tags[0].errors[0], "Invalid access name 'ng'");992    });993    it('public', () => {994      let res = comments.parseComment('/** @public */', {995        unwrap: true996      });997      assert.equal(res.tags.length, 1);998      assert(hasProperty(res.tags[0], 'title', 'public'));999    });1000    it('public type and description', () => {1001      let res = comments.parseComment('/** @public {number} ok */', {1002        unwrap: true,1003        recoverable: true1004      });1005      assert.equal(res.tags.length, 1);1006      assert(hasProperty(res.tags[0], 'title', 'public'));1007      assert(hasProperty(res.tags[0], 'description', 'ok'));1008      assert(hasProperty(res.tags[0], 'type'));1009      assert.deepEqual(res.tags[0].type, {1010        type: 'NameExpression',1011        name: 'number'1012      });1013    });1014    it('protected', () => {1015      let res = comments.parseComment('/** @protected */', {1016        unwrap: true1017      });1018      assert.equal(res.tags.length, 1);1019      assert(hasProperty(res.tags[0], 'title', 'protected'));1020    });1021    it('protected type and description', () => {1022      let res = comments.parseComment('/** @protected {number} ok */', {1023        unwrap: true,1024        recoverable: true1025      });1026      assert.equal(res.tags.length, 1);1027      assert(hasProperty(res.tags[0], 'title', 'protected'));1028      assert(hasProperty(res.tags[0], 'description', 'ok'));1029      assert(hasProperty(res.tags[0], 'type'));1030      assert.deepEqual(res.tags[0].type, {1031        type: 'NameExpression',1032        name: 'number'1033      });1034    });1035    it('private', () => {1036      let res = comments.parseComment('/** @private */', {1037        unwrap: true1038      });1039      assert.equal(res.tags.length, 1);1040      assert(hasProperty(res.tags[0], 'title', 'private'));1041    });1042    it('private type and description', () => {1043      let res = comments.parseComment('/** @private {number} ok */', {1044        unwrap: true,1045        recoverable: true1046      });1047      assert.equal(res.tags.length, 1);1048      assert(hasProperty(res.tags[0], 'title', 'private'));1049      assert(hasProperty(res.tags[0], 'description', 'ok'));1050      assert(hasProperty(res.tags[0], 'type'));1051      assert.deepEqual(res.tags[0].type, {1052        type: 'NameExpression',1053        name: 'number'1054      });1055    });1056    it('readonly', () => {1057      let res = comments.parseComment('/** @readonly */', {1058        unwrap: true1059      });1060      assert.equal(res.tags.length, 1);1061      assert(hasProperty(res.tags[0], 'title', 'readonly'));1062    });1063    it('readonly error', () => {1064      let res = comments.parseComment('/** @readonly ng */', {1065        unwrap: true,1066        recoverable: true1067      });1068      assert.equal(res.tags.length, 1);1069      assert(hasProperty(res.tags[0], 'errors'));1070      assert.equal(res.tags[0].errors.length, 1);1071      assert.equal(res.tags[0].errors[0], "Unknown content 'ng'");1072    });1073    it('requires', () => {1074      let res = comments.parseComment('/** @requires */', {1075        unwrap: true1076      });1077      assert.equal(res.tags.length, 0);1078    });1079    it('requires with module name', () => {1080      let res = comments.parseComment('/** @requires name.path */', {1081        unwrap: true1082      });1083      assert.equal(res.tags.length, 1);1084      assert(hasProperty(res.tags[0], 'title', 'requires'));1085      assert(hasProperty(res.tags[0], 'name', 'name.path'));1086    });1087    it('global', () => {1088      let res = comments.parseComment('/** @global */', {1089        unwrap: true1090      });1091      assert.equal(res.tags.length, 1);1092      assert(hasProperty(res.tags[0], 'title', 'global'));1093    });1094    it('global error', () => {1095      let res = comments.parseComment('/** @global ng */', {1096        unwrap: true,1097        recoverable: true1098      });1099      assert.equal(res.tags.length, 1);1100      assert(hasProperty(res.tags[0], 'errors'));1101      assert.equal(res.tags[0].errors.length, 1);1102      assert.equal(res.tags[0].errors[0], "Unknown content 'ng'");1103    });1104    it('inner', () => {1105      let res = comments.parseComment('/** @inner */', {1106        unwrap: true1107      });1108      assert.equal(res.tags.length, 1);1109      assert(hasProperty(res.tags[0], 'title', 'inner'));1110    });1111    it('inner error', () => {1112      let res = comments.parseComment('/** @inner ng */', {1113        unwrap: true,1114        recoverable: true1115      });1116      assert.equal(res.tags.length, 1);1117      assert(hasProperty(res.tags[0], 'errors'));1118      assert.equal(res.tags[0].errors.length, 1);1119      assert.equal(res.tags[0].errors[0], "Unknown content 'ng'");1120    });1121    it('instance', () => {1122      let res = comments.parseComment('/** @instance */', {1123        unwrap: true1124      });1125      assert.equal(res.tags.length, 1);1126      assert(hasProperty(res.tags[0], 'title', 'instance'));1127    });1128    it('instance error', () => {1129      let res = comments.parseComment('/** @instance ng */', {1130        unwrap: true,1131        recoverable: true1132      });1133      assert.equal(res.tags.length, 1);1134      assert(hasProperty(res.tags[0], 'errors'));1135      assert.equal(res.tags[0].errors.length, 1);1136      assert.equal(res.tags[0].errors[0], "Unknown content 'ng'");1137    });1138    it('since', () => {1139      let res = comments.parseComment('/** @since 1.2.1 */', {1140        unwrap: true1141      });1142      assert.equal(res.tags.length, 1);1143      assert(hasProperty(res.tags[0], 'title', 'since'));1144      assert(hasProperty(res.tags[0], 'description', '1.2.1'));1145    });1146    it('static', () => {1147      let res = comments.parseComment('/** @static */', {1148        unwrap: true1149      });1150      assert.equal(res.tags.length, 1);1151      assert(hasProperty(res.tags[0], 'title', 'static'));1152    });1153    it('static error', () => {1154      let res = comments.parseComment('/** @static ng */', {1155        unwrap: true,1156        recoverable: true1157      });1158      assert.equal(res.tags.length, 1);1159      assert(hasProperty(res.tags[0], 'errors'));1160      assert.equal(res.tags[0].errors.length, 1);1161      assert.equal(res.tags[0].errors[0], "Unknown content 'ng'");1162    });1163    it('this', () => {1164      let res = comments.parseComment(['/**', ' * @this thingName', '*/'].join('\n'), {1165        unwrap: true1166      });1167      assert.equal(res.tags.length, 1);1168      assert(hasProperty(res.tags[0], 'title', 'this'));1169      assert(hasProperty(res.tags[0], 'name', 'thingName'));1170    });1171    it('this with namepath', () => {1172      let res = comments.parseComment(['/**', ' * @this thingName.name', '*/'].join('\n'), {1173        unwrap: true1174      });1175      assert.equal(res.tags.length, 1);1176      assert(hasProperty(res.tags[0], 'title', 'this'));1177      assert(hasProperty(res.tags[0], 'name', 'thingName.name'));1178    });1179    it('this with name expression', () => {1180      let res = comments.parseComment(['/**', ' * @this {thingName.name}', '*/'].join('\n'), {1181        unwrap: true1182      });1183      assert.equal(res.tags.length, 1);1184      assert(hasProperty(res.tags[0], 'title', 'this'));1185      assert(hasProperty(res.tags[0], 'name', 'thingName.name'));1186    });1187    it('this error with type application', () => {1188      let res = comments.parseComment(['/**', ' * @this {Array<string>}', '*/'].join('\n'), {1189        unwrap: true,1190        recoverable: true1191      });1192      assert.equal(res.tags.length, 1);1193      assert(hasProperty(res.tags[0], 'title', 'this'));1194      assert(hasProperty(res.tags[0], 'errors'));1195      assert.equal(res.tags[0].errors.length, 1);1196      assert.equal(res.tags[0].errors[0], 'Invalid name for this');1197    });1198    it('this error', () => {1199      let res = comments.parseComment(['/**', ' * @this', '*/'].join('\n'), {1200        unwrap: true,1201        recoverable: true1202      });1203      assert.equal(res.tags.length, 1);1204      assert(hasProperty(res.tags[0], 'title', 'this'));1205      assert(hasProperty(res.tags[0], 'errors'));1206      assert.equal(res.tags[0].errors.length, 1);1207      assert.equal(res.tags[0].errors[0], 'Missing or invalid tag name');1208    });1209    it('var', () => {1210      let res = comments.parseComment('/** @var */', {1211        unwrap: true1212      });1213      assert.equal(res.tags.length, 1);1214      assert(hasProperty(res.tags[0], 'title', 'var'));1215    });1216    it('var with name', () => {1217      let res = comments.parseComment('/** @var thingName.name */', {1218        unwrap: true1219      });1220      assert.equal(res.tags.length, 1);1221      assert(hasProperty(res.tags[0], 'title', 'var'));1222      assert(hasProperty(res.tags[0], 'name', 'thingName.name'));1223    });1224    it('var with type', () => {1225      let res = comments.parseComment('/** @var {Object} thingName.name */', {1226        unwrap: true1227      });1228      assert.equal(res.tags.length, 1);1229      assert(hasProperty(res.tags[0], 'title', 'var'));1230      assert(hasProperty(res.tags[0], 'name', 'thingName.name'));1231      assert(hasProperty(res.tags[0], 'type'));1232      assert.deepEqual(res.tags[0].type, {1233        type: 'NameExpression',1234        name: 'Object'1235      });1236    });1237    it('version', () => {1238      let res = comments.parseComment('/** @version 1.2.1 */', {1239        unwrap: true1240      });1241      assert.equal(res.tags.length, 1);1242      assert(hasProperty(res.tags[0], 'title', 'version'));1243      assert(hasProperty(res.tags[0], 'description', '1.2.1'));1244    });1245    it('incorrect name', () => {1246      let res = comments.parseComment('/** @name thingName#%name */', {1247        unwrap: true1248      });1249      // name does not accept type1250      assert.equal(res.tags.length, 0);1251      assert.deepEqual(res, {1252        description: '',1253        tags: []1254      });1255    });1256    it('string literal property', () => {1257      let res = comments.parseComment(1258        ['/**', ' * @typedef {Object} comment', " * @property {('public'|'protected'|'private')} access", '*/'].join(1259          '\n'1260        ),1261        {1262          unwrap: true1263        }1264      );1265      assert.equal(res.tags.length, 2);1266      assert(hasProperty(res.tags[1], 'title', 'property'));1267      assert(hasProperty(res.tags[1], 'name', 'access'));1268      assert(hasProperty(res.tags[1].type, 'type', 'UnionType'));1269      assert.equal(res.tags[1].type.elements.length, 3);1270      containEqual(res.tags[1].type.elements, {1271        type: 'StringLiteralType',1272        value: 'public'1273      });1274      containEqual(res.tags[1].type.elements, {1275        type: 'StringLiteralType',1276        value: 'private'1277      });1278      containEqual(res.tags[1].type.elements, {1279        type: 'StringLiteralType',1280        value: 'protected'1281      });1282    });1283    it('numeric literal property', () => {1284      let res = comments.parseComment(1285        ['/**', ' * @typedef {Object} comment', ' * @property {(-42|1.5|0)} access', '*/'].join('\n'),1286        {1287          unwrap: true1288        }1289      );1290      assert.equal(res.tags.length, 2);1291      assert(hasProperty(res.tags[1], 'title', 'property'));1292      assert(hasProperty(res.tags[1], 'name', 'access'));1293      assert(hasProperty(res.tags[1].type, 'type', 'UnionType'));1294      assert.equal(res.tags[1].type.elements.length, 3);1295      containEqual(res.tags[1].type.elements, {1296        type: 'NumericLiteralType',1297        value: -421298      });1299      containEqual(res.tags[1].type.elements, {1300        type: 'NumericLiteralType',1301        value: 1.51302      });1303      containEqual(res.tags[1].type.elements, {1304        type: 'NumericLiteralType',1305        value: 01306      });1307    });1308    it('boolean literal property', () => {1309      let res = comments.parseComment(1310        ['/**', ' * @typedef {Object} comment', ' * @property {(true|false)} access', '*/'].join('\n'),1311        {1312          unwrap: true1313        }1314      );1315      assert.equal(res.tags.length, 2);1316      assert(hasProperty(res.tags[1], 'title', 'property'));1317      assert(hasProperty(res.tags[1], 'name', 'access'));1318      assert(hasProperty(res.tags[1].type, 'type', 'UnionType'));1319      assert.equal(res.tags[1].type.elements.length, 2);1320      containEqual(res.tags[1].type.elements, {1321        type: 'BooleanLiteralType',1322        value: true1323      });1324      containEqual(res.tags[1].type.elements, {1325        type: 'BooleanLiteralType',1326        value: false1327      });1328    });1329    it('complex union with literal types', () => {1330      let res = comments.parseComment(1331        ['/**', ' * @typedef {({ok: true, data: string} | {ok: false, error: Error})} Result', '*/'].join('\n'),1332        {1333          unwrap: true1334        }1335      );1336      assert.equal(res.tags.length, 1);1337      assert(hasProperty(res.tags[0], 'title', 'typedef'));1338      assert(hasProperty(res.tags[0], 'name', 'Result'));1339      assert(hasProperty(res.tags[0].type, 'type', 'UnionType'));1340      assert.equal(res.tags[0].type.elements.length, 2);1341      var e0 = res.tags[0].type.elements[0];1342      assert(hasProperty(e0, 'type', 'RecordType'));1343      assert.equal(e0.fields.length, 2);1344      containEqual(e0.fields, {1345        type: 'FieldType',1346        key: 'ok',1347        value: {1348          type: 'BooleanLiteralType',1349          value: true1350        }1351      });1352      containEqual(e0.fields, {1353        type: 'FieldType',1354        key: 'data',1355        value: {1356          type: 'NameExpression',1357          name: 'string'1358        }1359      });1360      var e1 = res.tags[0].type.elements[1];1361      assert(hasProperty(e1, 'type', 'RecordType'));1362      assert.equal(e1.fields.length, 2);1363      containEqual(e1.fields, {1364        type: 'FieldType',1365        key: 'ok',1366        value: {1367          type: 'BooleanLiteralType',1368          value: false1369        }1370      });1371      containEqual(e1.fields, {1372        type: 'FieldType',1373        key: 'error',1374        value: {1375          type: 'NameExpression',1376          name: 'Error'1377        }1378      });1379    });1380  });1381  describe('parseType', () => {1382    it('union type closure-compiler extended', () => {1383      var type = comments.parseType('string|number');1384      assert.deepEqual(type, {1385        type: 'UnionType',1386        elements: [1387          {1388            type: 'NameExpression',1389            name: 'string'1390          },1391          {1392            type: 'NameExpression',1393            name: 'number'1394          }1395        ]1396      });1397    });1398    it('empty union type', () => {1399      var type = comments.parseType('()');1400      assert.deepEqual(type, {1401        type: 'UnionType',1402        elements: []1403      });1404    });1405    it('comma last array type', () => {1406      var type = comments.parseType('[string,]');1407      assert.deepEqual(type, {1408        type: 'ArrayType',1409        elements: [1410          {1411            type: 'NameExpression',1412            name: 'string'1413          }1414        ]1415      });1416    });1417    it('array type of all literal', () => {1418      var type = comments.parseType('[*]');1419      assert.deepEqual(type, {1420        type: 'ArrayType',1421        elements: [1422          {1423            type: 'AllLiteral'1424          }1425        ]1426      });1427    });1428    it('array type of nullable literal', () => {1429      var type = comments.parseType('[?]');1430      assert.deepEqual(type, {1431        type: 'ArrayType',1432        elements: [1433          {1434            type: 'NullableLiteral'1435          }1436        ]1437      });1438    });1439    it('comma last record type', () => {1440      var type = comments.parseType('{,}');1441      assert.deepEqual(type, {1442        type: 'RecordType',1443        fields: []1444      });1445    });1446    it('type application', () => {1447      var type = comments.parseType('Array.<String>');1448      assert.deepEqual(type, {1449        type: 'TypeApplication',1450        expression: {1451          type: 'NameExpression',1452          name: 'Array'1453        },1454        applications: [1455          {1456            type: 'NameExpression',1457            name: 'String'1458          }1459        ]1460      });1461    });1462    it('type application with NullableLiteral', () => {1463      var type = comments.parseType('Array<?>');1464      assert.deepEqual(type, {1465        type: 'TypeApplication',1466        expression: {1467          type: 'NameExpression',1468          name: 'Array'1469        },1470        applications: [1471          {1472            type: 'NullableLiteral'1473          }1474        ]1475      });1476    });1477    it('type application with multiple patterns', () => {1478      var type = comments.parseType('Array.<String, Number>');1479      assert.deepEqual(type, {1480        type: 'TypeApplication',1481        expression: {1482          type: 'NameExpression',1483          name: 'Array'1484        },1485        applications: [1486          {1487            type: 'NameExpression',1488            name: 'String'1489          },1490          {1491            type: 'NameExpression',1492            name: 'Number'1493          }1494        ]1495      });1496    });1497    it('type application without dot', () => {1498      var type = comments.parseType('Array<String>');1499      assert.deepEqual(type, {1500        type: 'TypeApplication',1501        expression: {1502          type: 'NameExpression',1503          name: 'Array'1504        },1505        applications: [1506          {1507            type: 'NameExpression',1508            name: 'String'1509          }1510        ]1511      });1512    });1513    it('array-style type application', () => {1514      var type = comments.parseType('String[]');1515      assert.deepEqual(type, {1516        type: 'TypeApplication',1517        expression: {1518          type: 'NameExpression',1519          name: 'Array'1520        },1521        applications: [1522          {1523            type: 'NameExpression',1524            name: 'String'1525          }1526        ]1527      });1528    });1529    it('function type simple', () => {1530      var type = comments.parseType('function()');1531      assert.deepEqual(type, {1532        type: 'FunctionType',1533        params: [],1534        result: null1535      });1536    });1537    it('function type with name', () => {1538      var type = comments.parseType('function(a)');1539      assert.deepEqual(type, {1540        type: 'FunctionType',1541        params: [1542          {1543            type: 'NameExpression',1544            name: 'a'1545          }1546        ],1547        result: null1548      });1549    });1550    it('function type with name and type', () => {1551      var type = comments.parseType('function(a:b)');1552      assert.deepEqual(type, {1553        type: 'FunctionType',1554        params: [1555          {1556            type: 'ParameterType',1557            name: 'a',1558            expression: {1559              type: 'NameExpression',1560              name: 'b'1561            }1562          }1563        ],1564        result: null1565      });1566    });1567    it('function type with optional param', () => {1568      var type = comments.parseType('function(a=)');1569      assert.deepEqual(type, {1570        type: 'FunctionType',1571        params: [1572          {1573            type: 'OptionalType',1574            expression: {1575              type: 'NameExpression',1576              name: 'a'1577            }1578          }1579        ],1580        result: null1581      });1582    });1583    it('function type with optional param name and type', () => {1584      var type = comments.parseType('function(a:b=)');1585      assert.deepEqual(type, {1586        type: 'FunctionType',1587        params: [1588          {1589            type: 'OptionalType',1590            expression: {1591              type: 'ParameterType',1592              name: 'a',1593              expression: {1594                type: 'NameExpression',1595                name: 'b'1596              }1597            }1598          }1599        ],1600        result: null1601      });1602    });1603    it('function type with rest param', () => {1604      var type = comments.parseType('function(...a)');1605      assert.deepEqual(type, {1606        type: 'FunctionType',1607        params: [1608          {1609            type: 'RestType',1610            expression: {1611              type: 'NameExpression',1612              name: 'a'1613            }1614          }1615        ],1616        result: null1617      });1618    });1619    it('function type with rest param name and type', () => {1620      var type = comments.parseType('function(...a:b)');1621      assert.deepEqual(type, {1622        type: 'FunctionType',1623        params: [1624          {1625            type: 'RestType',1626            expression: {1627              type: 'ParameterType',1628              name: 'a',1629              expression: {1630                type: 'NameExpression',1631                name: 'b'1632              }1633            }1634          }1635        ],1636        result: null1637      });1638    });1639    it('function type with optional rest param', () => {1640      var type = comments.parseType('function(...a=)');1641      assert.deepEqual(type, {1642        type: 'FunctionType',1643        params: [1644          {1645            type: 'RestType',1646            expression: {1647              type: 'OptionalType',1648              expression: {1649                type: 'NameExpression',1650                name: 'a'1651              }1652            }1653          }1654        ],1655        result: null1656      });1657    });1658    it('function type with optional rest param name and type', () => {1659      var type = comments.parseType('function(...a:b=)');1660      assert.deepEqual(type, {1661        type: 'FunctionType',1662        params: [1663          {1664            type: 'RestType',1665            expression: {1666              type: 'OptionalType',1667              expression: {1668                type: 'ParameterType',1669                name: 'a',1670                expression: {1671                  type: 'NameExpression',1672                  name: 'b'1673                }1674              }1675            }1676          }1677        ],1678        result: null1679      });1680    });1681    it('string value in type', () => {1682      var type;1683      type = comments.parseType("{'ok':String}");1684      assert.deepEqual(type, {1685        fields: [1686          {1687            key: 'ok',1688            type: 'FieldType',1689            value: {1690              name: 'String',1691              type: 'NameExpression'1692            }1693          }1694        ],1695        type: 'RecordType'1696      });1697      type = comments.parseType('{"\\r\\n\\t\\u2028\\x20\\u20\\b\\f\\v\\\r\n\\\n\\0\\07\\012\\o":String}');1698      assert.deepEqual(type, {1699        fields: [1700          {1701            key: '\r\n\t\u2028\x20u20\b\f\v\0\u0007\u000ao',1702            type: 'FieldType',1703            value: {1704              name: 'String',1705              type: 'NameExpression'1706            }1707          }1708        ],1709        type: 'RecordType'1710      });1711      assert.throws(() => comments.parseType('{\'ok":String}'), /unexpected quote/);1712      assert.throws(() => comments.parseType("{'o\n':String}"), /unexpected quote/);1713    });1714    it('number value in type', () => {1715      var type;1716      type = comments.parseType('{20:String}');1717      assert.deepEqual(type, {1718        fields: [1719          {1720            key: '20',1721            type: 'FieldType',1722            value: {1723              name: 'String',1724              type: 'NameExpression'1725            }1726          }1727        ],1728        type: 'RecordType'1729      });1730      type = comments.parseType('{.2:String, 30:Number, 0x20:String}');1731      assert.deepEqual(type, {1732        fields: [1733          {1734            key: '0.2',1735            type: 'FieldType',1736            value: {1737              name: 'String',1738              type: 'NameExpression'1739            }1740          },1741          {1742            key: '30',1743            type: 'FieldType',1744            value: {1745              name: 'Number',1746              type: 'NameExpression'1747            }1748          },1749          {1750            key: '32',1751            type: 'FieldType',1752            value: {1753              name: 'String',1754              type: 'NameExpression'1755            }1756          }1757        ],1758        type: 'RecordType'1759      });1760      type = comments.parseType('{0X2:String, 0:Number, 100e200:String, 10e-20:Number}');1761      assert.deepEqual(type, {1762        fields: [1763          {1764            key: '2',1765            type: 'FieldType',1766            value: {1767              name: 'String',1768              type: 'NameExpression'1769            }1770          },1771          {1772            key: '0',1773            type: 'FieldType',1774            value: {1775              name: 'Number',1776              type: 'NameExpression'1777            }1778          },1779          {1780            key: '1e+202',1781            type: 'FieldType',1782            value: {1783              name: 'String',1784              type: 'NameExpression'1785            }1786          },1787          {1788            key: '1e-19',1789            type: 'FieldType',1790            value: {1791              name: 'Number',1792              type: 'NameExpression'1793            }1794          }1795        ],1796        type: 'RecordType'1797      });1798      assert.throws(() => comments.parseType('{0x:String}'), /unexpected token/);1799      assert.throws(() => comments.parseType('{0x'), /unexpected token/);1800      assert.throws(() => comments.parseType('{0xd'), /unexpected token/);1801      assert.throws(() => comments.parseType('{0x2_:'), /unexpected token/);1802      assert.throws(() => comments.parseType('{021:'), /unexpected token/);1803      assert.throws(() => comments.parseType('{021_:'), /unexpected token/);1804      assert.throws(() => comments.parseType('{021'), /unexpected token/);1805      assert.throws(() => comments.parseType('{08'), /unexpected token/);1806      assert.throws(() => comments.parseType('{0y'), /unexpected token/);1807      assert.throws(() => comments.parseType('{0'), /unexpected token/);1808      assert.throws(() => comments.parseType('{100e2'), /unexpected token/);1809      assert.throws(() => comments.parseType('{100e-2'), /unexpected token/);1810      assert.throws(() => comments.parseType('{100e-200:'), /unexpected token/);1811      assert.throws(() => comments.parseType('{100e:'), /unexpected token/);1812      assert.throws(() => comments.parseType('function(number=, string)'), /not reach to EOF/);1813    });1814    it('dotted type', () => {1815      var type;1816      type = comments.parseType('Cocoa.Cappuccino');1817      assert.deepEqual(type, {1818        name: 'Cocoa.Cappuccino',1819        type: 'NameExpression'1820      });1821    });1822    it('rest array type', () => {1823      var type;1824      type = comments.parseType('[string,...string]');1825      assert.deepEqual(type, {1826        elements: [1827          {1828            name: 'string',1829            type: 'NameExpression'1830          },1831          {1832            expression: {1833              name: 'string',1834              type: 'NameExpression'1835            },1836            type: 'RestType'1837          }1838        ],1839        type: 'ArrayType'1840      });1841    });1842    it('nullable type', () => {1843      var type;1844      type = comments.parseType('string?');1845      assert.deepEqual(type, {1846        expression: {1847          name: 'string',1848          type: 'NameExpression'1849        },1850        prefix: false,1851        type: 'NullableType'1852      });1853    });1854    it('non-nullable type', () => {1855      var type;1856      type = comments.parseType('string!');1857      assert.deepEqual(type, {1858        expression: {1859          name: 'string',1860          type: 'NameExpression'1861        },1862        prefix: false,1863        type: 'NonNullableType'1864      });1865    });1866    it('toplevel multiple pipe type', () => {1867      var type;1868      type = comments.parseType('string|number|Test');1869      assert.deepEqual(type, {1870        elements: [1871          {1872            name: 'string',1873            type: 'NameExpression'1874          },1875          {1876            name: 'number',1877            type: 'NameExpression'1878          },1879          {1880            name: 'Test',1881            type: 'NameExpression'1882          }1883        ],1884        type: 'UnionType'1885      });1886    });1887    it('string literal type', () => {1888      var type;1889      type = comments.parseType('"Hello, World"');1890      assert.deepEqual(type, {1891        type: 'StringLiteralType',1892        value: 'Hello, World'1893      });1894    });1895    it('numeric literal type', () => {1896      var type;1897      type = comments.parseType('32');1898      assert.deepEqual(type, {1899        type: 'NumericLiteralType',1900        value: 321901      });1902      type = comments.parseType('-142.42');1903      assert.deepEqual(type, {1904        type: 'NumericLiteralType',1905        value: -142.421906      });1907    });1908    it('boolean literal type', () => {1909      var type;1910      type = comments.parseType('true');1911      assert.deepEqual(type, {1912        type: 'BooleanLiteralType',1913        value: true1914      });1915      type = comments.parseType('false');1916      assert.deepEqual(type, {1917        type: 'BooleanLiteralType',1918        value: false1919      });1920    });1921    it('illegal tokens', () => {1922      assert.throws(() => comments.parseType('.'), /unexpected token/);1923      assert.throws(() => comments.parseType('.d'), /unexpected token/);1924      assert.throws(() => comments.parseType('('), /unexpected token/);1925      assert.throws(() => comments.parseType('Test.'), /unexpected token/);1926    });1927  });1928  describe('parseParamType', () => {1929    it('question', () => {1930      var type = comments.parseParamType('?');1931      assert.deepEqual(type, {1932        type: 'NullableLiteral'1933      });1934    });1935    it('question option', () => {1936      var type = comments.parseParamType('?=');1937      assert.deepEqual(type, {1938        type: 'OptionalType',1939        expression: {1940          type: 'NullableLiteral'1941        }1942      });1943    });1944    it('function option parameters former', () => {1945      var type = comments.parseParamType('function(?, number)');1946      assert.deepEqual(type, {1947        type: 'FunctionType',1948        params: [1949          {1950            type: 'NullableLiteral'1951          },1952          {1953            type: 'NameExpression',1954            name: 'number'1955          }1956        ],1957        result: null1958      });1959    });1960    it('function option parameters latter', () => {1961      var type = comments.parseParamType('function(number, ?)');1962      assert.deepEqual(type, {1963        type: 'FunctionType',1964        params: [1965          {1966            type: 'NameExpression',1967            name: 'number'1968          },1969          {1970            type: 'NullableLiteral'1971          }1972        ],1973        result: null1974      });1975    });1976    it('function type union', () => {1977      var type = comments.parseParamType('function(): ?|number');1978      assert.deepEqual(type, {1979        type: 'UnionType',1980        elements: [1981          {1982            type: 'FunctionType',1983            params: [],1984            result: {1985              type: 'NullableLiteral'1986            }1987          },1988          {1989            type: 'NameExpression',1990            name: 'number'1991          }1992        ]1993      });1994    });1995  });1996  describe('invalid', () => {1997    it('empty union pipe', () => {1998      assert.throws(() => {1999        comments.parseType('(|)').should.throw();2000      });2001      assert.throws(() => {2002        comments.parseType('(string|)').should.throw();2003      });2004      assert.throws(() => {2005        comments.parseType('(string||)').should.throw();2006      });2007    });2008    it('comma only array type', () => {2009      assert.throws(() => {2010        comments.parseType('[,]').should.throw();2011      });2012    });2013    it('comma only record type', () => {2014      assert.throws(() => {2015        comments.parseType('{,,}').should.throw();2016      });2017    });2018    it('incorrect bracket', () => {2019      assert.throws(() => {2020        comments.parseParamType('int[').should.throw();2021      });2022    });2023  });2024  describe('tags option', () => {2025    it('only param', () => {2026      let res = comments.parseComment(['/**', ' * @const @const', ' * @param {String} y', ' */'].join('\n'), {2027        tags: ['param'],2028        unwrap: true2029      });2030      assert.equal(res.tags.length, 1);2031      assert(hasProperty(res.tags[0], 'title', 'param'));2032      assert(hasProperty(res.tags[0], 'name', 'y'));2033    });2034    it('param and type', () => {2035      let res = comments.parseComment(2036        ['/**', ' * @const x', ' * @param {String} y', ' * @type {String} ', ' */'].join('\n'),2037        {2038          tags: ['param', 'type'],2039          unwrap: true2040        }2041      );2042      assert.equal(res.tags.length, 2);2043      assert(hasProperty(res.tags[0], 'title', 'param'));2044      assert(hasProperty(res.tags[0], 'name', 'y'));2045      assert(hasProperty(res.tags[1], 'title', 'type'));2046      assert(hasProperty(res.tags[1], 'type'));2047      assert(hasProperty(res.tags[1].type, 'name', 'String'));2048    });2049  });2050  describe('invalid tags', () => {2051    it('bad tag 1', () => {2052      assert.throws(() => {2053        comments.parse(['/**', ' * @param {String} hucairz', ' */'].join('\n'), {2054          tags: 1,2055          unwrap: true2056        });2057      });2058    });2059    it('bad tag 2', () => {2060      assert.throws(() => {2061        comments.parse(['/**', ' * @param {String} hucairz', ' */'].join('\n'), {2062          tags: ['a', 1],2063          unwrap: true2064        });2065      });2066    });2067  });2068  describe('optional params', () => {2069    // should fail since sloppy option not set2070    it('failure 0', () => {2071      assert.deepEqual(comments.parseComment(['/**', ' * @param {String} [val]', ' */'].join('\n'), {2072        unwrap: true2073      }), {2074        description: '',2075        tags: []2076      });2077    });2078    it('failure 1', () => {2079      assert.deepEqual(comments2080        .parseComment(['/**', ' * @param [val', ' */'].join('\n'), {2081          unwrap: true,2082          sloppy: true2083        })2084        , {2085          description: '',2086          tags: []2087        });2088    });2089    it('success 1', () => {2090      assert.deepEqual(comments2091        .parseComment(['/**', ' * @param {String} [val]', ' */'].join('\n'), {2092          unwrap: true,2093          sloppy: true2094        })2095        , {2096          description: '',2097          tags: [2098            {2099              title: 'param',2100              description: null,2101              type: {2102                type: 'OptionalType',2103                expression: {2104                  type: 'NameExpression',2105                  name: 'String'2106                }2107              },2108              name: 'val'2109            }2110          ]2111        });2112    });2113    it('success 2', () => {2114      assert.deepEqual(comments2115        .parseComment(['/**', ' * @param {String=} val', ' */'].join('\n'), {2116          unwrap: true,2117          sloppy: true2118        })2119        , {2120          description: '',2121          tags: [2122            {2123              title: 'param',2124              description: null,2125              type: {2126                type: 'OptionalType',2127                expression: {2128                  type: 'NameExpression',2129                  name: 'String'2130                }2131              },2132              name: 'val'2133            }2134          ]2135        });2136    });2137    it('success 3', () => {2138      assert.deepEqual(comments2139        .parseComment(['/**', ' * @param {String=} [val=abc] some description', ' */'].join('\n'), {2140          unwrap: true,2141          sloppy: true2142        })2143        , {2144          description: '',2145          tags: [2146            {2147              title: 'param',2148              description: 'some description',2149              type: {2150                type: 'OptionalType',2151                expression: {2152                  type: 'NameExpression',2153                  name: 'String'2154                }2155              },2156              name: 'val',2157              default: 'abc'2158            }2159          ]2160        });2161    });2162    it('success 4', () => {2163      assert.deepEqual(comments2164        .parseComment(['/**', ' * @param {String=} [val = abc] some description', ' */'].join('\n'), {2165          unwrap: true,2166          sloppy: true2167        })2168        , {2169          description: '',2170          tags: [2171            {2172              title: 'param',2173              description: 'some description',2174              type: {2175                type: 'OptionalType',2176                expression: {2177                  type: 'NameExpression',2178                  name: 'String'2179                }2180              },2181              name: 'val',2182              default: 'abc'2183            }2184          ]2185        });2186    });2187    it('default string', () => {2188      assert.deepEqual(comments2189        .parseComment(['/**', ' * @param {String} [val="foo"] some description', ' */'].join('\n'), {2190          unwrap: true,2191          sloppy: true2192        })2193        , {2194          description: '',2195          tags: [2196            {2197              title: 'param',2198              description: 'some description',2199              type: {2200                type: 'OptionalType',2201                expression: {2202                  type: 'NameExpression',2203                  name: 'String'2204                }2205              },2206              name: 'val',2207              default: '"foo"'2208            }2209          ]2210        });2211    });2212    it('default string surrounded by whitespace', () => {2213      assert.deepEqual(comments2214        .parseComment(['/**', " * @param {String} [val=   'foo'  ] some description", ' */'].join('\n'), {2215          unwrap: true,2216          sloppy: true2217        })2218        , {2219          description: '',2220          tags: [2221            {2222              title: 'param',2223              description: 'some description',2224              type: {2225                type: 'OptionalType',2226                expression: {2227                  type: 'NameExpression',2228                  name: 'String'2229                }2230              },2231              name: 'val',2232              default: "'foo'"2233            }2234          ]2235        });2236    });2237    it('should preserve whitespace in default string', () => {2238      assert.deepEqual(comments2239        .parseComment(['/**', ' * @param {String} [val=   "   foo"  ] some description', ' */'].join('\n'), {2240          unwrap: true,2241          sloppy: true2242        })2243        , {2244          description: '',2245          tags: [2246            {2247              title: 'param',2248              description: 'some description',2249              type: {2250                type: 'OptionalType',2251                expression: {2252                  type: 'NameExpression',2253                  name: 'String'2254                }2255              },2256              name: 'val',2257              default: '"   foo"'2258            }2259          ]2260        });2261    });2262    it('default array', () => {2263      assert.deepEqual(comments2264        .parseComment(['/**', " * @param {String} [val=['foo']] some description", ' */'].join('\n'), {2265          unwrap: true,2266          sloppy: true2267        })2268        , {2269          description: '',2270          tags: [2271            {2272              title: 'param',2273              description: 'some description',2274              type: {2275                type: 'OptionalType',2276                expression: {2277                  type: 'NameExpression',2278                  name: 'String'2279                }2280              },2281              name: 'val',2282              default: "['foo']"2283            }2284          ]2285        });2286    });2287    it('default array', () => {2288      assert.deepEqual(comments2289        .parseComment(['/**', " * @param {String} [val=['foo']] some description", ' */'].join('\n'), {2290          unwrap: true,2291          sloppy: true2292        })2293        , {2294          description: '',2295          tags: [2296            {2297              title: 'param',2298              description: 'some description',2299              type: {2300                type: 'OptionalType',2301                expression: {2302                  type: 'NameExpression',2303                  name: 'String'2304                }2305              },2306              name: 'val',2307              default: "['foo']"2308            }2309          ]2310        });2311    });2312    it('default array within white spaces', () => {2313      assert.deepEqual(comments2314        .parseComment(['/**', " * @param {String} [val = [ 'foo' ]] some description", ' */'].join('\n'), {2315          unwrap: true,2316          sloppy: true2317        })2318        , {2319          description: '',2320          tags: [2321            {2322              title: 'param',2323              description: 'some description',2324              type: {2325                type: 'OptionalType',2326                expression: {2327                  type: 'NameExpression',2328                  name: 'String'2329                }2330              },2331              name: 'val',2332              default: "['foo']"2333            }2334          ]2335        });2336    });2337    it('line numbers', () => {2338      let res = comments.parseComment(2339        [2340          '/**',2341          ' * @constructor',2342          ' * @param {string} foo',2343          ' * @returns {string}',2344          ' *',2345          ' * @example',2346          " * f('blah'); // => undefined",2347          ' */'2348        ].join('\n'),2349        {2350          unwrap: true,2351          lineNumbers: true2352        }2353      );2354      assert(hasProperty(res.tags[0], 'lineNumber', 1));2355      assert(hasProperty(res.tags[1], 'lineNumber', 2));2356      assert(hasProperty(res.tags[2], 'lineNumber', 3));2357      assert(hasProperty(res.tags[3], 'lineNumber', 5));2358    });2359    it('example caption', () => {2360      let res = comments.parseComment(2361        ['/**', ' * @example <caption>hi</caption>', " * f('blah'); // => undefined", ' */'].join('\n'),2362        {2363          unwrap: true,2364          lineNumbers: true2365        }2366      );2367      assert.deepEqual(res.tags[0].description, "f('blah'); // => undefined");2368      assert.deepEqual(res.tags[0].caption, 'hi');2369    });2370    it('should handle \\r\\n line endings correctly', () => {2371      let res = comments.parseComment(2372        [2373          '/**',2374          ' * @param {string} foo',2375          ' * @returns {string}',2376          ' *',2377          ' * @example',2378          " * f('blah'); // => undefined",2379          ' */'2380        ].join('\r\n'),2381        {2382          unwrap: true,2383          lineNumbers: true2384        }2385      );2386      assert(hasProperty(res.tags[0], 'lineNumber', 1));2387      assert(hasProperty(res.tags[1], 'lineNumber', 2));2388      assert(hasProperty(res.tags[2], 'lineNumber', 4));2389    });2390  });2391  describe('optional properties', () => {2392    // should fail since sloppy option not set2393    it('failure 0', () => {2394      assert.deepEqual(comments2395        .parseComment(['/**', ' * @property {String} [val] some description', ' */'].join('\n'), {2396          unwrap: true2397        })2398        , {2399          description: '',2400          tags: []2401        });2402    });2403    it('failure 1', () => {2404      assert.deepEqual(comments2405        .parseComment(['/**', ' * @property [val', ' */'].join('\n'), {2406          unwrap: true,2407          sloppy: true2408        })2409        , {2410          description: '',2411          tags: []2412        });2413    });2414    it('success 1', () => {2415      assert.deepEqual(comments2416        .parseComment(['/**', ' * @property {String} [val]', ' */'].join('\n'), {2417          unwrap: true,2418          sloppy: true2419        })2420        , {2421          description: '',2422          tags: [2423            {2424              title: 'property',2425              description: null,2426              type: {2427                type: 'OptionalType',2428                expression: {2429                  type: 'NameExpression',2430                  name: 'String'2431                }2432              },2433              name: 'val'2434            }2435          ]2436        });2437    });2438    it('success 2', () => {2439      assert.deepEqual(comments2440        .parseComment(['/**', ' * @property {String=} val', ' */'].join('\n'), {2441          unwrap: true,2442          sloppy: true2443        })2444        , {2445          description: '',2446          tags: [2447            {2448              title: 'property',2449              description: null,2450              type: {2451                type: 'OptionalType',2452                expression: {2453                  type: 'NameExpression',2454                  name: 'String'2455                }2456              },2457              name: 'val'2458            }2459          ]2460        });2461    });2462    it('success 3', () => {2463      assert.deepEqual(comments2464        .parseComment(['/**', ' * @property {String=} [val=abc] some description', ' */'].join('\n'), {2465          unwrap: true,2466          sloppy: true2467        })2468        , {2469          description: '',2470          tags: [2471            {2472              title: 'property',2473              description: 'some description',2474              type: {2475                type: 'OptionalType',2476                expression: {2477                  type: 'NameExpression',2478                  name: 'String'2479                }2480              },2481              name: 'val',2482              default: 'abc'2483            }2484          ]2485        });2486    });2487    it('success 4', () => {2488      assert.deepEqual(comments2489        .parseComment(['/**', ' * @property {String=} [val = abc] some description', ' */'].join('\n'), {2490          unwrap: true,2491          sloppy: true2492        })2493        , {2494          description: '',2495          tags: [2496            {2497              title: 'property',2498              description: 'some description',2499              type: {2500                type: 'OptionalType',2501                expression: {2502                  type: 'NameExpression',2503                  name: 'String'2504                }2505              },2506              name: 'val',2507              default: 'abc'2508            }2509          ]2510        });2511    });2512    it('default string', () => {2513      assert.deepEqual(comments2514        .parseComment(['/**', ' * @property {String} [val="foo"] some description', ' */'].join('\n'), {2515          unwrap: true,2516          sloppy: true2517        })2518        , {2519          description: '',2520          tags: [2521            {2522              title: 'property',2523              description: 'some description',2524              type: {2525                type: 'OptionalType',2526                expression: {2527                  type: 'NameExpression',2528                  name: 'String'2529                }2530              },2531              name: 'val',2532              default: '"foo"'2533            }2534          ]2535        });2536    });2537    it('default string surrounded by whitespace', () => {2538       assert.deepEqual(comments2539        .parseComment(['/**', " * @property {String} [val=   'foo'  ] some description", ' */'].join('\n'), {2540          unwrap: true,2541          sloppy: true2542        })2543       , {2544          description: '',2545          tags: [2546            {2547              title: 'property',2548              description: 'some description',2549              type: {2550                type: 'OptionalType',2551                expression: {2552                  type: 'NameExpression',2553                  name: 'String'2554                }2555              },2556              name: 'val',2557              default: "'foo'"2558            }2559          ]2560        });2561    });2562    it('should preserve whitespace in default string', () => {2563      assert.deepEqual(comments2564        .parseComment(['/**', ' * @property {String} [val=   "   foo"  ] some description', ' */'].join('\n'), {2565          unwrap: true,2566          sloppy: true2567        })2568        , {2569          description: '',2570          tags: [2571            {2572              title: 'property',2573              description: 'some description',2574              type: {2575                type: 'OptionalType',2576                expression: {2577                  type: 'NameExpression',2578                  name: 'String'2579                }2580              },2581              name: 'val',2582              default: '"   foo"'2583            }2584          ]2585        });2586    });2587    it('default array', () => {2588      assert.deepEqual(comments2589        .parseComment(['/**', " * @property {String} [val=['foo']] some description", ' */'].join('\n'), {2590          unwrap: true,2591          sloppy: true2592        })2593        , {2594          description: '',2595          tags: [2596            {2597              title: 'property',2598              description: 'some description',2599              type: {2600                type: 'OptionalType',2601                expression: {2602                  type: 'NameExpression',2603                  name: 'String'2604                }2605              },2606              name: 'val',2607              default: "['foo']"2608            }2609          ]2610        });2611    });2612    it('default array within white spaces', () => {2613      assert.deepEqual(comments2614        .parseComment(['/**', " * @property {String} [val = [ 'foo' ]] some description", ' */'].join('\n'), {2615          unwrap: true,2616          sloppy: true2617        })2618        , {2619          description: '',2620          tags: [2621            {2622              title: 'property',2623              description: 'some description',2624              type: {2625                type: 'OptionalType',2626                expression: {2627                  type: 'NameExpression',2628                  name: 'String'2629                }2630              },2631              name: 'val',2632              default: "['foo']"2633            }2634          ]2635        });2636    });2637  });2638  describe('recovery tests', () => {2639    it('params 2', () => {2640      let res = comments.parseComment(['@param f', '@param {string} f2'].join('\n'), {2641        recoverable: true2642      });2643      // ensure both parameters are OK2644      assert.equal(res.tags.length, 2);2645      assert(hasProperty(res.tags[0], 'title', 'param'));2646      assert(hasProperty(res.tags[0], 'type', null));2647      assert(hasProperty(res.tags[0], 'name', 'f'));2648      assert(hasProperty(res.tags[1], 'title', 'param'));2649      assert(hasProperty(res.tags[1], 'type'));2650      assert(hasProperty(res.tags[1].type, 'name', 'string'));2651      assert(hasProperty(res.tags[1].type, 'type', 'NameExpression'));2652      assert(hasProperty(res.tags[1], 'name', 'f2'));2653    });2654    it('params 2', () => {2655      let res = comments.parseComment(['@param string f', '@param {string} f2'].join('\n'), {2656        recoverable: true2657      });2658      // ensure first parameter is OK even with invalid type name2659      assert.equal(res.tags.length, 2);2660      assert(hasProperty(res.tags[0], 'title', 'param'));2661      assert(hasProperty(res.tags[0], 'type', null));2662      assert(hasProperty(res.tags[0], 'name', 'string'));2663      assert(hasProperty(res.tags[0], 'description', 'f'));2664      assert(hasProperty(res.tags[1], 'title', 'param'));2665      assert(hasProperty(res.tags[1], 'type'));2666      assert(hasProperty(res.tags[1].type, 'name', 'string'));2667      assert(hasProperty(res.tags[1].type, 'type', 'NameExpression'));2668      assert(hasProperty(res.tags[1], 'name', 'f2'));2669    });2670    it('return 1', () => {2671      let res = comments.parseComment(['@returns'].join('\n'), {2672        recoverable: true2673      });2674      // return tag should exist2675      assert.equal(res.tags.length, 1);2676      assert(hasProperty(res.tags[0], 'title', 'returns'));2677      assert(hasProperty(res.tags[0], 'type', null));2678    });2679    it('return 2', () => {2680      let res = comments.parseComment(['@returns', '@param {string} f2'].join('\n'), {2681        recoverable: true2682      });2683      // return tag should exist as well as next tag2684      assert.equal(res.tags.length, 2);2685      assert(hasProperty(res.tags[0], 'title', 'returns'));2686      assert(hasProperty(res.tags[0], 'type', null));2687      assert(hasProperty(res.tags[1], 'title', 'param'));2688      assert(hasProperty(res.tags[1], 'type'));2689      assert(hasProperty(res.tags[1].type, 'name', 'string'));2690      assert(hasProperty(res.tags[1].type, 'type', 'NameExpression'));2691      assert(hasProperty(res.tags[1], 'name', 'f2'));2692    });2693    it('return no type', () => {2694      let res = comments.parseComment(['@return a value'].join('\n'));2695      // return tag should exist2696      assert.equal(res.tags.length, 1);2697      assert(hasProperty(res.tags[0], 'title', 'return'));2698      assert(hasProperty(res.tags[0], 'type', null));2699      assert(hasProperty(res.tags[0], 'description', 'a value'));2700    });2701    it('extra @ 1', () => {2702      let res = comments.parseComment(['@', '@returns', '@param {string} f2'].join('\n'), {2703        recoverable: true2704      });2705      // empty tag name shouldn't affect subsequent tags2706      assert.equal(res.tags.length, 3);2707      assert(hasProperty(res.tags[0], 'title', ''));2708      assert(!res.tags[0].hasOwnProperty('type'));2709      assert(hasProperty(res.tags[1], 'title', 'returns'));2710      assert(hasProperty(res.tags[1], 'type', null));2711      assert(hasProperty(res.tags[2], 'title', 'param'));2712      assert(hasProperty(res.tags[2], 'type'));2713      assert(hasProperty(res.tags[2].type, 'name', 'string'));2714      assert(hasProperty(res.tags[2].type, 'type', 'NameExpression'));2715      assert(hasProperty(res.tags[2], 'name', 'f2'));2716    });2717    it('extra @ 2', () => {2718      let res = comments.parseComment(['@ invalid name', '@param {string} f2'].join('\n'), {2719        recoverable: true2720      });2721      // empty tag name shouldn't affect subsequent tags2722      assert.equal(res.tags.length, 2);2723      assert(hasProperty(res.tags[0], 'title', ''));2724      assert(!res.tags[0].hasOwnProperty('type'));2725      assert(!res.tags[0].hasOwnProperty('name'));2726      assert(hasProperty(res.tags[0], 'description', 'invalid name'));2727      assert(hasProperty(res.tags[1], 'title', 'param'));2728      assert(hasProperty(res.tags[1], 'type'));2729      assert(hasProperty(res.tags[1].type, 'name', 'string'));2730      assert(hasProperty(res.tags[1].type, 'type', 'NameExpression'));2731      assert(hasProperty(res.tags[1], 'name', 'f2'));2732    });2733    it('invalid tag 1', () => {2734      let res = comments.parseComment(['@111 invalid name', '@param {string} f2'].join('\n'), {2735        recoverable: true2736      });2737      // invalid tag name shouldn't affect subsequent tags2738      assert.equal(res.tags.length, 2);2739      assert(hasProperty(res.tags[0], 'title', '111'));2740      assert(!res.tags[0].hasOwnProperty('type'));2741      assert(!res.tags[0].hasOwnProperty('name'));2742      assert(hasProperty(res.tags[0], 'description', 'invalid name'));2743      assert(hasProperty(res.tags[1], 'title', 'param'));2744      assert(hasProperty(res.tags[1], 'type'));2745      assert(hasProperty(res.tags[1].type, 'name', 'string'));2746      assert(hasProperty(res.tags[1].type, 'type', 'NameExpression'));2747      assert(hasProperty(res.tags[1], 'name', 'f2'));2748    });2749    it('invalid tag 1', () => {2750      let res = comments.parseComment(['@111', '@param {string} f2'].join('\n'), {2751        recoverable: true2752      });2753      // invalid tag name shouldn't affect subsequent tags2754      assert.equal(res.tags.length, 2);2755      assert(hasProperty(res.tags[0], 'title', '111'));2756      assert(!res.tags[0].hasOwnProperty('type'));2757      assert(!res.tags[0].hasOwnProperty('name'));2758      assert(hasProperty(res.tags[0], 'description', null));2759      assert(hasProperty(res.tags[1], 'title', 'param'));2760      assert(hasProperty(res.tags[1], 'type'));2761      assert(hasProperty(res.tags[1].type, 'name', 'string'));2762      assert(hasProperty(res.tags[1].type, 'type', 'NameExpression'));2763      assert(hasProperty(res.tags[1], 'name', 'f2'));2764    });2765    it('should not crash on bad type in @param without name', () => {2766      let res = comments.parseComment('@param {Function(DOMNode)}', {2767        recoverable: true2768      });2769      assert.equal(res.tags.length, 1);2770      assert.deepEqual(res.tags[0], {2771        description: null,2772        errors: ['not reach to EOF', 'Missing or invalid tag name'],2773        name: null,2774        title: 'param',2775        type: null2776      });2777    });2778    it('should not crash on bad type in @param in sloppy mode', () => {2779      let res = comments.parseComment('@param {int[} [x]', {2780        sloppy: true,2781        recoverable: true2782      });2783      assert.equal(res.tags.length, 1);2784      assert.deepEqual(res.tags[0], {2785        description: null,2786        errors: ['expected an array-style type declaration (int[])'],2787        name: 'x',2788        title: 'param',2789        type: null2790      });2791    });2792  });2793  describe('@ mark contained descriptions', () => {2794    it('comment description #10', () => {2795      let res = comments.parseComment(2796        [2797          '/**',2798          ' * Prevents the default action. It is equivalent to',2799          ' * {@code e.preventDefault()}, but can be used as the callback argument of',2800          ' * {@link goog.events.listen} without declaring another function.',2801          ' * @param {!goog.events.Event} e An event.',2802          ' */'2803        ].join('\n'),2804        {2805          unwrap: true,2806          sloppy: true2807        }2808      );2809      assert.equal(2810        res.description,2811        'Prevents the default action. It is equivalent to\n{@code e.preventDefault()}, but can be used as the callback argument of\n{@link goog.events.listen} without declaring another function.'2812      );2813      assert.deepEqual(res.tags, [2814        {2815          title: 'param',2816          description: 'An event.',2817          type: {2818            type: 'NonNullableType',2819            expression: {2820              type: 'NameExpression',2821              name: 'goog.events.Event'2822            },2823            prefix: true2824          },2825          name: 'e'2826        }2827      ]);2828    });2829    it('tag description', () => {2830      assert.deepEqual(comments.parseComment(2831          [2832            '/**',2833            ' * Prevents the default action. It is equivalent to',2834            ' * @param {!goog.events.Event} e An event.',2835            ' * {@code e.preventDefault()}, but can be used as the callback argument of',2836            ' * {@link goog.events.listen} without declaring another function.',2837            ' */'2838          ].join('\n'),2839          {2840            unwrap: true,2841            sloppy: true2842          })2843        , {2844          description: 'Prevents the default action. It is equivalent to',2845          inlineTags: [],2846          tags: [2847            {2848              title: 'param',2849              description:2850                'An event.\n{@code e.preventDefault()}, but can be used as the callback argument of\n{@link goog.events.listen} without declaring another function.',2851              type: {2852                type: 'NonNullableType',2853                expression: {2854                  type: 'NameExpression',2855                  name: 'goog.events.Event'2856                },2857                prefix: true2858              },2859              name: 'e'2860            }2861          ]2862        });2863    });2864  });2865  describe('function', () => {2866    it('recognize "function" type', () => {2867      let res = comments.parseComment('@param {function} foo description', {});2868      assert.equal(res.tags.length, 1);2869      assert(hasProperty(res.tags[0], 'title', 'param'));2870      assert(hasProperty(res.tags[0], 'type'));2871      assert.deepEqual(res.tags[0].type, {2872        name: 'function',2873        type: 'NameExpression'2874      });2875      assert(hasProperty(res.tags[0], 'name', 'foo'));2876      assert(hasProperty(res.tags[0], 'description', 'description'));2877    });2878  });2879  describe('tagged namepaths', () => {2880    it('recognize module:', () => {2881      let res = comments.parseComment(['@alias module:Foo.bar'].join('\n'), {});2882      assert.equal(res.tags.length, 1);2883      assert(hasProperty(res.tags[0], 'title', 'alias'));2884      assert(hasProperty(res.tags[0], 'name', 'module:Foo.bar'));2885      assert(hasProperty(res.tags[0], 'description', null));2886    });2887    it('recognize external:', () => {2888      let res = comments.parseComment(['@param {external:Foo.bar} baz description'].join('\n'), {});2889      assert.equal(res.tags.length, 1);2890      assert(hasProperty(res.tags[0], 'title', 'param'));2891      assert.deepEqual(res.tags[0].type, {2892        name: 'external:Foo.bar',2893        type: 'NameExpression'2894      });2895      assert(hasProperty(res.tags[0], 'name', 'baz'));2896      assert(hasProperty(res.tags[0], 'description', 'description'));2897    });2898    it('recognize event:', () => {2899      let res = comments.parseComment(['@function event:Foo.bar'].join('\n'), {});2900      assert.equal(res.tags.length, 1);2901      assert(hasProperty(res.tags[0], 'title', 'function'));2902      assert(hasProperty(res.tags[0], 'name', 'event:Foo.bar'));2903      assert(hasProperty(res.tags[0], 'description', null));2904    });2905    it('invalid bogus:', () => {2906      let res = comments.parseComment(['@method bogus:Foo.bar'].join('\n'), {});2907      assert.equal(res.tags.length, 0);2908    });2909  });...parse.optional.js
Source:parse.optional.js  
...17  });18  describe('optional params', () => {19    // should fail since sloppy option not set20    it('failure 0', () => {21      let res = comments.parseComment('/** * @param {String} [val] */', {22        unwrap: true,23        strict: true24      });25      assert.equal(res.tags.length, 0);26      assert.equal(res.description, '');27    });28    it('failure 1', () => {29      let res = comments.parseComment('/** * @param [val */', {30        unwrap: true,31        strict: false32      });33      assert.deepEqual(pick(res, ['tags', 'description']), {34        'description': '',35        'tags': []36      });37    });38    it('success 1', () => {39      let res = comments.parseComment(['/**', ' * @param {String} [val]', ' */'].join('\n'), {40        unwrap: true,41        strict: false42      });43      assert.deepEqual(pick(res, ['tags', 'description']), {44        'description': '',45        'tags': [{46          'title': 'param',47          'description': '',48          'type': {49            'type': 'OptionalType',50            'expression': {51              'type': 'NameExpression',52              'name': 'String'53            }54          },55          'name': 'val'56        }]57      });58    });59    it('success 2', () => {60      let res = comments.parseComment(['/**', ' * @param {String=} val', ' */'].join('\n'), {61        unwrap: true,62        strict: false63      });64      assert.deepEqual(pick(res, ['tags', 'description']), {65        'description': '',66        'tags': [{67          'title': 'param',68          'description': '',69          'type': {70            'type': 'OptionalType',71            'expression': {72              'type': 'NameExpression',73              'name': 'String'74            }75          },76          'name': 'val'77        }]78      });79    });80    it('success 3', () => {81      let res = comments.parseComment('/** * @param {String=} [val=abc] some description */', {82        unwrap: true,83        strict: false84      });85      assert.deepEqual(pick(res, ['tags', 'description']), {86        description: '',87        tags: [88          {89            title: 'param',90            description: 'some description',91            inlineTags: [],92            type: {93              type: 'OptionalType',94              expression: {95                type: 'NameExpression',96                name: 'String'97              }98            },99            name: 'val',100            default: 'abc'101          }102        ]103      });104    });105    it('success 4', () => {106      let res = comments.parseComment(['/**', ' * @param {String=} [val = abc] some description', ' */'].join('\n'), {107        unwrap: true,108        strict: false109      });110      assert.deepEqual(pick(res, ['tags', 'description']), {111        description: '',112        tags: [113          {114            title: 'param',115            description: 'some description',116            inlineTags: [],117            type: {118              type: 'OptionalType',119              expression: {120                type: 'NameExpression',121                name: 'String'122              }123            },124            name: 'val',125            default: 'abc'126          }127        ]128      });129    });130    it('default string', () => {131      let res = comments.parseComment(['/**', ' * @param {String} [val="foo"] some description', ' */'].join('\n'), {132        unwrap: true,133        strict: false134      });135      assert.deepEqual(pick(res, ['tags', 'description']), {136        description: '',137        tags: [138          {139            title: 'param',140            description: 'some description',141            inlineTags: [],142            type: {143              type: 'OptionalType',144              expression: {145                type: 'NameExpression',146                name: 'String'147              }148            },149            name: 'val',150            default: '"foo"'151          }152        ]153      });154    });155    it('default string surrounded by whitespace', () => {156      let res = comments.parseComment(['/**', " * @param {String} [val=   'foo'  ] some description", ' */'].join('\n'), {157        unwrap: true,158        strict: false159      });160      assert.deepEqual(pick(res, ['tags', 'description']), {161        description: '',162        tags: [163          {164            title: 'param',165            description: 'some description',166            inlineTags: [],167            type: {168              type: 'OptionalType',169              expression: {170                type: 'NameExpression',171                name: 'String'172              }173            },174            name: 'val',175            default: "'foo'"176          }177        ]178      });179    });180    it('should preserve whitespace in default string', () => {181      let res = comments.parseComment(['/**', ' * @param {String} [val=   "   foo"  ] some description', ' */'].join('\n'), {182        unwrap: true,183        strict: false184      });185      assert.deepEqual(pick(res, ['tags', 'description']), {186        description: '',187        tags: [188          {189            title: 'param',190            description: 'some description',191            inlineTags: [],192            type: {193              type: 'OptionalType',194              expression: {195                type: 'NameExpression',196                name: 'String'197              }198            },199            name: 'val',200            default: '"   foo"'201          }202        ]203      });204    });205    it('default array', () => {206      let res = comments.parseComment(['/**', " * @param {String} [val=['foo']] some description", ' */'].join('\n'), {207        unwrap: true,208        strict: false209      });210      assert.deepEqual(pick(res, ['tags', 'description']), {211        description: '',212        tags: [213          {214            title: 'param',215            description: 'some description',216            inlineTags: [],217            type: {218              type: 'OptionalType',219              expression: {220                type: 'NameExpression',221                name: 'String'222              }223            },224            name: 'val',225            default: "['foo']"226          }227        ]228      });229    });230    it('default array', () => {231      let res = comments.parseComment(['/**', " * @param {String} [val=['foo']] some description", ' */'].join('\n'), {232        unwrap: true,233        strict: false234      });235      assert.deepEqual(pick(res, ['tags', 'description']), {236        description: '',237        tags: [238          {239            title: 'param',240            description: 'some description',241            inlineTags: [],242            type: {243              type: 'OptionalType',244              expression: {245                type: 'NameExpression',246                name: 'String'247              }248            },249            name: 'val',250            default: "['foo']"251          }252        ]253      });254    });255    it('default array within white spaces', () => {256      let res = comments.parseComment(['/**', " * @param {String} [val = [ 'foo' ]] some description", ' */'].join('\n'), {257        unwrap: true,258        strict: false259      });260      assert.deepEqual(pick(res, ['tags', 'description']), {261        description: '',262        tags: [263          {264            title: 'param',265            description: 'some description',266            inlineTags: [],267            type: {268              type: 'OptionalType',269              expression: {270                type: 'NameExpression',271                name: 'String'272              }273            },274            name: 'val',275            default: "[ 'foo' ]"276          }277        ]278      });279    });280    it('example caption', () => {281      let res = comments.parseComment([282        '/**',283        ' * @example <caption>hi</caption>',284        " * f('blah'); // => undefined",285        ' */'286      ].join('\n'), {287        unwrap: true,288        jsdoc: true289      });290      assert.equal(res.tags[0].description, "f('blah'); // => undefined");291      assert.equal(res.tags[0].caption, 'hi');292    });293    it('should handle \\r\\n line endings correctly', () => {294      let res = comments.parseComment([295        '/**',296        ' * @param {string} foo',297        ' * @returns {string}',298        ' *',299        ' * @example',300        " * f('blah'); // => undefined",301        ' */'302      ].join('\r\n'), {303        unwrap: true,304        jsdoc: true305      });306      assert.equal(res.tags[2].description, "f('blah'); // => undefined");307    });308  });309  describe('optional properties', () => {310    // should fail since sloppy option not set311    it('failure 0', () => {312      let res = comments.parseComment(['/**',313        ' * @property {String} [val] some description',314        ' */'315      ].join('\n'), {316        unwrap: true,317        strict: true318      });319      assert.deepEqual(pick(res, ['tags', 'description']), {320        'description': '',321        'tags': []322      });323    });324    it('failure 1', () => {325      let res = comments.parseComment(['/**', ' * @property [val', ' */'].join('\n'), {326        unwrap: true,327        strict: false328      });329      assert.deepEqual(pick(res, ['tags', 'description']), {330        'description': '',331        'tags': []332      });333    });334    it('success 1', () => {335      let res = comments.parseComment(['/**', ' * @property {String} [val]', ' */'].join('\n'), {336        unwrap: true,337        strict: false338      });339      assert.deepEqual(pick(res, ['tags', 'description']), {340        description: '',341        tags: [342          {343            title: 'property',344            description: '',345            type: {346              type: 'OptionalType',347              expression: {348                type: 'NameExpression',349                name: 'String'350              }351            },352            name: 'val'353          }354        ]355      });356    });357    it('success 2', () => {358      let res = comments.parseComment(['/**', ' * @property {String=} val', ' */'].join('\n'), {359        unwrap: true,360        strict: false361      });362      assert.deepEqual(pick(res, ['tags', 'description']), {363        description: '',364        tags: [365          {366            title: 'property',367            description: '',368            type: {369              type: 'OptionalType',370              expression: {371                type: 'NameExpression',372                name: 'String'373              }374            },375            name: 'val'376          }377        ]378      });379    });380    it('success 3', () => {381      let res = comments.parseComment(['/**', ' * @property {String=} [val=abc] some description', ' */'].join('\n'), {382        unwrap: true,383        strict: false384      });385      assert.deepEqual(pick(res, ['tags', 'description']), {386        description: '',387        tags: [388          {389            title: 'property',390            description: 'some description',391            inlineTags: [],392            type: {393              type: 'OptionalType',394              expression: {395                type: 'NameExpression',396                name: 'String'397              }398            },399            name: 'val',400            default: 'abc'401          }402        ]403      });404    });405    it('success 4', () => {406      let res = comments.parseComment(['/**', ' * @property {String=} [val = abc] some description', ' */'].join('\n'), {407        unwrap: true,408        strict: false409      });410      assert.deepEqual(pick(res, ['tags', 'description']), {411        description: '',412        tags: [413          {414            title: 'property',415            description: 'some description',416            inlineTags: [],417            type: {418              type: 'OptionalType',419              expression: {420                type: 'NameExpression',421                name: 'String'422              }423            },424            name: 'val',425            default: 'abc'426          }427        ]428      });429    });430    it('default string', () => {431      let res = comments.parseComment(['/**', ' * @property {String} [val="foo"] some description', ' */'].join('\n'), {432        unwrap: true,433        strict: false434      });435      assert.deepEqual(pick(res, ['tags', 'description']), {436        description: '',437        tags: [438          {439            title: 'property',440            description: 'some description',441            inlineTags: [],442            type: {443              type: 'OptionalType',444              expression: {445                type: 'NameExpression',446                name: 'String'447              }448            },449            name: 'val',450            default: '"foo"'451          }452        ]453      });454    });455    it('default string surrounded by whitespace', () => {456      let res = comments.parseComment(['/**', " * @property {String} [val=   'foo'  ] some description", ' */'].join('\n'), {457        unwrap: true,458        strict: false459      });460      assert.deepEqual(pick(res, ['tags', 'description']), {461        description: '',462        tags: [463          {464            title: 'property',465            description: 'some description',466            inlineTags: [],467            type: {468              type: 'OptionalType',469              expression: {470                type: 'NameExpression',471                name: 'String'472              }473            },474            name: 'val',475            default: "'foo'"476          }477        ]478      });479    });480    it('should preserve whitespace in default string', () => {481      let res = comments.parseComment(['/**', ' * @property {String} [val=   "   foo"  ] some description', ' */'].join('\n'), {482        unwrap: true,483        strict: false484      });485      assert.deepEqual(pick(res, ['tags', 'description']), {486        description: '',487        tags: [488          {489            title: 'property',490            description: 'some description',491            inlineTags: [],492            type: {493              type: 'OptionalType',494              expression: {495                type: 'NameExpression',496                name: 'String'497              }498            },499            name: 'val',500            default: '"   foo"'501          }502        ]503      });504    });505    it('default array', () => {506      let res = comments.parseComment(['/**', " * @property {String} [val=['foo']] some description", ' */'].join('\n'), {507        unwrap: true,508        strict: false509      });510      assert.deepEqual(pick(res, ['tags', 'description']), {511        description: '',512        tags: [513          {514            title: 'property',515            description: 'some description',516            inlineTags: [],517            type: {518              type: 'OptionalType',519              expression: {520                type: 'NameExpression',521                name: 'String'522              }523            },524            name: 'val',525            default: "['foo']"526          }527        ]528      });529    });530    it('default array within white spaces', () => {531      let res = comments.parseComment(['/**', " * @property {String} [val = [ 'foo' ]] some description", ' */'].join('\n'), {532        unwrap: true,533        strict: false534      });535      assert.deepEqual(pick(res, ['tags', 'description']), {536        description: '',537        tags: [538          {539            title: 'property',540            description: 'some description',541            inlineTags: [],542            type: {543              type: 'OptionalType',544              expression: {545                type: 'NameExpression',...Parser.js
Source:Parser.js  
...21         constructor22         *************23         */24      `;25      var test = qx.tool.compiler.jsdoc.Parser.parseComment(text);26      this.assert(qx.lang.Object.equals(test, {}));27    },28    29    testCheckParams: function() {30      let text = `*31         @param {String} json jsdoc style32         @param json {String}   qooxdoo style33    `;  34      var test = qx.tool.compiler.jsdoc.Parser.parseComment(text);35      qx.tool.compiler.jsdoc.Parser.parseJsDoc(test, "test", null);36      console.log(test["@description"][0].body);37      this.assert(test["@description"][0].body === "");38      this.assert(test["@param"].length === 2);39    },40     41    testCheckIssue633: function() {42      {43        let text = `*44        // [Constructor]45        `;  46        var test = qx.tool.compiler.jsdoc.Parser.parseComment(text);47        console.log(test["@description"][0].body);48        this.assert(test["@description"][0].body === "");49      }50      {51        let text = `52         *53         * Create an editor instance54         * 55         * [Constructor]56         * 57         * @return {Object}58         *59        `;  60        test = qx.tool.compiler.jsdoc.Parser.parseComment(text);61        console.log(test["@description"][0].body);62        this.assert(test["@description"][0].body !== "");63      }64    },65    66    testCheckRpc: function() {67      let text = `68       * <p>This namespace provides an API implementing the69       * <a href="https://www.jsonrpc.org/specification">JSON Remote Procedure Call (JSON-RPC) version 2 specification</a>70       * </p>71       * <p>JSON-RPC v2 is transport-agnostic. We provide a high-level72       * API interface (qx.io.jsonrpc.Client), a transport interface73       * (qx.io.jsonrpc.transport.ITransport) and an HTTP transport implementation.74       * Other transports based on websockets or other mechanisms can be added later.75       * </p>76       * Here is an example:77       *78       * <pre class="javascript">79       * (async()=>{80       *   const client = new qx.io.jsonrpc.Client("https://domain.com/endpoint");81       *   let result;82       *   try {83       *     client.sendNotification("other_method", [1,2,3]); // notifications are "fire & forget"84       *     result = await client.sendRequest("other_method", [1,2,3]);85       *   } catch(e) {86       *     // handle exceptions87       *   }88       * })();89       * </pre>90       *91       * or using a batch:92       *93       * <pre class="javascript">94       * (async()=>{95       *   const client = new qx.io.jsonrpc.Client("https://domain.com/endpoint");96       *   const batch = new qx.io.jsonrpc.protocol.Batch()97       *     .add(new qx.io.jsonrpc.protocol.Request("method3", [1,2,3]))98       *     .addNotification("method4") // or shorthand method99       *    .addRequest("method5",["foo", "bar"]) // positional parameters100       *     .addRequest("method6", {foo:"bar"}); // named parameters101       *   let results;102       *   try {103       *     results = await client.sendBatch(batch);104       *     // results will be an array with three items, the result of the requests105       *   } catch(e) {106       *     // handle exceptions107       *   }108       * })();109       * </pre>110       *111       * The high-level Client API does not handle transport-specific issues like112       * authentication - this needs to be done in the transport layer. For example,113       * to use HTTP Bearer authentication, do this:114       * <pre class="javascript">115       * const client = new qx.io.jsonrpc.Client("https://domain.com/endpoint");116       * const auth = new qx.io.request.authentication.Bearer("TOKEN");117       * client.getTransportImpl().setAuthentication(auth);118       * client.sendRequest("method-needing-authentication", [1,2,3]);119       * </pre>120       *121       * If you need a client with a customized transport often, we recommend122       * to create a class that inherits from the client class, override123       * the methods which are needed to produce that custom behavior (such124       * as {@link qx.io.jsonrpc.transport.Http#_createTransportImpl},125       * and provide a <pre class="javascript">defer</pre> section which registers126       * the behavior for your particular class of URIs:127       *128       * <pre class="javascript">129       * defer() {130       *   qx.io.jsonrpc.Client.registerTransport(/^http/, my.custom.Transport);131       * }132       * </pre>133       *134       * The client will always use the transport that was last registered for135       * a certain endpoint pattern, i.e. from then on, all clients created136       * with urls that start with "http" will use that custom behavior.137       *138       */139      `;  140      var test = qx.tool.compiler.jsdoc.Parser.parseComment(text);141      console.log(test["@description"][0].body);142      this.assert(test["@description"][0].body !== "");143    },144    145    testCheckInlineMarkdown: function() {146      let text = `147    * *strong*148    * __emphasis__149    * {@link Resource}     -> link?150    * @ignore(qx.*)151    `;  152      var test = qx.tool.compiler.jsdoc.Parser.parseComment(text);153      console.log(test["@description"][0].body);154      this.assert(test["@description"][0].body !== "");155      this.assert(test["@description"][0].body.includes("<strong>"));156      this.assert(test["@description"][0].body.includes("<em>"));157      this.assert(test["@ignore"].length === 1);158    },159    160    testHiResSyntax() {161      let data = qx.tool.compiler.jsdoc.Parser.parseComment(162        " *\n" + 163        " * @asset(qx/test/webfonts/fontawesome-webfont.*)\n" + 164        " * @asset(qx/icon/Tango/48/places/folder.png)\n" + 165        " * @asset(qx/icon/Tango/32/places/folder.png)\n" +166        " * @asset(qx/static/blank.gif)\n" +167        " * @asset(qx/static/drawer.png)\n" +168        " * @asset(qx/static/drawer@2x.png)");169      this.assert(Boolean(data["@asset"] && data["@asset"].length == 6));170    },171    172    testIgnore: function() {173      let text = `*174     @ignore(process.*)175     @ignore(global.*)176     @ignore(Symbol.*)177     @ignore(chrome.*)178     179    */ 180    `;181      var test = qx.tool.compiler.jsdoc.Parser.parseComment(text);182      console.log(test["@description"][0].body);183      this.assert(test["@description"][0].body === "");184      this.assert(test["@ignore"].length === 4);185    },186    187    testCheckMarkdown: function() {188      let text = `189    *190    * The \`qx.bom.rest\` package consists of only one class: {@link Resource}.191    *192    * {@link Resource} allows to encapsulate the specifics of a REST interface.193    * Rather than requesting URLs with a specific HTTP method manually, a resource194    * representing the remote resource is instantiated and actions are invoked on this resource.195    * A resource with its actions can be configured declaratively or programmatically.196    *197    * There is also {@link qx.io.rest.Resource} which uses {@link Resource} under the hood.198    * The main differences between them are:199    *200    * * The event object available in the listeners (e.g. \`success()\`, \`getSuccess()\` and \`getError()\`) is201    *   a native JavaScript object instead of a qooxdoo object ({@link qx.event.type.Rest}):202    * ** See {@link qx.io.rest.Resource} vs. {@link Resource}203    * ** \`event.getId()\` => \`event.id\`204    * ** \`event.getRequest()\` => \`event.request\`205    * ** \`event.getAction()\` => \`event.action\`206    * ** \`event.getData()\` => \`event.response\`207    * ** \`event.getPhase()\` => @---@ (see below)208    * * Methods which allow request manipulation (e.g. \`configureRequest()\`) will operate on an209    *   instance of {@link qx.bom.request.SimpleXhr} instead of {@link qx.io.request.Xhr}210    *   (their API is similar but not identical)211    * * The method \`poll()\` returns no {@link qx.event.Timer} object. There are two new methods212    *   (\`stopPollByAction()\` and \`restartPollByAction()\`) available at {@link Resource}213    *   which replace the functionality provided by the Timer object.214    * * The phase support, which is a more elaborate version of readyState, is not available.215    *   So use readyState instead.216    * ** Phases (available only in {@link qx.io.rest.Resource}):217    * *** \`unsent\`, \`opened\`, \`sent\`, \`loading\`, \`load\`, \`success\`218    * *** \`abort\`, \`timeout\`, \`statusError\`219    * ** readyState (available in {@link Resource} and {@link qx.io.rest.Resource}):220    * *** \`UNSENT\`221    * *** \`OPENED\`222    * *** \`HEADERS_RECEIVED\`223    * *** \`LOADING\`224    * *** \`DONE\`  225        `;226      var test = qx.tool.compiler.jsdoc.Parser.parseComment(text);227      console.log(test["@description"][0].body);228      this.assert(test["@description"][0].body !== "");229      this.assert(test["@description"][0].body.includes("<code>"));230      this.assert(test["@description"][0].body.includes("<ul>"));231      this.assert(test["@description"][0].body.includes("<li>"));232    },233    234    testCheckInlineCode: function() {235      let text = `236      * // Start a 5-second recurrent timer.237      * @require(qx.event.type.Pointer) TEST // load-time dependency for early native events238      `;239      var test = qx.tool.compiler.jsdoc.Parser.parseComment(text);240      console.log(test["@description"][0].body);241      this.assert(test["@description"][0].body === "");242      console.log(test["@require"][0].body);243      this.assert(test["@require"][0].body !== "");244      console.log(test["@require"][0].docComment);245      this.assert(test["@require"][0].docComment !== "");246    },247    248    249    testChecksJsdocParamParser: function() {250      var parser = new qx.tool.compiler.jsdoc.ParamParser();251      var pdoc = { name: "@param", body: "value {Boolean}, the new value of the widget" };252      parser.parseCommand(pdoc, "abc.def.Ghi", null);253      delete pdoc.name;254      delete pdoc.body;255      this.assert(qx.lang.Object.equals(pdoc, {256        "paramName": "value",257        "type": "Boolean",258        "description": ", the new value of the widget"259      }));260    261      pdoc = { name: "@param", body: "cellInfo {Map}\nInformation about the cell being renderered, including:\n<ul>\n<li>state</li>\n<li>rowDiv</li>\n<li>stylesheet</li>\n<li>element</li>\n<li>dataIndex</li>\n<li>cellData</li>\n<li>height</li>\n</ul>" };262      parser.parseCommand(pdoc, "abc.def.Ghi", null);263      delete pdoc.name;264      delete pdoc.body;265      this.assert(qx.lang.Object.equals(pdoc, {266        "paramName": "cellInfo",267        "type": "Map",268        "description": "\nInformation about the cell being renderered, including:\n<ul>\n<li>state</li>\n<li>rowDiv</li>\n<li>stylesheet</li>\n<li>element</li>\n<li>dataIndex</li>\n<li>cellData</li>\n<li>height</li>\n</ul>"269      }));270    },271    272    testChecksJsdocInlineCommentsAndUrls: function() {273      let result;274      275      result = qx.tool.compiler.jsdoc.Parser.parseComment(276        `277         * @ignore(abc,278         *    def,279         *    ghi)280        `);281      this.assert(qx.lang.Object.equals(result, {282        "@description": [283          {284            "name": "@description",285            "body": ""286          }287        ],288        "@ignore": [289          {290            "name": "@ignore",291            "body": "abc,\n    def,\n    ghi"292          }293        ]294      }));295          296      result = qx.tool.compiler.jsdoc.Parser.parseComment(297        `298         * @ignore(abc, // abc comment299         *    def, // def comment300         *    ghi)301        `);302      this.assert(qx.lang.Object.equals(result, {303        "@description": [304          {305            "name": "@description",306            "body": ""307          }308        ],309        "@ignore": [310          {311            "name": "@ignore",312            "body": "abc,\n    def,\n    ghi"313          }314        ]315      }));316      317      result = qx.tool.compiler.jsdoc.Parser.parseComment(`318         * @ignore(stuff) // comment about ignore stuff319         * http://abc.com // comment about url320         * http://dev.com 321         * 322         `);323      this.assert(qx.lang.Object.equals(result, {324        "@description": [325          {326            "name": "@description",327            "body": ""328          }329        ],330        "@ignore": [331          {...parse-comment.test.js
Source:parse-comment.test.js  
1const parseComment = require("../../lib/parse-comment");2describe("parseComment", () => {3  test("Basic intent to add", () => {4    expect(5      parseComment(6        `@all-contributors please add jakebolam for doc, infra and code`7      )8    ).toEqual({9      action: "add",10      who: "jakebolam",11      contributions: ["doc", "infra", "code"],12    });13  });14  test("Basic intent to add - ignore case (for action and contributions, NOT for user)", () => {15    expect(16      parseComment(17        `@all-contributors please Add jakeBolam for DOC, inFra and coDe`18      )19    ).toEqual({20      action: "add",21      who: "jakeBolam",22      contributions: ["doc", "infra", "code"],23    });24  });25  test("Basic intent to add - non name username", () => {26    expect(27      parseComment(`@all-contributors please add tbenning for design`)28    ).toEqual({29      action: "add",30      who: "tbenning",31      contributions: ["design"],32    });33  });34  test("Basic intent to add - capitalized username", () => {35    expect(36      parseComment(`@all-contributors please add Rbot25_RULES for tool`)37    ).toEqual({38      action: "add",39      who: "Rbot25_RULES",40      contributions: ["tool"],41    });42  });43  test("Basic intent to add - with plurals", () => {44    expect(parseComment(`@all-contributors please add dat2 for docs`)).toEqual({45      action: "add",46      who: "dat2",47      contributions: ["doc"],48    });49  });50  test("Support full words (like infrastructure)", () => {51    expect(52      parseComment(53        `@all-contributors please add jakebolam for infrastructure, documentation`54      )55    ).toEqual({56      action: "add",57      who: "jakebolam",58      contributions: ["infra", "doc"],59    });60  });61  test("Support adding people with mentions", () => {62    expect(63      parseComment(`@all-contributors please add @sinchang for infrastructure`)64    ).toEqual({65      action: "add",66      who: "sinchang",67      contributions: ["infra"],68    });69  });70  test("Support alternative sentences", () => {71    expect(72      parseComment(`@all-contributors add @sinchang for infrastructure`)73    ).toEqual({74      action: "add",75      who: "sinchang",76      contributions: ["infra"],77    });78    expect(79      parseComment(80        `Jane you are crushing it in documentation and your infrastructure work has been great too. Let's add jane.doe23 for her contributions. cc @all-contributors-bot`81      )82    ).toEqual({83      action: "add",84      who: "jane.doe23",85      contributions: ["doc", "infra"],86    });87  });88  test("Support split words (like user testing)", () => {89    expect(90      parseComment(91        `@all-contributors please add jakebolam for infrastructure, fund finding`92      )93    ).toEqual({94      action: "add",95      who: "jakebolam",96      contributions: ["infra", "fundingFinding"],97    });98    expect(99      parseComment(100        `@all-contributors please add jakebolam for infrastructure, user testing and testing`101      )102    ).toEqual({103      action: "add",104      who: "jakebolam",105      contributions: ["infra", "userTesting", "test"],106    });107  });108  test("Support split words types that are referenced via other terms (e.g. a plural split word)", () => {109    expect(110      parseComment(111        `@all-contributors please add @jakebolam for infrastructure, funds`112      )113    ).toEqual({114      action: "add",115      who: "jakebolam",116      contributions: ["infra", "fundingFinding"],117    });118  });119  test("Intent unknown", () => {120    expect(parseComment(`@all-contributors please lollmate for tool`)).toEqual({121      action: false,122    });123  });124  test("Ensure (trailing) hyphens are not discarded", () => {125    expect(126      parseComment(`@all-contributors please add @jakebolam- for testing`)127    ).toEqual({128      action: "add",129      who: "jakebolam-",130      contributions: ["test"],131    });132    expect(133      parseComment(134        `@all-contributors please add @jakebolam-jakebolam for bugs, ideas`135      )136    ).toEqual({137      action: "add",138      who: "jakebolam-jakebolam",139      contributions: ["bug", "ideas"],140    });141  });142  test("Contribution unknown", () => {143    expect(144      parseComment(`@all-contributors please add @octocat for unknown`)145    ).toEqual({146      action: "add",147      who: "octocat",148      contributions: [],149    });150  });...messageCommentsSrv.js
Source:messageCommentsSrv.js  
1committeeApp.factory("messageCommentsSrv", function ($q) {2    class Comment {3        constructor(parseComment) {4            this.text = parseComment.get("text");5            this.username = parseComment.get("userId").get("name");6            this.date = parseComment.get("createdAt");7            this.commentId = parseComment.id;8        }9    }10    function getMessageComments(message) {11        var async = $q.defer();12        var comments = [];13        const MessageComment = Parse.Object.extend('MessageComment');14        const query = new Parse.Query(MessageComment);15        query.equalTo("messageId", message.parseMessage);16        query.find().then((results) => {17            results.forEach(parseComment => {18                var comment = new Comment(parseComment);19                comments.push(comment)20            });21            comments.sort(function (a, b) {22                return b.date - a.date;23            });24            async.resolve(comments);25        }, (error) => {26            async.reject(error);27        });28        return async.promise;29    }30    function createComment(text, message) {31        var async = $q.defer();32        const MessageComment = Parse.Object.extend('MessageComment');33        const myNewComment = new MessageComment();34        myNewComment.set('text', text);35        myNewComment.set('messageId', message.parseMessage);36        myNewComment.set('userId', Parse.User.current());37        myNewComment.save().then(38            (result) => {39                var comment = new Comment(result);40                async.resolve(comment);41            },42            (error) => {43                async.reject(error);44                console.error('Error while creating MessageComment: ', error);45            }46        );47        return async.promise;48    }49    function deleteMessageComments(comments) {50        var async = $q.defer();51        var commentPromises = []52        comments.forEach((comment) =>53            commentPromises.push(deleteComment(comment.commentId))54        );55        // neutralize rejected deletetions56        commentPromises = commentPromises.map(57            promise => promise.catch(() => null)58        );59        // wait for all promises, while the neutrailized promises (which rejected...) 60        $q.all(commentPromises).then(results => {61            var successCounter = 0;62            var failCounter = 0;63            for (let index = 0; index < results.length; index++) {64                if (results[index] == null || !results[index])65                    failCounter++;66                else67                    successCounter++;68            }69            async.resolve([successCounter, failCounter]);70        });71        return async.promise;72    }73    function deleteComment(commentId) {74        var async = $q.defer();75        const MessageComment = Parse.Object.extend('MessageComment');76        const query = new Parse.Query(MessageComment);77        // here you put the objectId that you want to delete78        query.get(commentId).then((object) => {79            object.destroy().then((response) => {80                // console.log('Deleted MessageComment', response);81                async.resolve(commentId);82            }, (error) => {83                console.error('Error while deleting MessageComment', error);84                (error) => async.reject(error);85            });86        }, (error) => {87            console.error('Error while getting MessageComment', error);88            async.reject(error);89        });90        return async.promise;91    }92    return {93        getMessageComments: getMessageComments,94        createComment: createComment,95        deleteMessageComments: deleteMessageComments96    }...issueCommentsSrv.js
Source:issueCommentsSrv.js  
1committeeApp.factory("issueCommentsSrv", function ($q) {2    class Comment {3        constructor(parseComment) {4            this.text = parseComment.get("text");5            this.username = parseComment.get("userId").get("name");6            this.date = parseComment.get("createdAt");7            this.commentId = parseComment.id;8        }9    }10    function getIssueComments(issue) {11        var async = $q.defer();12        var comments = [];13        const IssueComment = Parse.Object.extend('IssueComment');14        const query = new Parse.Query(IssueComment);15        query.equalTo("issueId", issue.parseIssue);16        query.find().then((results) => {17            results.forEach(parseComment => {18                var comment = new Comment(parseComment);19                comments.push(comment)20            });21            comments.sort(function (a, b) {22                return b.date - a.date;23            });24            async.resolve(comments);25        }, (error) => {26            async.reject(error);27        });28        return async.promise;29    }30    function createComment(text, issue) {31        var async = $q.defer();32        const IssueComment = Parse.Object.extend('IssueComment');33        const myNewComment = new IssueComment();34        myNewComment.set('text', text);35        myNewComment.set('issueId', issue.parseIssue);36        myNewComment.set('userId', Parse.User.current());37        myNewComment.save().then(38            (result) => {39                var comment = new Comment(result);40                async.resolve(comment);41            },42            (error) => {43                async.reject(error);44                console.error('Error while creating IssueComment: ', error);45            }46        );47        return async.promise;48    }49    function deleteIssueComments(comments) {50        var async = $q.defer();51        var commentPromises = []52        comments.forEach((comment) =>53            commentPromises.push(deleteComment(comment.commentId))54        );55        // neutralize rejected deletetions56        commentPromises = commentPromises.map(57            promise => promise.catch(() => null)58        );59        // wait for all promises, while the neutrailized promises (which rejected...) 60        $q.all(commentPromises).then(results => {61            var successCounter = 0;62            var failCounter = 0;63            for (let index = 0; index < results.length; index++) {64                if (results[index] == null || !results[index])65                    failCounter++;66                else67                    successCounter++;68            }69            async.resolve([successCounter, failCounter]);70        });71        return async.promise;72    }73    function deleteComment(commentId) {74        var async = $q.defer();75        const IssueComment = Parse.Object.extend('IssueComment');76        const query = new Parse.Query(IssueComment);77        // here you put the objectId that you want to delete78        query.get(commentId).then((object) => {79            object.destroy().then((response) => {80                // console.log('Deleted IssueComment', response);81                async.resolve(commentId);82            }, (error) => {83                console.error('Error while deleting IssueComment', error);84                (error) => async.reject(error);85            });86        }, (error) => {87            console.error('Error while getting IssueComment', error);88            async.reject(error);89        });90        return async.promise;91    }92    return {93        getIssueComments: getIssueComments,94        createComment: createComment,95        deleteIssueComments: deleteIssueComments96    }...parseComment.js
Source:parseComment.js  
2let parseComment = require('../../src/parseComment');3let assert = require('assert');4describe('parseComment', () => {5    it('base', () => {6        assert.deepEqual(parseComment('/**/'), [{7            content: '/**/',8            next: '',9            paraBlocks: [['']]10        }]);11    });12    it('base2', () => {13        assert.deepEqual(parseComment('/**/abc/**/'), [{14            content: '/**/',15            next: 'abc',16            paraBlocks: [['']]17        }, {18            content: '/**/',19            next: '',20            paraBlocks: [['']]21        }]);22    });23    it('base3', () => {24        assert.deepEqual(parseComment('/*#test*/'), [{25            content: '/*#test*/',26            next: '',27            paraBlocks: [28                ['#test']29            ]30        }]);31    });32    it('wipe *', () => {33        assert.deepEqual(parseComment('/*****#test*****/'), [{34            content: '/*****#test*****/',35            next: '',36            paraBlocks: [37                ['#test****']38            ]39        }]);40    });41    it('seperate by #', () => {42        assert.deepEqual(parseComment('/*#test1\n#test2*/'), [{43            content: '/*#test1\n#test2*/',44            next: '',45            paraBlocks: [46                ['#test1'],47                ['#test2']48            ]49        }]);50    });51    it('seperate by # with lines', () => {52        assert.deepEqual(parseComment('/**\n#test1\n*abc\n#test2\n*def\n*lkl\n*/'), [{53            content: '/**\n#test1\n*abc\n#test2\n*def\n*lkl\n*/',54            next: '',55            paraBlocks: [56                [''],57                ['#test1', 'abc'],58                ['#test2', 'def', 'lkl', '']59            ]60        }]);61    });...testParser.js
Source:testParser.js  
...3let testParser = require('../../src/testParser');4let assert = require('assert');5describe('index', () => {6    it('base', () => {7        assert.deepEqual(testParser(parseComment('/*## test\n[[1, 2], 3]*/\n let a = () => {}')).tests, [{8            sample: '[[1, 2], 3]',9            testVar: 'a',10            testVariables: {11                test: '',12                tar: 'function'13            }14        }]);15    });16    it('end line', () => {17        assert.deepEqual(testParser(parseComment('/*## test\n[[1, 2], 3]\n<!--testEnd-->other things*/\n let a = () => {}')).tests, [{18            sample: '[[1, 2], 3]',19            testVar: 'a',20            testVariables: {21                test: '',22                tar: 'function'23            }24        }]);25    });26    it('missing variable name', (done) => {27        try {28            testParser(parseComment('/*## test\n[[1, 2], 3]*/\n() => {}')).tests;29        } catch (err) {30            assert.equal(err.toString().indexOf('could not find function name') !== -1, true);31            done();32        }33    });34    it('test title', () => {35        assert.deepEqual(testParser(parseComment('/*## test a=b c=d\n[[1, 2], 3]*/\n let a = () => {}')).tests, [{36            sample: '[[1, 2], 3]',37            testVar: 'a',38            testVariables: {39                test: '',40                a: 'b',41                c: 'd',42                tar: 'function'43            }44        }]);45    });46    it('test title2', () => {47        assert.deepEqual(testParser(parseComment('/*## testenv=bash\n[[1, 2], 3]*/\n let a = () => {}')).tests, []);48    });...Using AI Code Generation
1const { parseComment } = require('playwright-core/lib/utils/stackTrace');2const { parseComment } = require('playwright-core/lib/utils/stackTrace');3const { test } = require('@playwright/test');4test('example test', async ({ page }) => {5  await page.click('text=Get started');6  const comment = parseComment(new Error().stack);7  console.log(comment);8});9const { test } = require('@playwright/test');10test('example test', async ({ page }, { myParam }) => {11  await page.click('text=Get started');12  console.log(myParam);13});14const { test } = require('@playwright/test');15test('example test', async ({ page }, { myParam }) => {16  await page.click('text=Get started');17  console.log(myParam);18}, {19    params: {20    }21});22const { test, testData } = require('@playwright/test');23testData({24});25test('example test', asyncUsing AI Code Generation
1const { parseComment } = require('@playwright/test/lib/utils/stackTrace');2const { test } = require('@playwright/test');3const path = require('path');4test('test', async ({ page }) => {5  const { title, file, line, column } = parseComment(test.fixtures[0].fn);6});7#### test(name, fn, options)Using AI Code Generation
1const { parseComment } = require('@playwright/test/lib/utils/stackTrace');2const { stackTrace } = require('@playwright/test/lib/utils/stackTrace');3const { test } = require('@playwright/test');4test('test', async ({ page }) => {5  const element = await page.locator('text="GitHub"');6  await element.click();7  const title = await page.locator('css=h1').first().innerText();8  console.log(title);9  const result = parseComment(stackTrace());10  console.log(result);11});12    {13    }14const { test } = require('@playwright/test');15test('test', async ({ page }) => {16  const element = await page.locator('text="GitHub"');17  await element.click();18  const title = await page.locator('css=h1').first().innerText();19  console.log(title);20});Using AI Code Generation
1const { parseComment } = require('playwright/lib/utils/utils');2   * @param {ClickOptions=} options3   * @returns {Promise<void>}4  async click(selector, options = {}) {5    await this._wrapApiCall('page.click', async () => {6      const handle = await this.$(selector);7      if (!handle)8        throw new Error('Element not found to click: ' + selector);9      await handle.click(options);10      await handle.dispose();11    });12  }13`;14const result = parseComment(comment);15console.log(result);16{17    {18    },19    {20    }21  "returns": {22  }23}24  -p, --playwright <playwright>  Path to playwright package (default: "playwright")25  -o, --output <output>          Path to output file (default: "playwright-api-docs.json")Using AI Code Generation
1const { parseComment } = require('playwright-core/lib/test/workerRunner');2console.log(parseComment('/* foo */'));3{4  "annotations": {},5  "params": {}6}Using AI Code Generation
1const parseComment = require('playwright/lib/utils/parseComment');2   * @param {string} username3   * @param {string} password4   * @param {boolean} rememberMe5`;6const parsed = parseComment(comment);7console.log(parsed);Using AI Code Generation
1const { parseComment } = require('playwright/lib/utils/stackTrace');2        at Object.<anonymous> (/Users/username/path/to/file.js:1:1)3        at Module._compile (internal/modules/cjs/loader.js:999:30)4        at Object.Module._extensions..js (internal/modules/cjs/loader.js:1027:10)5        at Module.load (internal/modules/cjs/loader.js:863:32)6        at Function.Module._load (internal/modules/cjs/loader.js:708:14)7        at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:60:12)8`;9const result = parseComment(stack);10#### `getPlaywrightError(error)`11#### `getPlaywrightErrorMessage(error)`12#### `getPlaywrightStack(error)`13#### `getCallMetadata(options)`LambdaTest’s Playwright tutorial will give you a broader idea about the Playwright automation framework, its unique features, and use cases with examples to exceed your understanding of Playwright testing. This tutorial will give A to Z guidance, from installing the Playwright framework to some best practices and advanced concepts.
Get 100 minutes of automation test minutes FREE!!
