var ngdoc = require('../src/ngdoc.js'); var DOM = require('../src/dom.js').DOM; var gruntUtil = require('../../lib/grunt/utils.js'); describe('ngdoc', function() { var Doc = ngdoc.Doc; var dom; beforeEach(function() { dom = new DOM(); this.addMatchers({ toContain: function(text) { this.actual = this.actual.toString(); return this.actual.indexOf(text) > -1; } }); }); describe('Doc', function() { describe('metadata', function() { it('should find keywords and filter ignored words', function() { expect(new Doc('\nHello: World! @ignore. $abc').keywords()).toEqual('$abc hello world'); expect(new Doc('The `ng:class-odd` and').keywords()).toEqual('ng:class-odd'); }); it('should get property and methods', function() { var doc = new Doc('Document'); doc.properties.push(new Doc('Proprety')); doc.properties.push(new Doc('Method')); expect(doc.keywords()).toEqual('document method proprety'); }); it('should have shortName', function() { var d1 = new Doc('@name a.b.c').parse(); var d2 = new Doc('@name a.b.ng-c').parse(); var d3 = new Doc('@name some text: more text').parse(); expect(ngdoc.metadata([d1])[0].shortName).toEqual('a.b.c'); expect(ngdoc.metadata([d2])[0].shortName).toEqual('a.b.ng-c'); expect(ngdoc.metadata([d3])[0].shortName).toEqual('more text'); }); }); describe('parse', function() { it('should convert @names into properties', function() { var doc = new Doc('\n@name name\n@desc\ndesc\ndesc2\n@dep\n'); doc.parse(); expect(doc.name).toEqual('name'); expect(doc.desc).toEqual('desc\ndesc2'); expect(doc.dep).toEqual(''); }); it('should parse parameters', function() { var doc = new Doc( '@name a\n' + '@param {*} a short\n' + '@param {Type} b med\n' + '@param {Class=} [c=2] long\nline\n' + '@param {function(number, string=)} d fn with optional arguments'); doc.parse(); expect(doc.param).toEqual([ {name:'a', description:'

short

\n
', type:'*', optional:false, 'default':undefined}, {name:'b', description:'

med

\n
', type:'Type', optional:false, 'default':undefined}, {name:'c', description:'

long\nline

\n
', type:'Class', optional:true, 'default':'2'}, {name:'d', description:'

fn with optional arguments

\n
', type: 'function(number, string=)', optional: false, 'default':undefined} ]); }); it('should parse return', function() { var doc = new Doc('@name a\n@returns {Type} text *bold*.'); doc.parse(); expect(doc.returns).toEqual({ type: 'Type', description: '

text bold.

\n
' }); }); it('should parse filename', function() { var doc = new Doc('@name friendly name', 'docs/a.b.ngdoc', 1); doc.parse(0); expect(doc.id).toEqual('a.b'); expect(doc.name).toEqual('friendly name'); }); it('should store all links', function() { var doc = new Doc('@name a\n@description {@link api/angular.link}'); doc.parse(); expect(doc.links).toContain('api/angular.link'); }); describe('convertUrlToAbsolute', function() { var doc; beforeEach(function() { doc = new Doc({section: 'section'}); }); it('should not change absolute url', function() { expect(doc.convertUrlToAbsolute('guide/index')).toEqual('guide/index'); }); it('should prepend current section to relative url', function() { expect(doc.convertUrlToAbsolute('angular.widget')).toEqual('section/angular.widget'); }); it('should change id to index if not specified', function() { expect(doc.convertUrlToAbsolute('guide/')).toEqual('guide/index'); }); }); describe('sorting', function() { function property(name) { return function(obj) {return obj[name];}; } var dev_guide_overview = new Doc({ngdoc:'overview', id:'dev_guide.overview', text: ''}); var dev_guide_bootstrap = new Doc({ngdoc:'function', id:'dev_guide.bootstrap', text: ''}); it('should put angular.fn() in front of dev_guide.overview, etc', function() { expect(ngdoc.metadata([dev_guide_overview, dev_guide_bootstrap]).map(property('id'))) .toEqual(['dev_guide.overview', 'dev_guide.bootstrap']); }); }); }); }); describe('markdown', function() { it('should not replace anything in
, but escape the html escape the content', function() {
      expect(new Doc().markdown('bah x\n
\nangular.k\n
\n asdf x')). toEqual( '

bah x\n' + '

\n' +
            '<b>angular</b>.k\n' +
            '
\n' + ' asdf x

\n
'); }); it('should wrap everything inside a container tag', function() { var doc = new Doc('@name superman').parse(); var content = doc.markdown('hello'); expect(content).toMatch('

hello

\n
'); }); it('should use the content before a colon as the name prefix for the className of the tag container', function() { var doc = new Doc('@name super: man').parse(); var content = doc.markdown('hello'); expect(content).toMatch('

hello

\n
'); }); it('should replace text between two
 tags', function() {
      expect(new Doc().markdown('
x
\n# One\n
b
')). toMatch('
\n

One

\n/); }); it('should ignore nested doc widgets', function() { expect(new Doc().markdown( 'before\n
\n' + '
angular.module("ngLocale", [], ["$provide", function($provide) { var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"}; $provide.value("$locale", { "DATETIME_FORMATS": { "AMPMS": { "0": "\u0635", "1": "\u0645" }, "DAY": { "0": "\u0627\u0644\u0623\u062d\u062f", "1": "\u0627\u0644\u0627\u062b\u0646\u064a\u0646", "2": "\u0627\u0644\u062b\u0644\u0627\u062b\u0627\u0621", "3": "\u0627\u0644\u0623\u0631\u0628\u0639\u0627\u0621", "4": "\u0627\u0644\u062e\u0645\u064a\u0633", "5": "\u0627\u0644\u062c\u0645\u0639\u0629", "6": "\u0627\u0644\u0633\u0628\u062a" }, "MONTH": { "0": "\u064a\u0646\u0627\u064a\u0631", "1": "\u0641\u0628\u0631\u0627\u064a\u0631", "2": "\u0645\u0627\u0631\u0633", "3": "\u0623\u0628\u0631\u064a\u0644", "4": "\u0645\u0627\u064a\u0648", "5": "\u064a\u0648\u0646\u064a\u0648", "6": "\u064a\u0648\u0644\u064a\u0648", "7": "\u0623\u063a\u0633\u0637\u0633", "8": "\u0633\u0628\u062a\u0645\u0628\u0631", "9": "\u0623\u0643\u062a\u0648\u0628\u0631", "10": "\u0646\u0648\u0641\u0645\u0628\u0631", "11": "\u062f\u064a\u0633\u0645\u0628\u0631" }, "SHORTDAY": { "0": "\u0627\u0644\u0623\u062d\u062f", "1": "\u0627\u0644\u0627\u062b\u0646\u064a\u0646", "2": "\u0627\u0644\u062b\u0644\u0627\u062b\u0627\u0621", "3": "\u0627\u0644\u0623\u0631\u0628\u0639\u0627\u0621", "4": "\u0627\u0644\u062e\u0645\u064a\u0633", "5": "\u0627\u0644\u062c\u0645\u0639\u0629", "6": "\u0627\u0644\u0633\u0628\u062a" }, "SHORTMONTH": { "0": "\u064a\u0646\u0627\u064a\u0631", "1": "\u0641\u0628\u0631\u0627\u064a\u0631", "2": "\u0645\u0627\u0631\u0633", "3": "\u0623\u0628\u0631\u064a\u0644", "4": "\u0645\u0627\u064a\u0648", "5": "\u064a\u0648\u0646\u064a\u0648", "6": "\u064a\u0648\u0644\u064a\u0648", "7": "\u0623\u063a\u0633\u0637\u0633", "8": "\u0633\u0628\u062a\u0645\u0628\u0631", "9": "\u0623\u0643\u062a\u0648\u0628\u0631", "10": "\u0646\u0648\u0641\u0645\u0628\u0631", "11": "\u062f\u064a\u0633\u0645\u0628\u0631" }, "fullDate": "EEEE\u060c d MMMM\u060c y", "longDate": "d MMMM\u060c y", "medium": "dd\u200f/MM\u200f/yyyy h:mm:ss a", "mediumDate": "dd\u200f/MM\u200f/yyyy", "mediumTime": "h:mm:ss a", "short": "d\u200f/M\u200f/yyyy h:mm a", "shortDate": "d\u200f/M\u200f/yyyy", "shortTime": "h:mm a" }, "NUMBER_FORMATS": { "CURRENCY_SYM": "\u00a3", "DECIMAL_SEP": "\u066b", "GROUP_SEP": "\u066c", "PATTERNS": { "0": { "gSize": 0, "lgSize": 0, "macFrac": 0, "maxFrac": 3, "minFrac": 0, "minInt": 1, "negPre": "", "negSuf": "-", "posPre": "", "posSuf": "" }, "1": { "gSize": 0, "lgSize": 0, "macFrac": 0, "maxFrac": 2, "minFrac": 2, "minInt": 1, "negPre": "\u00a4\u00a0", "negSuf": "-", "posPre": "\u00a4\u00a0", "posSuf": "" } } }, "id": "ar-sd", "pluralCat": function (n) { if (n == 0) { return PLURAL_CATEGORY.ZERO; } if (n == 1) { return PLURAL_CATEGORY.ONE; } if (n == 2) { return PLURAL_CATEGORY.TWO; } if (n == (n | 0) && n % 100 >= 3 && n % 100 <= 10) { return PLURAL_CATEGORY.FEW; } if (n == (n | 0) && n % 100 >= 11 && n % 100 <= 99) { return PLURAL_CATEGORY.MANY; } return PLURAL_CATEGORY.OTHER;} }); }]);
ion: 'param desc'} ], returns: {type: 'number', description: 'return desc'} }); doc.html_usage_function(dom); expect(dom).toContain('name([a][, b], c)'); //TODO(i) the comma position here is lame expect(dom).toContain('param desc'); expect(dom).toContain('(optional)'); expect(dom).toContain('return desc'); }); }); describe('filter', function() { it('should format', function() { var doc = new Doc({ ngdoc:'formatter', shortName:'myFilter', param: [ {name:'a', type:'string'}, {name:'b', type:'string'} ] }); doc.html_usage_filter(dom); expect(dom).toContain('myFilter_expression | myFilter:b'); expect(dom).toContain('$filter(\'myFilter\')(a, b)'); }); }); describe('property', function() { it('should format', function() { var doc = new Doc({ ngdoc:'property', name:'myProp', type:'string', returns:{type: 'type', description: 'description'} }); doc.html_usage_property(dom); expect(dom).toContain('myProp'); expect(dom).toContain('type'); expect(dom).toContain('description'); }); }); }); });