From ba6b68b6ae2bb2400a75ca2834fee47bfd60f1c6 Mon Sep 17 00:00:00 2001 From: Misko Hevery Date: Mon, 31 Jan 2011 16:21:29 -0800 Subject: changed the documentation @example to use --- docs/angular.filter.ngdoc | 15 +- docs/angular.formatter.ngdoc | 70 ++--- docs/angular.service.ngdoc | 93 +++--- docs/angular.validator.ngdoc | 44 +-- docs/angular.widget.ngdoc | 33 ++- docs/spec/domSpec.js | 28 -- docs/spec/ngdocSpec.js | 70 +---- docs/src/dom.js | 19 +- docs/src/ngdoc.js | 118 ++++---- src/Angular.js | 92 +++--- src/Compiler.js | 68 +++-- src/Scope.js | 46 +-- src/angular-mocks.js | 26 +- src/apis.js | 530 +++++++++++++++++---------------- src/directives.js | 676 +++++++++++++++++++++++-------------------- src/filters.js | 351 +++++++++++----------- src/formatters.js | 197 +++++++------ src/services.js | 233 +++++++++------ src/validators.js | 309 +++++++++++--------- src/widgets.js | 554 ++++++++++++++++++----------------- 20 files changed, 1880 insertions(+), 1692 deletions(-) diff --git a/docs/angular.filter.ngdoc b/docs/angular.filter.ngdoc index 9d1191c5..5d4f5940 100644 --- a/docs/angular.filter.ngdoc +++ b/docs/angular.filter.ngdoc @@ -46,12 +46,13 @@ You can use these variables in the function: the DOM in addition to transforming the input. -@exampleDescription +@example The following example filter reverses a text string. In addition, it conditionally makes the text upper-case (to demonstrate optional arguments) and assigns color (to demonstrate DOM modification). -@example + + -Formatted: - -
+ angular.formatter('reverse', { + parse: function(value){ + return reverse(value||'').toUpperCase(); + }, + format: function(value){ + return reverse(value||'').toLowerCase(); + } + }); + -Stored: -
-
{{data}}
+ Formatted: + +
+ Stored: +
+
{{data}}
+
+ + it('should store reverse', function(){ + expect(element('.doc-example input:first').val()).toEqual('angular'); + expect(element('.doc-example input:last').val()).toEqual('RALUGNA'); -@scenario -it('should store reverse', function(){ - expect(element('.doc-example input:first').val()).toEqual('angular'); - expect(element('.doc-example input:last').val()).toEqual('RALUGNA'); + this.addFutureAction('change to XYZ', function($window, $document, done){ + $document.elements('.doc-example input:last').val('XYZ').trigger('change'); + done(); + }); + expect(element('.doc-example input:first').val()).toEqual('zyx'); + }); + +
- this.addFutureAction('change to XYZ', function($window, $document, done){ - $document.elements('.doc-example input:last').val('XYZ').trigger('change'); - done(); - }); - expect(element('.doc-example input:first').val()).toEqual('zyx'); -}); diff --git a/docs/angular.service.ngdoc b/docs/angular.service.ngdoc index 4e4810f9..0d3406e5 100644 --- a/docs/angular.service.ngdoc +++ b/docs/angular.service.ngdoc @@ -17,22 +17,22 @@ services if needed. Like other core angular variables and identifiers, the built-in services always start with `$`. - * `{@link angular.service.$browser $browser}` - * `{@link angular.service.$window $window}` - * `{@link angular.service.$document $document}` - * `{@link angular.service.$location $location}` - * `{@link angular.service.$log $log}` - * `{@link angular.service.$exceptionHandler $exceptionHandler}` - * `{@link angular.service.$hover $hover}` - * `{@link angular.service.$invalidWidgets $invalidWidgets}` - * `{@link angular.service.$route $route}` - * `{@link angular.service.$xhr $xhr}` - * `{@link angular.service.$xhr.error $xhr.error}` - * `{@link angular.service.$xhr.bulk $xhr.bulk}` - * `{@link angular.service.$xhr.cache $xhr.cache}` - * `{@link angular.service.$resource $resource}` - * `{@link angular.service.$cookies $cookies}` - * `{@link angular.service.$cookieStore $cookieStore}` + * {@link angular.service.$browser $browser} + * {@link angular.service.$window $window} + * {@link angular.service.$document $document} + * {@link angular.service.$location $location} + * {@link angular.service.$log $log} + * {@link angular.service.$exceptionHandler $exceptionHandler} + * {@link angular.service.$hover $hover} + * {@link angular.service.$invalidWidgets $invalidWidgets} + * {@link angular.service.$route $route} + * {@link angular.service.$xhr $xhr} + * {@link angular.service.$xhr.error $xhr.error} + * {@link angular.service.$xhr.bulk $xhr.bulk} + * {@link angular.service.$xhr.cache $xhr.cache} + * {@link angular.service.$resource $resource} + * {@link angular.service.$cookies $cookies} + * {@link angular.service.$cookieStore $cookieStore} # Writing your own custom services angular provides only set of basic services, so for any nontrivial application it will be necessary @@ -138,29 +138,38 @@ myController.$inject = ['$location', '$log']; @example - - -
-

Let's try this simple notify service, injected into the controller...

- - -
+ + + + +
+

Let's try this simple notify service, injected into the controller...

+ + +
+
+ + it('should test service', function(){ + expect(element(':input[name=message]').val()).toEqual('test'); + }); + +
diff --git a/docs/angular.validator.ngdoc b/docs/angular.validator.ngdoc index 5501cc56..96b1e76a 100644 --- a/docs/angular.validator.ngdoc +++ b/docs/angular.validator.ngdoc @@ -50,24 +50,28 @@ UPS tracking number. default. @example - - - -@scenario -it('should validate correct UPS tracking number', function() { - expect(element('input[name=trackNo]').attr('class')). - not().toMatch(/ng-validation-error/); -}); + + + + + + + it('should validate correct UPS tracking number', function() { + expect(element('input[name=trackNo]').attr('class')). + not().toMatch(/ng-validation-error/); + }); -it('should not validate in correct UPS tracking number', function() { - input('trackNo').enter('foo'); - expect(element('input[name=trackNo]').attr('class')). - toMatch(/ng-validation-error/); -}); + it('should not validate in correct UPS tracking number', function() { + input('trackNo').enter('foo'); + expect(element('input[name=trackNo]').attr('class')). + toMatch(/ng-validation-error/); + }); + + diff --git a/docs/angular.widget.ngdoc b/docs/angular.widget.ngdoc index 5942d933..6360f8ea 100644 --- a/docs/angular.widget.ngdoc +++ b/docs/angular.widget.ngdoc @@ -57,17 +57,22 @@ angular.widget('@my:watch', function(expression, compileElement) { @example - - - + + + + + + + + diff --git a/docs/spec/domSpec.js b/docs/spec/domSpec.js index f9308ed6..3fda656f 100644 --- a/docs/spec/domSpec.js +++ b/docs/spec/domSpec.js @@ -7,34 +7,6 @@ describe('dom', function(){ dom = new DOM(); }); - describe('example', function(){ - it('should render code, live, test', function(){ - dom.example('desc', 'src', 'scenario'); - expect(dom.toString()).toEqual( - '

Example

\n' + - '
' + - 'descsrc\n' + - 'scenario\n'+ - '\n' + - '
\n'); - }); - - it('should render non-live, test with description', function(){ - dom.example('desc', 'src', false); - expect(dom.toString()).toEqual('

Example

\n' + - '
' + - 'desc
' + - '
src
\n' + - '
\n' + - '
\n'); - }); - - it('should render non-live, test', function(){ - dom.example('desc', 'src', false); - expect(dom.toString()).toContain('
src
'); - }); - }); - describe('h', function(){ it('should render using function', function(){ diff --git a/docs/spec/ngdocSpec.js b/docs/spec/ngdocSpec.js index d912bf3a..69bb5db3 100644 --- a/docs/spec/ngdocSpec.js +++ b/docs/spec/ngdocSpec.js @@ -74,12 +74,6 @@ describe('ngdoc', function(){ }); }); - it('should not remove extra line breaks', function(){ - var doc = new Doc('@example\nA\n\nB'); - doc.parse(); - expect(doc.example).toEqual('A\n\nB'); - }); - it('should parse filename', function(){ var doc = new Doc('@name friendly name', 'docs/a.b.ngdoc', 1); doc.parse(0); @@ -128,32 +122,14 @@ describe('ngdoc', function(){ }); }); - describe('scenario', function(){ - it('should render from @example/@scenario and ', function(){ - var doc = new Doc( - '@id id\n' + - '@description scenario0' + - '@example exempleText\n' + - '@scenario scenario1\n' + - '@scenario scenario2').parse(); - expect(ngdoc.scenarios([doc])).toContain('describe("id"'); - expect(ngdoc.scenarios([doc])).toContain('navigateTo("index.html#!id")'); - expect(ngdoc.scenarios([doc])).toContain('\n scenario0\n'); - expect(ngdoc.scenarios([doc])).toContain('\n scenario1\n'); - expect(ngdoc.scenarios([doc])).toContain('\n scenario2\n'); - }); - }); - describe('markdown', function(){ - var markdown = ngdoc.markdown; - it('should replace angular in markdown', function(){ - expect(markdown('')). + expect(new Doc().markdown('')). toEqual('

<angular/>

'); }); it('should not replace anything in
, but escape the html escape the content', function(){
-      expect(markdown('bah x\n
\nangular.k\n
\n asdf x')). + expect(new Doc().markdown('bah x\n
\nangular.k\n
\n asdf x')). toEqual( '

bah x

' + '
\n' +
@@ -163,7 +139,7 @@ describe('ngdoc', function(){
     });
 
     it('should replace text between two 
 tags', function() {
-      expect(markdown('
x
# One
b
')). + expect(new Doc().markdown('
x
# One
b
')). toMatch('

One

text {{ abc }}

'); }); - }); - describe('@exampleDescription', function(){ - it('should render example description', function(){ - var doc = new Doc('@exampleDescription some\n text'); - doc.ngdoc = "filter"; - doc.parse(); - expect(doc.html()).toContain('

some\n text'); - }); - - it('should alias @exampleDescription to @exampleDesc', function(){ - var doc = new Doc('@exampleDesc some\n text'); - doc.ngdoc = "filter"; - doc.parse(); - expect(doc.html()).toContain('

some\n text'); + it('should support doc:example', function(){ + var doc = new Doc('@ngdoc overview\n@example \n' + + '\n' + + ' \n' + + ' \n' + + '').parse(); + var html = doc.html(); + expect(html).toContain('<escapeme>'); + expect(html).toContain('<scenario>'); + expect(doc.scenarios).toEqual(['']); }); - - it('should render description in related method', function(){ - var doc = new Doc('').parse(); - doc.ngdoc = 'service'; - doc.methods = [ - new Doc('@ngdoc method\n@exampleDescription MDesc\n@example MExmp').parse()]; - doc.properties = [ - new Doc('@ngdoc property\n@exampleDescription PDesc\n@example PExmp').parse()]; - expect(doc.html()).toContain('

MDesc

' + - '
MExmp
'); - expect(doc.html()).toContain('

PDesc

' + - '
PExmp
'); - }); - }); describe('@depricated', function() { diff --git a/docs/src/dom.js b/docs/src/dom.js index 7708cbc9..4210d687 100644 --- a/docs/src/dom.js +++ b/docs/src/dom.js @@ -74,25 +74,8 @@ DOM.prototype = { }); }, - example: function(description, source, scenario) { - if (description || source || scenario) { - this.h('Example', function(){ - if (description) - this.html(description); - if (scenario === false) { - this.code(source); - } else { - this.tag('doc:example', function(){ - if (source) this.tag('doc:source', source); - if (scenario) this.tag('doc:scenario', scenario); - }); - } - }); - } - }, - h: function(heading, content, fn){ - if (content==undefined || content && content.legth == 0) return; + if (content==undefined || (content instanceof Array && content.length == 0)) return; this.headingDepth++; this.tag('h' + this.headingDepth, heading); var className = typeof heading == 'string' diff --git a/docs/src/ngdoc.js b/docs/src/ngdoc.js index a3a037cd..d90f8d3d 100644 --- a/docs/src/ngdoc.js +++ b/docs/src/ngdoc.js @@ -7,7 +7,6 @@ var DOM = require('dom.js').DOM; var htmlEscape = require('dom.js').htmlEscape; var NEW_LINE = /\n\r?/; -exports.markdown = markdown; exports.trim = trim; exports.metadata = metadata; exports.scenarios = scenarios; @@ -25,6 +24,11 @@ function Doc(text, file, line) { this.file = file; this.line = line; } + this.scenarios = this.scenarios || []; + this.requires = this.requires || []; + this.param = this.param || []; + this.properties = this.properties || []; + this.methods = this.methods || []; } Doc.METADATA_IGNORE = (function(){ var words = require('fs').readFileSync(__dirname + '/ignore.words', 'utf8'); @@ -53,16 +57,53 @@ Doc.prototype = { return words.join(' '); }, + markdown: function (text) { + var self = this; + var IS_URL = /^(https?:\/\/|ftps?:\/\/|mailto:)/; + var IS_ANGULAR = /^angular\./; + if (!text) return text; + var parts = text.split(/(
[\s\S]*?<\/pre>|[\s\S]*?<\/doc:example>)/),
+        match;
+
+    parts.forEach(function(text, i){
+      if (text.match(/^
/)) {
+        text = text.replace(/^
([\s\S]*)<\/pre>/mi, function(_, content){
+          return '
' +
+                  content.replace(//g, '>') +
+                 '
'; + }); + } else if (text.match(/^/)) { + text = text.replace(/()([\s\S]*)(<\/doc:source>)/mi, + function(_, before, content, after){ + return before + htmlEscape(content) + after; + }); + text = text.replace(/()([\s\S]*)(<\/doc:scenario>)/mi, + function(_, before, content, after){ + self.scenarios.push(content); + return before + htmlEscape(content) + after; + }); + } else { + text = text.replace(//gm, '<angular/>'); + text = text.replace(/{@link ([^\s}]+)((\s|\n)+(.+?))?\s*}/gm, + function(_all, url, _2, _3, title){ + return '' + + (url.match(IS_ANGULAR) ? '' : '') + + (title || url) + + (url.match(IS_ANGULAR) ? '' : '') + + ''; + }); + text = new Showdown.converter().makeHtml(text); + } + parts[i] = text; + }); + return parts.join(''); + }, + parse: function(){ var atName; var atText; var match; var self = this; - this.scenarios = []; - this.requires = []; - this.param = []; - this.properties = []; - this.methods = []; self.text.split(NEW_LINE).forEach(function(line){ if (match = line.match(/^\s*@(\w+)(\s+(.*))?/)) { // we found @name ... @@ -82,9 +123,9 @@ Doc.prototype = { this.id = this.id // if we have an id just use it || (((this.file||'').match(/.*\/([^\/]*)\.ngdoc/)||{})[1]) // try to extract it from file name || this.name; // default to name - this.description = markdown(this.description); - this['this'] = markdown(this['this']); - this.exampleDescription = markdown(this.exampleDescription || this.exampleDesc); + this.description = this.markdown(this.description); + this.example = this.markdown(this.example); + this['this'] = this.markdown(this['this']); return this; function flush(){ @@ -98,7 +139,7 @@ Doc.prototype = { } var param = { name: match[5] || match[4], - description:markdown(text.replace(match[0], match[7])), + description:self.markdown(text.replace(match[0], match[7])), type: match[1], optional: !!match[2], 'default':match[6] @@ -111,18 +152,10 @@ Doc.prototype = { } self.returns = { type: match[1], - description: markdown(text.replace(match[0], match[2])) + description: self.markdown(text.replace(match[0], match[2])) }; - } else if(atName == 'description') { - text.replace(/([\s\S]*?)<\/doc:scenario>/gmi, - function(_, scenario){ - self.scenarios.push(scenario); - }); - self.description = text; } else if(atName == 'requires') { self.requires.push(text); - } else if(atName == 'scenario') { - self.scenarios.push(text); } else if(atName == 'property') { var match = text.match(/^({(\S+)}\s*)?(\S+)(\s+(.*))?/); if (!match) { @@ -154,7 +187,7 @@ Doc.prototype = { throw new Error("Don't know how to format @ngdoc: " + self.ngdoc); }).call(self, dom); - dom.example(self.exampleDescription, self.example, self.scenarios[0]); + dom.h('Example', self.example, dom.html); }); return dom.toString(); @@ -407,13 +440,13 @@ Doc.prototype = { dom.h(method.shortName + '(' + signature.join(', ') + ')', method, function(){ dom.html(method.description); method.html_usage_parameters(dom); - dom.example(method.exampleDescription, method.example, false); + dom.h('Example', method.example, dom.html); }); }); dom.h('Properties', this.properties, function(property){ dom.h(property.name, function(){ dom.text(property.description); - dom.example(property.exampleDescription, property.example, false); + dom.h('Example', property.example, dom.html); }); }); }, @@ -436,47 +469,6 @@ Doc.prototype = { ////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////// -function markdown (text) { - var IS_URL = /^(https?:\/\/|ftps?:\/\/|mailto:)/; - var IS_ANGULAR = /^angular\./; - if (!text) return text; - var parts = text.split(/(
[\s\S]*?<\/pre>|[\s\S]*?<\/doc:example>)/),
-      match;
-
-  parts.forEach(function(text, i){
-    if (text.match(/^
/)) {
-      text = text.replace(/^
([\s\S]*)<\/pre>/mi, function(_, content){
-        return '
' +
-                content.replace(//g, '>') +
-               '
'; - }); - } else if (text.match(/^/)) { - text = text.replace(/()([\s\S]*)(<\/doc:source>)/mi, - function(_, before, content, after){ - return before + htmlEscape(content) + after; - }); - text = text.replace(/()([\s\S]*)(<\/doc:scenario>)/mi, - function(_, before, content, after){ - return before + htmlEscape(content) + after; - }); - } else { - text = text.replace(//gm, '<angular/>'); - text = text.replace(/{@link ([^\s}]+)((\s|\n)+(.+?))?\s*}/gm, - function(_all, url, _2, _3, title){ - return '' - + (url.match(IS_ANGULAR) ? '' : '') - + (title || url) - + (url.match(IS_ANGULAR) ? '' : '') - + ''; - }); - text = new Showdown.converter().makeHtml(text); - } - parts[i] = text; - }); - return parts.join(''); -}; - ////////////////////////////////////////////////////////// function scenarios(docs){ var specs = []; diff --git a/src/Angular.js b/src/Angular.js index 2812c926..de2de30d 100644 --- a/src/Angular.js +++ b/src/Angular.js @@ -484,14 +484,18 @@ function map(obj, iterator, context) { * @returns {number} The size of `obj` or `0` if `obj` is neither an object or an array. * * @example - * Number of items in array: {{ [1,2].$size() }}
- * Number of items in object: {{ {a:1, b:2, c:3}.$size() }}
- * - * @scenario - it('should print correct sizes for an array and an object', function() { - expect(binding('[1,2].$size()')).toBe('2'); - expect(binding('{a:1, b:2, c:3}.$size()')).toBe('3'); - }); + * + * + * Number of items in array: {{ [1,2].$size() }}
+ * Number of items in object: {{ {a:1, b:2, c:3}.$size() }}
+ *
+ * + * it('should print correct sizes for an array and an object', function() { + * expect(binding('[1,2].$size()')).toBe('2'); + * expect(binding('{a:1, b:2, c:3}.$size()')).toBe('3'); + * }); + * + *
*/ function size(obj) { var size = 0, key; @@ -556,17 +560,19 @@ function isLeafNode (node) { * @returns {*} The copy or updated `destination` if `destination` was specified. * * @example - Salutation:
- Name:
- -
- - The master object is NOT equal to the form object. - -
master={{master}}
-
form={{form}}
- - * @scenario + * + * + Salutation:
+ Name:
+ +
+ + The master object is NOT equal to the form object. + +
master={{master}}
+
form={{form}}
+ *
+ * it('should print that initialy the form object is NOT equal to master', function() { expect(element('.doc-example input[name=master.salutation]').val()).toBe('Hello'); expect(element('.doc-example input[name=master.name]').val()).toBe('world'); @@ -577,6 +583,8 @@ function isLeafNode (node) { element('.doc-example button').click(); expect(element('.doc-example span').css('display')).toBe('none'); }); + * + *
*/ function copy(source, destination){ if (!destination) { @@ -633,27 +641,31 @@ function copy(source, destination){ * @returns {boolean} True if arguments are equal. * * @example - Salutation:
- Name:
-
- - The greeting object is - NOT equal to - {salutation:'Hello', name:'world'}. - -
greeting={{greeting}}
- - @scenario - it('should print that initialy greeting is equal to the hardcoded value object', function() { - expect(element('.doc-example input[name=greeting.salutation]').val()).toBe('Hello'); - expect(element('.doc-example input[name=greeting.name]').val()).toBe('world'); - expect(element('.doc-example span').css('display')).toBe('none'); - }); - - it('should say that the objects are not equal when the form is modified', function() { - input('greeting.name').enter('kitty'); - expect(element('.doc-example span').css('display')).toBe('inline'); - }); + * + * + Salutation:
+ Name:
+
+ + The greeting object is + NOT equal to + {salutation:'Hello', name:'world'}. + +
greeting={{greeting}}
+ *
+ * + it('should print that initialy greeting is equal to the hardcoded value object', function() { + expect(element('.doc-example input[name=greeting.salutation]').val()).toBe('Hello'); + expect(element('.doc-example input[name=greeting.name]').val()).toBe('world'); + expect(element('.doc-example span').css('display')).toBe('none'); + }); + + it('should say that the objects are not equal when the form is modified', function() { + input('greeting.name').enter('kitty'); + expect(element('.doc-example span').css('display')).toBe('inline'); + }); + * + *
*/ function equals(o1, o2) { if (o1 == o2) return true; diff --git a/src/Compiler.js b/src/Compiler.js index c2c56650..472ec625 100644 --- a/src/Compiler.js +++ b/src/Compiler.js @@ -139,40 +139,44 @@ Compiler.prototype = { * @element ANY * @param {integer|string=} [priority=0] priority integer, or FIRST, LAST constant * - * @exampleDescription + * @example * try changing the invoice and see that the Total will lag in evaluation * @example -
TOTAL: without ng:eval-order {{ items.$sum('total') | currency }}
-
TOTAL: with ng:eval-order {{ items.$sum('total') | currency }}
- - - - - - - - - - - - - - - - - - - -
QTYDescriptionCostTotal
{{item.total = item.qty * item.cost | currency}}X
add{{ items.$sum('total') | currency }}
- * - * @scenario - it('should check ng:format', function(){ - expect(using('.doc-example-live div:first').binding("items.$sum('total')")).toBe('$9.99'); - expect(using('.doc-example-live div:last').binding("items.$sum('total')")).toBe('$9.99'); - input('item.qty').enter('2'); - expect(using('.doc-example-live div:first').binding("items.$sum('total')")).toBe('$9.99'); - expect(using('.doc-example-live div:last').binding("items.$sum('total')")).toBe('$19.98'); - }); + + +
TOTAL: without ng:eval-order {{ items.$sum('total') | currency }}
+
TOTAL: with ng:eval-order {{ items.$sum('total') | currency }}
+ + + + + + + + + + + + + + + + + + + +
QTYDescriptionCostTotal
{{item.total = item.qty * item.cost | currency}}X
add{{ items.$sum('total') | currency }}
+
+ + it('should check ng:format', function(){ + expect(using('.doc-example-live div:first').binding("items.$sum('total')")).toBe('$9.99'); + expect(using('.doc-example-live div:last').binding("items.$sum('total')")).toBe('$9.99'); + input('item.qty').enter('2'); + expect(using('.doc-example-live div:first').binding("items.$sum('total')")).toBe('$9.99'); + expect(using('.doc-example-live div:last').binding("items.$sum('total')")).toBe('$19.98'); + }); + +
*/ templatize: function(element, elementIndex, priority){ diff --git a/src/Scope.js b/src/Scope.js index aef2706e..a73375ab 100644 --- a/src/Scope.js +++ b/src/Scope.js @@ -202,7 +202,7 @@ function errorHandlerFor(element, error) { * @returns {Object} Newly created scope. * * - * @exampleDescription + * @example * This example demonstrates scope inheritance and property overriding. * * In this example, the root scope encompasses the whole HTML DOM tree. This scope has `salutation`, @@ -216,27 +216,29 @@ function errorHandlerFor(element, error) { * - The child scope inherits the salutation property from the root scope. * - The $index property does not leak from the child scope to the root scope. * - * @example -
    -
  • - {{$index}}: {{salutation}} {{name}}! -
  • -
-
-   $index={{$index}}
-   salutation={{salutation}}
-   name={{name}}
- - @scenario - it('should inherit the salutation property and override the name property', function() { - expect(using('.doc-example-live').repeater('li').row(0)). - toEqual(['0', 'Hello', 'World']); - expect(using('.doc-example-live').repeater('li').row(1)). - toEqual(['1', 'Hello', 'Earth']); - expect(using('.doc-example-live').element('pre').text()). - toBe('$index=\nsalutation=Hello\nname=Misko'); - }); - + + +
    +
  • + {{$index}}: {{salutation}} {{name}}! +
  • +
+
+       $index={{$index}}
+       salutation={{salutation}}
+       name={{name}}
+
+ + it('should inherit the salutation property and override the name property', function() { + expect(using('.doc-example-live').repeater('li').row(0)). + toEqual(['0', 'Hello', 'World']); + expect(using('.doc-example-live').repeater('li').row(1)). + toEqual(['1', 'Hello', 'Earth']); + expect(using('.doc-example-live').element('pre').text()). + toBe('$index=\nsalutation=Hello\nname=Misko'); + }); + +
*/ function createScope(parent, providers, instanceCache) { function Parent(){} diff --git a/src/angular-mocks.js b/src/angular-mocks.js index fe0fb011..71a18d06 100644 --- a/src/angular-mocks.js +++ b/src/angular-mocks.js @@ -239,10 +239,10 @@ angular.service('$exceptionHandler', function(e) { */ angular.service('$log', function() { var $log = { - log: function(){ $log.logs.push(arguments) }, - warn: function(){ $log.logs.push(arguments) }, - info: function(){ $log.logs.push(arguments) }, - error: function(){ $log.logs.push(arguments) } + log: function(){ $log.logs.push(arguments); }, + warn: function(){ $log.logs.push(arguments); }, + info: function(){ $log.logs.push(arguments); }, + error: function(){ $log.logs.push(arguments); } }; $log.log.logs = []; @@ -265,6 +265,15 @@ angular.service('$log', function() { * @param {(number|string)} timestamp Timestamp representing the desired time in *UTC* * * @example + * !!!! WARNING !!!!! + * This is not a complete Date object so only methods that were implemented can be called safely. + * To make matters worse, TzDate instances inherit stuff from Date via a prototype. + * + * We do our best to intercept calls to "unimplemented" methods, but since the list of methods is + * incomplete we might be missing some non-standard methods. This can result in errors like: + * "Date.prototype.foo called on incompatible Object". + * + *
  * var newYearInBratislava = new TzDate(-1, '2009-12-31T23:00:00Z');
  * newYearInBratislava.getTimezoneOffset() => -60;
  * newYearInBratislava.getFullYear() => 2010;
@@ -272,15 +281,8 @@ angular.service('$log', function() {
  * newYearInBratislava.getDate() => 1;
  * newYearInBratislava.getHours() => 0;
  * newYearInBratislava.getMinutes() => 0;
+ * 
* - * - * !!!! WARNING !!!!! - * This is not a complete Date object so only methods that were implemented can be called safely. - * To make matters worse, TzDate instances inherit stuff from Date via a prototype. - * - * We do our best to intercept calls to "unimplemented" methods, but since the list of methods is - * incomplete we might be missing some non-standard methods. This can result in errors like: - * "Date.prototype.foo called on incompatible Object". */ function TzDate(offset, timestamp) { if (angular.isString(timestamp)) { diff --git a/src/apis.js b/src/apis.js index 35e3a92f..437cd6e0 100644 --- a/src/apis.js +++ b/src/apis.js @@ -79,22 +79,26 @@ var angularArray = { * @returns {number} The position of the element in `array`. The position is 0-based. `-1` is returned if the value can't be found. * * @example -
-
- Index of '{{bookName}}' in the list {{books}} is {{books.$indexOf(bookName)}}. - - @scenario - it('should correctly calculate the initial index', function() { - expect(binding('books.$indexOf(bookName)')).toBe('2'); - }); - - it('should recalculate', function() { - input('bookName').enter('foo'); - expect(binding('books.$indexOf(bookName)')).toBe('-1'); - - input('bookName').enter('Moby Dick'); - expect(binding('books.$indexOf(bookName)')).toBe('0'); - }); + + +
+
+ Index of '{{bookName}}' in the list {{books}} is {{books.$indexOf(bookName)}}. +
+ + it('should correctly calculate the initial index', function() { + expect(binding('books.$indexOf(bookName)')).toBe('2'); + }); + + it('should recalculate', function() { + input('bookName').enter('foo'); + expect(binding('books.$indexOf(bookName)')).toBe('-1'); + + input('bookName').enter('Moby Dick'); + expect(binding('books.$indexOf(bookName)')).toBe('0'); + }); + +
*/ 'indexOf': indexOf, @@ -117,42 +121,46 @@ var angularArray = { * @returns {number} Sum of items in the array. * * @example - - - - - - - - - - - - - - - -
QtyDescriptionCostTotal
{{item.qty * item.cost | currency}}[X]
add itemTotal:{{invoice.items.$sum('qty*cost') | currency}}
- - @scenario - //TODO: these specs are lame because I had to work around issues #164 and #167 - it('should initialize and calculate the totals', function() { - expect(repeater('.doc-example-live table tr', 'item in invoice.items').count()).toBe(3); - expect(repeater('.doc-example-live table tr', 'item in invoice.items').row(1)). - toEqual(['$99.50']); - expect(binding("invoice.items.$sum('qty*cost')")).toBe('$99.50'); - expect(binding("invoice.items.$sum('qty*cost')")).toBe('$99.50'); - }); - - it('should add an entry and recalculate', function() { - element('.doc-example a:contains("add item")').click(); - using('.doc-example-live tr:nth-child(3)').input('item.qty').enter('20'); - using('.doc-example-live tr:nth-child(3)').input('item.cost').enter('100'); - - expect(repeater('.doc-example-live table tr', 'item in invoice.items').row(2)). - toEqual(['$2,000.00']); - expect(binding("invoice.items.$sum('qty*cost')")).toBe('$2,099.50'); - }); + + + + + + + + + + + + + + + + + +
QtyDescriptionCostTotal
{{item.qty * item.cost | currency}}[X]
add itemTotal:{{invoice.items.$sum('qty*cost') | currency}}
+
+ + //TODO: these specs are lame because I had to work around issues #164 and #167 + it('should initialize and calculate the totals', function() { + expect(repeater('.doc-example-live table tr', 'item in invoice.items').count()).toBe(3); + expect(repeater('.doc-example-live table tr', 'item in invoice.items').row(1)). + toEqual(['$99.50']); + expect(binding("invoice.items.$sum('qty*cost')")).toBe('$99.50'); + expect(binding("invoice.items.$sum('qty*cost')")).toBe('$99.50'); + }); + + it('should add an entry and recalculate', function() { + element('.doc-example a:contains("add item")').click(); + using('.doc-example-live tr:nth-child(3)').input('item.qty').enter('20'); + using('.doc-example-live tr:nth-child(3)').input('item.cost').enter('100'); + + expect(repeater('.doc-example-live table tr', 'item in invoice.items').row(2)). + toEqual(['$2,000.00']); + expect(binding("invoice.items.$sum('qty*cost')")).toBe('$2,099.50'); + }); + +
*/ 'sum':function(array, expression) { var fn = angular['Function']['compile'](expression); @@ -185,33 +193,37 @@ var angularArray = { * @returns {*} The removed element. * * @example -
    -
  • - {{task}} [X] -
  • -
-
- tasks = {{tasks}} - - @scenario - it('should initialize the task list with for tasks', function() { - expect(repeater('.doc-example ul li', 'task in tasks').count()).toBe(4); - expect(repeater('.doc-example ul li', 'task in tasks').column('task')). - toEqual(['Learn Angular', 'Read Documentation', 'Check out demos', - 'Build cool applications']); - }); - - it('should initialize the task list with for tasks', function() { - element('.doc-example ul li a:contains("X"):first').click(); - expect(repeater('.doc-example ul li', 'task in tasks').count()).toBe(3); - - element('.doc-example ul li a:contains("X"):last').click(); - expect(repeater('.doc-example ul li', 'task in tasks').count()).toBe(2); - - expect(repeater('.doc-example ul li', 'task in tasks').column('task')). - toEqual(['Read Documentation', 'Check out demos']); - }); + + +
    +
  • + {{task}} [X] +
  • +
+
+ tasks = {{tasks}} +
+ + it('should initialize the task list with for tasks', function() { + expect(repeater('.doc-example ul li', 'task in tasks').count()).toBe(4); + expect(repeater('.doc-example ul li', 'task in tasks').column('task')). + toEqual(['Learn Angular', 'Read Documentation', 'Check out demos', + 'Build cool applications']); + }); + + it('should initialize the task list with for tasks', function() { + element('.doc-example ul li a:contains("X"):first').click(); + expect(repeater('.doc-example ul li', 'task in tasks').count()).toBe(3); + + element('.doc-example ul li a:contains("X"):last').click(); + expect(repeater('.doc-example ul li', 'task in tasks').count()).toBe(2); + + expect(repeater('.doc-example ul li', 'task in tasks').column('task')). + toEqual(['Read Documentation', 'Check out demos']); + }); + +
*/ 'remove':function(array, value) { var index = indexOf(array, value); @@ -254,48 +266,52 @@ var angularArray = { * the predicate returned true for. * * @example -
- - Search: - - - - - - -
NamePhone
{{friend.name}}{{friend.phone}}
-
- Any:
- Name only
- Phone only
- - - - - - -
NamePhone
{{friend.name}}{{friend.phone}}
- - @scenario - it('should search across all fields when filtering with a string', function() { - input('searchText').enter('m'); - expect(repeater('#searchTextResults tr', 'friend in friends').column('name')). - toEqual(['Mary', 'Mike', 'Adam']); - - input('searchText').enter('76'); - expect(repeater('#searchTextResults tr', 'friend in friends').column('name')). - toEqual(['John', 'Julie']); - }); - - it('should search in specific fields when filtering with a predicate object', function() { - input('search.$').enter('i'); - expect(repeater('#searchObjResults tr', 'friend in friends').column('name')). - toEqual(['Mary', 'Mike', 'Julie']); - }); + + +
+ + Search: + + + + + + +
NamePhone
{{friend.name}}{{friend.phone}}
+
+ Any:
+ Name only
+ Phone only
+ + + + + + +
NamePhone
{{friend.name}}{{friend.phone}}
+
+ + it('should search across all fields when filtering with a string', function() { + input('searchText').enter('m'); + expect(repeater('#searchTextResults tr', 'friend in friends').column('name')). + toEqual(['Mary', 'Mike', 'Adam']); + + input('searchText').enter('76'); + expect(repeater('#searchTextResults tr', 'friend in friends').column('name')). + toEqual(['John', 'Julie']); + }); + + it('should search in specific fields when filtering with a predicate object', function() { + input('search.$').enter('i'); + expect(repeater('#searchObjResults tr', 'friend in friends').column('name')). + toEqual(['Mary', 'Mike', 'Julie']); + }); + +
*/ 'filter':function(array, expression) { var predicates = []; @@ -398,53 +414,55 @@ var angularArray = { * * @TODO simplify the example. * - * @exampleDescription + * @example * This example shows how an initially empty array can be filled with objects created from user * input via the `$add` method. - * - * @example - [add empty] - [add 'John'] - [add 'Mary'] - -
    -
  • - - - [X] -
  • -
-
people = {{people}}
- - @scenario - beforeEach(function() { - expect(binding('people')).toBe('people = []'); - }); - - it('should create an empty record when "add empty" is clicked', function() { - element('.doc-example a:contains("add empty")').click(); - expect(binding('people')).toBe('people = [{\n "name":"",\n "sex":null}]'); - }); - - it('should create a "John" record when "add \'John\'" is clicked', function() { - element('.doc-example a:contains("add \'John\'")').click(); - expect(binding('people')).toBe('people = [{\n "name":"John",\n "sex":"male"}]'); - }); - - it('should create a "Mary" record when "add \'Mary\'" is clicked', function() { - element('.doc-example a:contains("add \'Mary\'")').click(); - expect(binding('people')).toBe('people = [{\n "name":"Mary",\n "sex":"female"}]'); - }); - - it('should delete a record when "X" is clicked', function() { - element('.doc-example a:contains("add empty")').click(); - element('.doc-example li a:contains("X"):first').click(); - expect(binding('people')).toBe('people = []'); - }); + + + [add empty] + [add 'John'] + [add 'Mary'] + +
    +
  • + + + [X] +
  • +
+
people = {{people}}
+
+ + beforeEach(function() { + expect(binding('people')).toBe('people = []'); + }); + + it('should create an empty record when "add empty" is clicked', function() { + element('.doc-example a:contains("add empty")').click(); + expect(binding('people')).toBe('people = [{\n "name":"",\n "sex":null}]'); + }); + + it('should create a "John" record when "add \'John\'" is clicked', function() { + element('.doc-example a:contains("add \'John\'")').click(); + expect(binding('people')).toBe('people = [{\n "name":"John",\n "sex":"male"}]'); + }); + + it('should create a "Mary" record when "add \'Mary\'" is clicked', function() { + element('.doc-example a:contains("add \'Mary\'")').click(); + expect(binding('people')).toBe('people = [{\n "name":"Mary",\n "sex":"female"}]'); + }); + + it('should delete a record when "X" is clicked', function() { + element('.doc-example a:contains("add empty")').click(); + element('.doc-example li a:contains("X"):first').click(); + expect(binding('people')).toBe('people = []'); + }); + +
*/ 'add':function(array, value) { array.push(isUndefined(value)? {} : value); @@ -471,29 +489,33 @@ var angularArray = { * @returns {number} Number of elements in the array (for which the condition evaluates to true). * * @example -

-     
    -
  • - {{item.name}}: points= - -
  • -
-

Number of items which have one point: {{ items.$count('points==1') }}

-

Number of items which have more than one point: {{items.$count('points>1')}}

- - @scenario - it('should calculate counts', function() { - expect(binding('items.$count(\'points==1\')')).toEqual(2); - expect(binding('items.$count(\'points>1\')')).toEqual(1); - }); - - it('should recalculate when updated', function() { - using('.doc-example li:first-child').input('item.points').enter('23'); - expect(binding('items.$count(\'points==1\')')).toEqual(1); - expect(binding('items.$count(\'points>1\')')).toEqual(2); - }); + + +

+         
    +
  • + {{item.name}}: points= + +
  • +
+

Number of items which have one point: {{ items.$count('points==1') }}

+

Number of items which have more than one point: {{items.$count('points>1')}}

+
+ + it('should calculate counts', function() { + expect(binding('items.$count(\'points==1\')')).toEqual(2); + expect(binding('items.$count(\'points>1\')')).toEqual(1); + }); + + it('should recalculate when updated', function() { + using('.doc-example li:first-child').input('item.points').enter('23'); + expect(binding('items.$count(\'points==1\')')).toEqual(1); + expect(binding('items.$count(\'points>1\')')).toEqual(2); + }); + +
*/ 'count':function(array, condition) { if (!condition) return array.length; @@ -535,52 +557,56 @@ var angularArray = { * @returns {Array} Sorted copy of the source array. * * @example -
- -
Sorting predicate = {{predicate}}
-
- - - - - - - - - - - -
Name - (^)Phone - (^)Age - (^)
{{friend.name}}{{friend.phone}}{{friend.age}}
- - @scenario - it('should be reverse ordered by aged', function() { - expect(binding('predicate')).toBe('Sorting predicate = -age'); - expect(repeater('.doc-example table', 'friend in friends').column('friend.age')). - toEqual(['35', '29', '21', '19', '10']); - expect(repeater('.doc-example table', 'friend in friends').column('friend.name')). - toEqual(['Adam', 'Julie', 'Mike', 'Mary', 'John']); - }); - - it('should reorder the table when user selects different predicate', function() { - element('.doc-example a:contains("Name")').click(); - expect(repeater('.doc-example table', 'friend in friends').column('friend.name')). - toEqual(['Adam', 'John', 'Julie', 'Mary', 'Mike']); - expect(repeater('.doc-example table', 'friend in friends').column('friend.age')). - toEqual(['35', '10', '29', '19', '21']); - - element('.doc-example a:contains("Phone")+a:contains("^")').click(); - expect(repeater('.doc-example table', 'friend in friends').column('friend.phone')). - toEqual(['555-9876', '555-8765', '555-5678', '555-4321', '555-1212']); - expect(repeater('.doc-example table', 'friend in friends').column('friend.name')). - toEqual(['Mary', 'Julie', 'Adam', 'Mike', 'John']); - }); + + +
+ +
Sorting predicate = {{predicate}}
+
+ + + + + + + + + + + +
Name + (^)Phone + (^)Age + (^)
{{friend.name}}{{friend.phone}}{{friend.age}}
+
+ + it('should be reverse ordered by aged', function() { + expect(binding('predicate')).toBe('Sorting predicate = -age'); + expect(repeater('.doc-example table', 'friend in friends').column('friend.age')). + toEqual(['35', '29', '21', '19', '10']); + expect(repeater('.doc-example table', 'friend in friends').column('friend.name')). + toEqual(['Adam', 'Julie', 'Mike', 'Mary', 'John']); + }); + + it('should reorder the table when user selects different predicate', function() { + element('.doc-example a:contains("Name")').click(); + expect(repeater('.doc-example table', 'friend in friends').column('friend.name')). + toEqual(['Adam', 'John', 'Julie', 'Mary', 'Mike']); + expect(repeater('.doc-example table', 'friend in friends').column('friend.age')). + toEqual(['35', '10', '29', '19', '21']); + + element('.doc-example a:contains("Phone")+a:contains("^")').click(); + expect(repeater('.doc-example table', 'friend in friends').column('friend.phone')). + toEqual(['555-9876', '555-8765', '555-5678', '555-4321', '555-1212']); + expect(repeater('.doc-example table', 'friend in friends').column('friend.name')). + toEqual(['Mary', 'Julie', 'Adam', 'Mike', 'John']); + }); + +
*/ //TODO: WTH is descend param for and how/when it should be used, how is it affected by +/- in // predicate? the code below is impossible to read and specs are not very good. @@ -648,21 +674,25 @@ var angularArray = { * @returns {Array} A new sub-array of length `limit`. * * @example -
- Limit [1,2,3,4,5,6,7,8,9] to: -

Output: {{ numbers.$limitTo(limit) | json }}

-
- - * @scenario - it('should limit the numer array to first three items', function() { - expect(element('.doc-example input[name=limit]').val()).toBe('3'); - expect(binding('numbers.$limitTo(limit) | json')).toEqual('[1,2,3]'); - }); - - it('should update the output when -3 is entered', function() { - input('limit').enter(-3); - expect(binding('numbers.$limitTo(limit) | json')).toEqual('[7,8,9]'); - }); + + +
+ Limit [1,2,3,4,5,6,7,8,9] to: +

Output: {{ numbers.$limitTo(limit) | json }}

+
+
+ + it('should limit the numer array to first three items', function() { + expect(element('.doc-example input[name=limit]').val()).toBe('3'); + expect(binding('numbers.$limitTo(limit) | json')).toEqual('[1,2,3]'); + }); + + it('should update the output when -3 is entered', function() { + input('limit').enter(-3); + expect(binding('numbers.$limitTo(limit) | json')).toEqual('[7,8,9]'); + }); + +
*/ limitTo: function(array, limit) { limit = parseInt(limit, 10); diff --git a/src/directives.js b/src/directives.js index 104ff9c8..5ca7c2ec 100644 --- a/src/directives.js +++ b/src/directives.js @@ -4,22 +4,26 @@ * @name angular.directive.ng:init * * @description - * `ng:init` attribute allows the for initialization tasks to be executed + * `ng:init` attribute allows the for initialization tasks to be executed * before the template enters execution mode during bootstrap. * * @element ANY * @param {expression} expression to eval. * * @example + +
{{greeting}} {{person}}!
- * - * @scenario - it('should check greeting', function(){ - expect(binding('greeting')).toBe('Hello'); - expect(binding('person')).toBe('World'); - }); +
+ + it('should check greeting', function(){ + expect(binding('greeting')).toBe('Hello'); + expect(binding('person')).toBe('World'); + }); + +
*/ angularDirective("ng:init", function(expression){ return function(element){ @@ -33,66 +37,70 @@ angularDirective("ng:init", function(expression){ * @name angular.directive.ng:controller * * @description - * To support the Model-View-Controller design pattern, it is possible - * to assign behavior to a scope through `ng:controller`. The scope is - * the MVC model. The HTML (with data bindings) is the MVC view. + * To support the Model-View-Controller design pattern, it is possible + * to assign behavior to a scope through `ng:controller`. The scope is + * the MVC model. The HTML (with data bindings) is the MVC view. * The `ng:controller` directive specifies the MVC controller class * * @element ANY * @param {expression} expression to eval. * * @example - -
- Name: - [ greet ]
- Contact: -
    -
  • - - - [ clear - | X ] -
  • -
  • [ add ]
  • -
-
- * - * @scenario - it('should check controller', function(){ - expect(element('.doc-example-live div>:input').val()).toBe('John Smith'); - expect(element('.doc-example-live li[ng\\:repeat-index="0"] input').val()).toBe('408 555 1212'); - expect(element('.doc-example-live li[ng\\:repeat-index="1"] input').val()).toBe('john.smith@example.org'); - element('.doc-example-live li:first a:contains("clear")').click(); - expect(element('.doc-example-live li:first input').val()).toBe(''); - element('.doc-example-live li:last a:contains("add")').click(); - expect(element('.doc-example-live li[ng\\:repeat-index="2"] input').val()).toBe('yourname@example.org'); - }); + + + +
+ Name: + [ greet ]
+ Contact: +
    +
  • + + + [ clear + | X ] +
  • +
  • [ add ]
  • +
+
+
+ + it('should check controller', function(){ + expect(element('.doc-example-live div>:input').val()).toBe('John Smith'); + expect(element('.doc-example-live li[ng\\:repeat-index="0"] input').val()).toBe('408 555 1212'); + expect(element('.doc-example-live li[ng\\:repeat-index="1"] input').val()).toBe('john.smith@example.org'); + element('.doc-example-live li:first a:contains("clear")').click(); + expect(element('.doc-example-live li:first input').val()).toBe(''); + element('.doc-example-live li:last a:contains("add")').click(); + expect(element('.doc-example-live li[ng\\:repeat-index="2"] input').val()).toBe('yourname@example.org'); + }); + +
*/ angularDirective("ng:controller", function(expression){ this.scope(true); @@ -112,36 +120,38 @@ angularDirective("ng:controller", function(expression){ * @name angular.directive.ng:eval * * @description - * The `ng:eval` allows you to execute a binding which has side effects + * The `ng:eval` allows you to execute a binding which has side effects * without displaying the result to the user. * * @element ANY * @param {expression} expression to eval. * - * @exampleDescription - * Notice that `{{` `obj.multiplied = obj.a * obj.b` `}}` has a side effect of assigning - * a value to `obj.multiplied` and displaying the result to the user. Sometimes, - * however, it is desirable to execute a side effect without showing the value to - * the user. In such a case `ng:eval` allows you to execute code without updating - * the display. - * * @example - * - * * - * = {{obj.multiplied = obj.a * obj.b}}
- * - * - * obj.divide = {{obj.divide}}
- * obj.updateCount = {{obj.updateCount}} - * - * @scenario - it('should check eval', function(){ - expect(binding('obj.divide')).toBe('3'); - expect(binding('obj.updateCount')).toBe('2'); - input('obj.a').enter('12'); - expect(binding('obj.divide')).toBe('6'); - expect(binding('obj.updateCount')).toBe('3'); - }); + * Notice that `{{` `obj.multiplied = obj.a * obj.b` `}}` has a side effect of assigning + * a value to `obj.multiplied` and displaying the result to the user. Sometimes, + * however, it is desirable to execute a side effect without showing the value to + * the user. In such a case `ng:eval` allows you to execute code without updating + * the display. + + + + * + = {{obj.multiplied = obj.a * obj.b}}
+ + + obj.divide = {{obj.divide}}
+ obj.updateCount = {{obj.updateCount}} +
+ + it('should check eval', function(){ + expect(binding('obj.divide')).toBe('3'); + expect(binding('obj.updateCount')).toBe('2'); + input('obj.a').enter('12'); + expect(binding('obj.divide')).toBe('6'); + expect(binding('obj.updateCount')).toBe('3'); + }); + +
*/ angularDirective("ng:eval", function(expression){ return function(element){ @@ -155,27 +165,30 @@ angularDirective("ng:eval", function(expression){ * @name angular.directive.ng:bind * * @description - * The `ng:bind` attribute asks to replace the text content of this - * HTML element with the value of the given expression and kept it up to - * date when the expression's value changes. Usually you just write - * {{expression}} and let compile it into + * The `ng:bind` attribute asks to replace the text content of this + * HTML element with the value of the given expression and kept it up to + * date when the expression's value changes. Usually you just write + * {{expression}} and let compile it into * `` at bootstrap time. - * + * * @element ANY * @param {expression} expression to eval. * - * @exampleDescription - * Try it here: enter text in text box and watch the greeting change. * @example - * Enter name: .
- * Hello ! - * - * @scenario - it('should check ng:bind', function(){ - expect(using('.doc-example-live').binding('name')).toBe('Whirled'); - using('.doc-example-live').input('name').enter('world'); - expect(using('.doc-example-live').binding('name')).toBe('world'); - }); + * Try it here: enter text in text box and watch the greeting change. + + + Enter name: .
+ Hello ! +
+ + it('should check ng:bind', function(){ + expect(using('.doc-example-live').binding('name')).toBe('Whirled'); + using('.doc-example-live').input('name').enter('world'); + expect(using('.doc-example-live').binding('name')).toBe('world'); + }); + +
*/ angularDirective("ng:bind", function(expression, element){ element.addClass('ng-binding'); @@ -259,32 +272,35 @@ function compileBindTemplate(template){ * @name angular.directive.ng:bind-template * * @description - * The `ng:bind-template` attribute specifies that the element - * text should be replaced with the template in ng:bind-template. - * Unlike ng:bind the ng:bind-template can contain multiple `{{` `}}` - * expressions. (This is required since some HTML elements + * The `ng:bind-template` attribute specifies that the element + * text should be replaced with the template in ng:bind-template. + * Unlike ng:bind the ng:bind-template can contain multiple `{{` `}}` + * expressions. (This is required since some HTML elements * can not have SPAN elements such as TITLE, or OPTION to name a few. - * + * * @element ANY * @param {string} template of form * {{ expression }} to eval. * - * @exampleDescription - * Try it here: enter text in text box and watch the greeting change. * @example - Salutation:
- Name:
-

- * 
- * @scenario
-   it('should check ng:bind', function(){
-     expect(using('.doc-example-live').binding('{{salutation}} {{name}}')).
-       toBe('Hello World!');
-     using('.doc-example-live').input('salutation').enter('Greetings');
-     using('.doc-example-live').input('name').enter('user');
-     expect(using('.doc-example-live').binding('{{salutation}} {{name}}')).
-       toBe('Greetings user!');
-   });
+ * Try it here: enter text in text box and watch the greeting change.
+   
+     
+      Salutation: 
+ Name:
+

+     
+ + it('should check ng:bind', function(){ + expect(using('.doc-example-live').binding('{{salutation}} {{name}}')). + toBe('Hello World!'); + using('.doc-example-live').input('salutation').enter('Greetings'); + using('.doc-example-live').input('name').enter('user'); + expect(using('.doc-example-live').binding('{{salutation}} {{name}}')). + toBe('Greetings user!'); + }); + +
*/ angularDirective("ng:bind-template", function(expression, element){ element.addClass('ng-binding'); @@ -313,49 +329,52 @@ var REMOVE_ATTRIBUTES = { * @name angular.directive.ng:bind-attr * * @description - * The `ng:bind-attr` attribute specifies that the element attributes - * which should be replaced by the expression in it. Unlike `ng:bind` - * the `ng:bind-attr` contains a JSON key value pairs representing - * which attributes need to be changed. You don’t usually write the - * `ng:bind-attr` in the HTML since embedding - * {{expression}} into the + * The `ng:bind-attr` attribute specifies that the element attributes + * which should be replaced by the expression in it. Unlike `ng:bind` + * the `ng:bind-attr` contains a JSON key value pairs representing + * which attributes need to be changed. You don’t usually write the + * `ng:bind-attr` in the HTML since embedding + * {{expression}} into the * attribute directly is the preferred way. The attributes get * translated into `` at * bootstrap time. - * + * * This HTML snippet is preferred way of working with `ng:bind-attr` *
  *   Google
  * 
- * + * * The above gets translated to bellow during bootstrap time. *
  *   Google
  * 
- * + * * @element ANY - * @param {string} attribute_json a JSON key-value pairs representing - * the attributes to replace. Each key matches the attribute - * which needs to be replaced. Each value is a text template of - * the attribute with embedded - * {{expression}}s. Any number of + * @param {string} attribute_json a JSON key-value pairs representing + * the attributes to replace. Each key matches the attribute + * which needs to be replaced. Each value is a text template of + * the attribute with embedded + * {{expression}}s. Any number of * key-value pairs can be specified. * - * @exampleDescription - * Try it here: enter text in text box and click Google. * @example - Google for: - - Google - * - * @scenario - it('should check ng:bind-attr', function(){ - expect(using('.doc-example-live').element('a').attr('href')). - toBe('http://www.google.com/search?q=AngularJS'); - using('.doc-example-live').input('query').enter('google'); - expect(using('.doc-example-live').element('a').attr('href')). - toBe('http://www.google.com/search?q=google'); - }); + * Try it here: enter text in text box and click Google. + + + Google for: + + Google + + + it('should check ng:bind-attr', function(){ + expect(using('.doc-example-live').element('a').attr('href')). + toBe('http://www.google.com/search?q=AngularJS'); + using('.doc-example-live').input('query').enter('google'); + expect(using('.doc-example-live').element('a').attr('href')). + toBe('http://www.google.com/search?q=google'); + }); + + */ angularDirective("ng:bind-attr", function(expression){ return function(element){ @@ -396,23 +415,28 @@ angularDirective("ng:bind-attr", function(expression){ * @name angular.directive.ng:click * * @description - * The ng:click allows you to specify custom behavior when + * The ng:click allows you to specify custom behavior when * element is clicked. - * + * * @element ANY * @param {expression} expression to eval upon click. * * @example - - count: {{count}} - * @scenario - it('should check ng:click', function(){ - expect(binding('count')).toBe('0'); - element('.doc-example-live :button').click(); - expect(binding('count')).toBe('1'); - }); + + + + count: {{count}} + + + it('should check ng:click', function(){ + expect(binding('count')).toBe('0'); + element('.doc-example-live :button').click(); + expect(binding('count')).toBe('1'); + }); + + */ /* * A directive that allows creation of custom onclick handlers that are defined as angular @@ -440,35 +464,37 @@ angularDirective("ng:click", function(expression, element){ * @name angular.directive.ng:submit * * @description - * - * @element form - * @param {expression} expression to eval. - * - * @exampleDescription - * @example - *
- * Enter text and hit enter: - * - *
- *
list={{list}}
- * @scenario - it('should check ng:submit', function(){ - expect(binding('list')).toBe('list=[]'); - element('.doc-example-live form input').click(); - this.addFutureAction('submit from', function($window, $document, done) { - $window.angular.element( - $document.elements('.doc-example-live form')). - trigger('submit'); - done(); - }); - expect(binding('list')).toBe('list=["hello"]'); - }); - */ -/** * Enables binding angular expressions to onsubmit events. * * Additionally it prevents the default action (which for form means sending the request to the * server and reloading the current page). + * + * @element form + * @param {expression} expression to eval. + * + * @example + + +
+ Enter text and hit enter: + +
+
list={{list}}
+
+ + it('should check ng:submit', function(){ + expect(binding('list')).toBe('list=[]'); + element('.doc-example-live form input').click(); + this.addFutureAction('submit from', function($window, $document, done) { + $window.angular.element( + $document.elements('.doc-example-live form')). + trigger('submit'); + done(); + }); + expect(binding('list')).toBe('list=["hello"]'); + }); + +
*/ angularDirective("ng:submit", function(expression, element) { return injectUpdateView(function($updateView, element) { @@ -488,26 +514,30 @@ angularDirective("ng:submit", function(expression, element) { * @name angular.directive.ng:watch * * @description - * The `ng:watch` allows you watch a variable and then execute + * The `ng:watch` allows you watch a variable and then execute * an evaluation on variable change. - * + * * @element ANY * @param {expression} expression to eval. * - * @exampleDescription - * Notice that the counter is incremented - * every time you change the text. * @example -
-
- Change counter: {{counter}} Name: {{name}} -
- * @scenario - it('should check ng:watch', function(){ - expect(using('.doc-example-live').binding('counter')).toBe('2'); - using('.doc-example-live').input('name').enter('abc'); - expect(using('.doc-example-live').binding('counter')).toBe('3'); - }); + * Notice that the counter is incremented + * every time you change the text. + + +
+
+ Change counter: {{counter}} Name: {{name}} +
+
+ + it('should check ng:watch', function(){ + expect(using('.doc-example-live').binding('counter')).toBe('2'); + using('.doc-example-live').input('name').enter('abc'); + expect(using('.doc-example-live').binding('counter')).toBe('3'); + }); + +
*/ //TODO: delete me, since having watch in UI is logic in UI. (leftover form getangular) angularDirective("ng:watch", function(expression, element){ @@ -544,34 +574,37 @@ function ngClass(selector) { * @name angular.directive.ng:class * * @description - * The `ng:class` allows you to set CSS class on HTML element + * The `ng:class` allows you to set CSS class on HTML element * conditionally. - * + * * @element ANY * @param {expression} expression to eval. * - * @exampleDescription * @example - - -
- Sample Text      - * - * @scenario - it('should check ng:class', function(){ - expect(element('.doc-example-live span').attr('className')).not(). - toMatch(/ng-input-indicator-wait/); + + + + +
+ Sample Text      +
+ + it('should check ng:class', function(){ + expect(element('.doc-example-live span').attr('className')).not(). + toMatch(/ng-input-indicator-wait/); + + using('.doc-example-live').element(':button:first').click(); - using('.doc-example-live').element(':button:first').click(); + expect(element('.doc-example-live span').attr('className')). + toMatch(/ng-input-indicator-wait/); - expect(element('.doc-example-live span').attr('className')). - toMatch(/ng-input-indicator-wait/); + using('.doc-example-live').element(':button:last').click(); - using('.doc-example-live').element(':button:last').click(); - - expect(element('.doc-example-live span').attr('className')).not(). - toMatch(/ng-input-indicator-wait/); - }); + expect(element('.doc-example-live span').attr('className')).not(). + toMatch(/ng-input-indicator-wait/); + }); + +
*/ angularDirective("ng:class", ngClass(function(){return true;})); @@ -581,33 +614,35 @@ angularDirective("ng:class", ngClass(function(){return true;})); * @name angular.directive.ng:class-odd * * @description - * The `ng:class-odd` and `ng:class-even` works exactly as - * `ng:class`, except it works in conjunction with `ng:repeat` + * The `ng:class-odd` and `ng:class-even` works exactly as + * `ng:class`, except it works in conjunction with `ng:repeat` * and takes affect only on odd (even) rows. * * @element ANY - * @param {expression} expression to eval. Must be inside + * @param {expression} expression to eval. Must be inside * `ng:repeat`. - * - * @exampleDescription * @example -
    -
  1. - - {{name}}       - -
  2. -
- * - * @scenario - it('should check ng:class-odd and ng:class-even', function(){ - expect(element('.doc-example-live li:first span').attr('className')). - toMatch(/ng-format-negative/); - expect(element('.doc-example-live li:last span').attr('className')). - toMatch(/ng-input-indicator-wait/); - }); + + +
    +
  1. + + {{name}}       + +
  2. +
+
+ + it('should check ng:class-odd and ng:class-even', function(){ + expect(element('.doc-example-live li:first span').attr('className')). + toMatch(/ng-format-negative/); + expect(element('.doc-example-live li:last span').attr('className')). + toMatch(/ng-input-indicator-wait/); + }); + +
*/ angularDirective("ng:class-odd", ngClass(function(i){return i % 2 === 0;})); @@ -617,33 +652,35 @@ angularDirective("ng:class-odd", ngClass(function(i){return i % 2 === 0;})); * @name angular.directive.ng:class-even * * @description - * The `ng:class-odd` and `ng:class-even` works exactly as - * `ng:class`, except it works in conjunction with `ng:repeat` + * The `ng:class-odd` and `ng:class-even` works exactly as + * `ng:class`, except it works in conjunction with `ng:repeat` * and takes affect only on odd (even) rows. * * @element ANY - * @param {expression} expression to eval. Must be inside + * @param {expression} expression to eval. Must be inside * `ng:repeat`. - * - * @exampleDescription * @example -
    -
  1. - - {{name}}       - -
  2. -
- * - * @scenario - it('should check ng:class-odd and ng:class-even', function(){ - expect(element('.doc-example-live li:first span').attr('className')). - toMatch(/ng-format-negative/); - expect(element('.doc-example-live li:last span').attr('className')). - toMatch(/ng-input-indicator-wait/); - }); + + +
    +
  1. + + {{name}}       + +
  2. +
+
+ + it('should check ng:class-odd and ng:class-even', function(){ + expect(element('.doc-example-live li:first span').attr('className')). + toMatch(/ng-format-negative/); + expect(element('.doc-example-live li:last span').attr('className')). + toMatch(/ng-input-indicator-wait/); + }); + +
*/ angularDirective("ng:class-even", ngClass(function(i){return i % 2 === 1;})); @@ -655,27 +692,30 @@ angularDirective("ng:class-even", ngClass(function(i){return i % 2 === 1;})); * @description * The `ng:show` and `ng:hide` allows you to show or hide a portion * of the HTML conditionally. - * + * * @element ANY - * @param {expression} expression if truthy then the element is + * @param {expression} expression if truthy then the element is * shown or hidden respectively. * - * @exampleDescription * @example - Click me:
- Show: I show up when you checkbox is checked?
- Hide: I hide when you checkbox is checked? - * - * @scenario - it('should check ng:show / ng:hide', function(){ - expect(element('.doc-example-live span:first:hidden').count()).toEqual(1); - expect(element('.doc-example-live span:last:visible').count()).toEqual(1); - - input('checked').check(); - - expect(element('.doc-example-live span:first:visible').count()).toEqual(1); - expect(element('.doc-example-live span:last:hidden').count()).toEqual(1); - }); + + + Click me:
+ Show: I show up when you checkbox is checked?
+ Hide: I hide when you checkbox is checked? +
+ + it('should check ng:show / ng:hide', function(){ + expect(element('.doc-example-live span:first:hidden').count()).toEqual(1); + expect(element('.doc-example-live span:last:visible').count()).toEqual(1); + + input('checked').check(); + + expect(element('.doc-example-live span:first:visible').count()).toEqual(1); + expect(element('.doc-example-live span:last:hidden').count()).toEqual(1); + }); + +
*/ angularDirective("ng:show", function(expression, element){ return function(element){ @@ -693,27 +733,30 @@ angularDirective("ng:show", function(expression, element){ * @description * The `ng:show` and `ng:hide` allows you to show or hide a portion * of the HTML conditionally. - * + * * @element ANY - * @param {expression} expression if truthy then the element is + * @param {expression} expression if truthy then the element is * shown or hidden respectively. * - * @exampleDescription * @example - Click me:
- Show: I show up when you checkbox is checked?
- Hide: I hide when you checkbox is checked? - * - * @scenario - it('should check ng:show / ng:hide', function(){ - expect(element('.doc-example-live span:first:hidden').count()).toEqual(1); - expect(element('.doc-example-live span:last:visible').count()).toEqual(1); - - input('checked').check(); - - expect(element('.doc-example-live span:first:visible').count()).toEqual(1); - expect(element('.doc-example-live span:last:hidden').count()).toEqual(1); - }); + + + Click me:
+ Show: I show up when you checkbox is checked?
+ Hide: I hide when you checkbox is checked? +
+ + it('should check ng:show / ng:hide', function(){ + expect(element('.doc-example-live span:first:hidden').count()).toEqual(1); + expect(element('.doc-example-live span:last:visible').count()).toEqual(1); + + input('checked').check(); + + expect(element('.doc-example-live span:first:visible').count()).toEqual(1); + expect(element('.doc-example-live span:last:hidden').count()).toEqual(1); + }); + +
*/ angularDirective("ng:hide", function(expression, element){ return function(element){ @@ -730,28 +773,31 @@ angularDirective("ng:hide", function(expression, element){ * * @description * The ng:style allows you to set CSS style on an HTML element conditionally. - * + * * @element ANY - * @param {expression} expression which evals to an object whes key's are - * CSS style names and values are coresponding values for those + * @param {expression} expression which evals to an object whes key's are + * CSS style names and values are coresponding values for those * CSS keys. * - * @exampleDescription * @example - - -
- Sample Text -
myStyle={{myStyle}}
- * - * @scenario - it('should check ng:style', function(){ - expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)'); - element('.doc-example-live :button[value=set]').click(); - expect(element('.doc-example-live span').css('color')).toBe('red'); - element('.doc-example-live :button[value=clear]').click(); - expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)'); - }); + + + + +
+ Sample Text +
myStyle={{myStyle}}
+
+ + it('should check ng:style', function(){ + expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)'); + element('.doc-example-live :button[value=set]').click(); + expect(element('.doc-example-live span').css('color')).toBe('red'); + element('.doc-example-live :button[value=clear]').click(); + expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)'); + }); + +
*/ angularDirective("ng:style", function(expression, element){ return function(element){ diff --git a/src/filters.js b/src/filters.js index 7fa7926d..0f6121ec 100644 --- a/src/filters.js +++ b/src/filters.js @@ -14,19 +14,23 @@ * When the value is negative, this css class is applied to the binding making it by default red. * * @example -
- {{amount | currency}} - * - * @scenario - it('should init with 1234.56', function(){ - expect(binding('amount | currency')).toBe('$1,234.56'); - }); - it('should update', function(){ - input('amount').enter('-1234'); - expect(binding('amount | currency')).toBe('$-1,234.00'); - expect(element('.doc-example-live .ng-binding').attr('className')). - toMatch(/ng-format-negative/); - }); + + +
+ {{amount | currency}} +
+ + it('should init with 1234.56', function(){ + expect(binding('amount | currency')).toBe('$1,234.56'); + }); + it('should update', function(){ + input('amount').enter('-1234'); + expect(binding('amount | currency')).toBe('$-1,234.00'); + expect(element('.doc-example-live .ng-binding').attr('className')). + toMatch(/ng-format-negative/); + }); + +
*/ angularFilter.currency = function(amount){ this.$element.toggleClass('ng-format-negative', amount < 0); @@ -49,24 +53,28 @@ angularFilter.currency = function(amount){ * @returns {string} Number rounded to decimalPlaces and places a “,” after each third digit. * * @example - Enter number:
- Default formatting: {{val | number}}
- No fractions: {{val | number:0}}
- Negative number: {{-val | number:4}} - - * @scenario - it('should format numbers', function(){ - expect(binding('val | number')).toBe('1,234.57'); - expect(binding('val | number:0')).toBe('1,235'); - expect(binding('-val | number:4')).toBe('-1,234.5679'); - }); - - it('should update', function(){ - input('val').enter('3374.333'); - expect(binding('val | number')).toBe('3,374.33'); - expect(binding('val | number:0')).toBe('3,374'); - expect(binding('-val | number:4')).toBe('-3,374.3330'); - }); + + + Enter number:
+ Default formatting: {{val | number}}
+ No fractions: {{val | number:0}}
+ Negative number: {{-val | number:4}} +
+ + it('should format numbers', function(){ + expect(binding('val | number')).toBe('1,234.57'); + expect(binding('val | number:0')).toBe('1,235'); + expect(binding('-val | number:4')).toBe('-1,234.5679'); + }); + + it('should update', function(){ + input('val').enter('3374.333'); + expect(binding('val | number')).toBe('3,374.33'); + expect(binding('val | number:0')).toBe('3,374'); + expect(binding('-val | number:4')).toBe('-3,374.3330'); + }); + +
*/ angularFilter.number = function(number, fractionSize){ if (isNaN(number) || !isFinite(number)) { @@ -183,19 +191,22 @@ var NUMBER_STRING = /^\d+$/; * @returns {string} Formatted string or the input if input is not recognized as date/millis. * * @example - {{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}: - {{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}
- {{1288323623006 | date:'MM/dd/yyyy @ h:mma'}}: - {{'1288323623006' | date:'MM/dd/yyyy @ h:mma'}}
- * - * @scenario - it('should format date', function(){ - expect(binding("1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'")). - toMatch(/2010\-10\-2\d \d{2}:\d{2}:\d{2} \-?\d{4}/); - expect(binding("'1288323623006' | date:'MM/dd/yyyy @ h:mma'")). - toMatch(/10\/2\d\/2010 @ \d{1,2}:\d{2}(am|pm)/); - }); - * + + + {{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}: + {{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}
+ {{1288323623006 | date:'MM/dd/yyyy @ h:mma'}}: + {{'1288323623006' | date:'MM/dd/yyyy @ h:mma'}}
+
+ + it('should format date', function(){ + expect(binding("1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'")). + toMatch(/2010\-10\-2\d \d{2}:\d{2}:\d{2} \-?\d{4}/); + expect(binding("'1288323623006' | date:'MM/dd/yyyy @ h:mma'")). + toMatch(/10\/2\d\/2010 @ \d{1,2}:\d{2}(am|pm)/); + }); + +
*/ angularFilter.date = function(date, format) { if (isString(date)) { @@ -255,19 +266,23 @@ angularFilter.date = function(date, format) { * @css ng-monospace Always applied to the encapsulating element. * * @example: - -
{{ obj | json }}
- * - * @scenario - it('should jsonify filtered objects', function() { - expect(binding('obj | json')).toBe('{\n "a":1,\n "b":[]}'); - }); - - it('should update', function() { - input('objTxt').enter('[1, 2, 3]'); - expect(binding('obj | json')).toBe('[1,2,3]'); - }); + + + +
{{ obj | json }}
+
+ + it('should jsonify filtered objects', function() { + expect(binding('obj | json')).toBe('{\n "a":1,\n "b":[]}'); + }); + + it('should update', function() { + input('objTxt').enter('[1, 2, 3]'); + expect(binding('obj | json')).toBe('[1,2,3]'); + }); + +
* */ angularFilter.json = function(object) { @@ -324,63 +339,67 @@ angularFilter.uppercase = uppercase; * @returns {string} Sanitized or raw html. * * @example - Snippet: - - - - - - - - - - - - - - - - - - - - - -
FilterSourceRendered
html filter -
<div ng:bind="snippet | html">
</div>
-
-
-
no filter
<div ng:bind="snippet">
</div>
unsafe html filter
<div ng:bind="snippet | html:'unsafe'">
</div>
- * - * @scenario - it('should sanitize the html snippet ', function(){ - expect(using('#html-filter').binding('snippet | html')). - toBe('

an html\nclick here\nsnippet

'); - }); - - it ('should escape snippet without any filter', function() { - expect(using('#escaped-html').binding('snippet')). - toBe("<p style=\"color:blue\">an html\n" + - "<em onmouseover=\"this.textContent='PWN3D!'\">click here</em>\n" + - "snippet</p>"); - }); - - it ('should inline raw snippet if filtered as unsafe', function() { - expect(using('#html-unsafe-filter').binding("snippet | html:'unsafe'")). - toBe("

an html\n" + - "click here\n" + - "snippet

"); - }); - - it('should update', function(){ - input('snippet').enter('new text'); - expect(using('#html-filter').binding('snippet | html')).toBe('new text'); - expect(using('#escaped-html').binding('snippet')).toBe("new <b>text</b>"); - expect(using('#html-unsafe-filter').binding("snippet | html:'unsafe'")).toBe('new text'); - }); + + + + + + + + + + + + + + + + + + + + + +
FilterSourceRendered
html filter +
<div ng:bind="snippet | html">
</div>
+
+
+
no filter
<div ng:bind="snippet">
</div>
unsafe html filter
<div ng:bind="snippet | html:'unsafe'">
</div>
+
+ + it('should sanitize the html snippet ', function(){ + expect(using('#html-filter').binding('snippet | html')). + toBe('

an html\nclick here\nsnippet

'); + }); + + it('should escape snippet without any filter', function() { + expect(using('#escaped-html').binding('snippet')). + toBe("<p style=\"color:blue\">an html\n" + + "<em onmouseover=\"this.textContent='PWN3D!'\">click here</em>\n" + + "snippet</p>"); + }); + + it('should inline raw snippet if filtered as unsafe', function() { + expect(using('#html-unsafe-filter').binding("snippet | html:'unsafe'")). + toBe("

an html\n" + + "click here\n" + + "snippet

"); + }); + + it('should update', function(){ + input('snippet').enter('new text'); + expect(using('#html-filter').binding('snippet | html')).toBe('new text'); + expect(using('#escaped-html').binding('snippet')).toBe("new <b>text</b>"); + expect(using('#html-unsafe-filter').binding("snippet | html:'unsafe'")).toBe('new text'); + }); +
+
*/ angularFilter.html = function(html, option){ return new HTML(html, option); @@ -401,59 +420,63 @@ angularFilter.html = function(html, option){ * @returns {string} Html-linkified text. * * @example - Snippet: - - - - - - - - - - - - - - - - -
FilterSourceRendered
linky filter -
<div ng:bind="snippet | linky">
</div>
-
-
-
no filter
<div ng:bind="snippet">
</div>
- - @scenario - it('should linkify the snippet with urls', function(){ - expect(using('#linky-filter').binding('snippet | linky')). - toBe('Pretty text with some links:\n' + - 'http://angularjs.org/,\n' + - 'us@somewhere.org,\n' + - 'another@somewhere.org,\n' + - 'and one more: ftp://127.0.0.1/.'); - }); - - it ('should not linkify snippet without the linky filter', function() { - expect(using('#escaped-html').binding('snippet')). - toBe("Pretty text with some links:\n" + - "http://angularjs.org/,\n" + - "mailto:us@somewhere.org,\n" + - "another@somewhere.org,\n" + - "and one more: ftp://127.0.0.1/."); - }); - - it('should update', function(){ - input('snippet').enter('new http://link.'); - expect(using('#linky-filter').binding('snippet | linky')). - toBe('new http://link.'); - expect(using('#escaped-html').binding('snippet')).toBe('new http://link.'); - }); + + + Snippet: + + + + + + + + + + + + + + + + +
FilterSourceRendered
linky filter +
<div ng:bind="snippet | linky">
</div>
+
+
+
no filter
<div ng:bind="snippet">
</div>
+
+ + it('should linkify the snippet with urls', function(){ + expect(using('#linky-filter').binding('snippet | linky')). + toBe('Pretty text with some links:\n' + + 'http://angularjs.org/,\n' + + 'us@somewhere.org,\n' + + 'another@somewhere.org,\n' + + 'and one more: ftp://127.0.0.1/.'); + }); + + it ('should not linkify snippet without the linky filter', function() { + expect(using('#escaped-html').binding('snippet')). + toBe("Pretty text with some links:\n" + + "http://angularjs.org/,\n" + + "mailto:us@somewhere.org,\n" + + "another@somewhere.org,\n" + + "and one more: ftp://127.0.0.1/."); + }); + + it('should update', function(){ + input('snippet').enter('new http://link.'); + expect(using('#linky-filter').binding('snippet | linky')). + toBe('new http://link.'); + expect(using('#escaped-html').binding('snippet')).toBe('new http://link.'); + }); + +
*/ //TODO: externalize all regexps angularFilter.linky = function(text){ diff --git a/src/formatters.js b/src/formatters.js index e96e3634..d0fea46e 100644 --- a/src/formatters.js +++ b/src/formatters.js @@ -18,17 +18,21 @@ angularFormatter.noop = formatter(identity, identity); * @returns {?string} A JSON string representation of the model. * * @example - *
- * - *
data={{data}}
- *
- * - * @scenario - * it('should format json', function(){ - * expect(binding('data')).toEqual('data={\n \"name\":\"misko\",\n \"project\":\"angular\"}'); - * input('data').enter('{}'); - * expect(binding('data')).toEqual('data={\n }'); - * }); + + +
+ +
data={{data}}
+
+
+ + it('should format json', function(){ + expect(binding('data')).toEqual('data={\n \"name\":\"misko\",\n \"project\":\"angular\"}'); + input('data').enter('{}'); + expect(binding('data')).toEqual('data={\n }'); + }); + +
*/ angularFormatter.json = formatter(toJson, function(value){ return fromJson(value || 'null'); @@ -45,17 +49,21 @@ angularFormatter.json = formatter(toJson, function(value){ * @returns {boolean} Converts to `true` unless user enters (blank), `f`, `false`, `0`, `no`, `[]`. * * @example - * Enter truthy text: - * - * - *
value={{value}}
- * - * @scenario - * it('should format boolean', function(){ - * expect(binding('value')).toEqual('value=false'); - * input('value').enter('truthy'); - * expect(binding('value')).toEqual('value=true'); - * }); + + + Enter truthy text: + + +
value={{value}}
+
+ + it('should format boolean', function(){ + expect(binding('value')).toEqual('value=false'); + input('value').enter('truthy'); + expect(binding('value')).toEqual('value=true'); + }); + +
*/ angularFormatter['boolean'] = formatter(toString, toBoolean); @@ -70,16 +78,20 @@ angularFormatter['boolean'] = formatter(toString, toBoolean); * @returns {number} Number from the parsed string. * * @example - * Enter valid number: - * - *
value={{value}}
- * - * @scenario - * it('should format numbers', function(){ - * expect(binding('value')).toEqual('value=1234'); - * input('value').enter('5678'); - * expect(binding('value')).toEqual('value=5678'); - * }); + + + Enter valid number: + +
value={{value}}
+
+ + it('should format numbers', function(){ + expect(binding('value')).toEqual('value=1234'); + input('value').enter('5678'); + expect(binding('value')).toEqual('value=5678'); + }); + +
*/ angularFormatter.number = formatter(toString, function(obj){ if (obj == _null || NUMBER.exec(obj)) { @@ -100,20 +112,24 @@ angularFormatter.number = formatter(toString, function(obj){ * @returns {Array} Array parsed from the entered string. * * @example - * Enter a list of items: - * - * - *
value={{value}}
- * - * @scenario - * it('should format lists', function(){ - * expect(binding('value')).toEqual('value=["chair","table"]'); - * this.addFutureAction('change to XYZ', function($window, $document, done){ - * $document.elements('.doc-example :input:last').val(',,a,b,').trigger('change'); - * done(); - * }); - * expect(binding('value')).toEqual('value=["a","b"]'); - * }); + + + Enter a list of items: + + +
value={{value}}
+
+ + it('should format lists', function(){ + expect(binding('value')).toEqual('value=["chair","table"]'); + this.addFutureAction('change to XYZ', function($window, $document, done){ + $document.elements('.doc-example :input:last').val(',,a,b,').trigger('change'); + done(); + }); + expect(binding('value')).toEqual('value=["a","b"]'); + }); + +
*/ angularFormatter.list = formatter( function(obj) { return obj ? obj.join(", ") : obj; }, @@ -138,20 +154,24 @@ angularFormatter.list = formatter( * @returns {String} Trim excess leading and trailing space. * * @example - * Enter text with leading/trailing spaces: - * - * - *
value={{value|json}}
- * - * @scenario - * it('should format trim', function(){ - * expect(binding('value')).toEqual('value="book"'); - * this.addFutureAction('change to XYZ', function($window, $document, done){ - * $document.elements('.doc-example :input:last').val(' text ').trigger('change'); - * done(); - * }); - * expect(binding('value')).toEqual('value="text"'); - * }); + + + Enter text with leading/trailing spaces: + + +
value={{value|json}}
+
+ + it('should format trim', function(){ + expect(binding('value')).toEqual('value="book"'); + this.addFutureAction('change to XYZ', function($window, $document, done){ + $document.elements('.doc-example :input:last').val(' text ').trigger('change'); + done(); + }); + expect(binding('value')).toEqual('value="text"'); + }); + +
*/ angularFormatter.trim = formatter( function(obj) { return obj ? trim("" + obj) : ""; } @@ -176,33 +196,36 @@ angularFormatter.trim = formatter( * @returns {object} object which is located at the selected position. * * @example - * - *
- * User: - * - * - * user={{currentUser.name}}
- * password={{currentUser.password}}
- *
- * - * @scenario - * it('should retrieve object by index', function(){ - * expect(binding('currentUser.password')).toEqual('guest'); - * select('currentUser').option('2'); - * expect(binding('currentUser.password')).toEqual('abc'); - * }); + + + +
+ User: + + + user={{currentUser.name}}
+ password={{currentUser.password}}
+ + + it('should retrieve object by index', function(){ + expect(binding('currentUser.password')).toEqual('guest'); + select('currentUser').option('2'); + expect(binding('currentUser.password')).toEqual('abc'); + }); + + */ angularFormatter.index = formatter( function(object, array){ diff --git a/src/services.js b/src/services.js index 68860e22..f54234a6 100644 --- a/src/services.js +++ b/src/services.js @@ -22,8 +22,19 @@ function angularServiceInject(name, fn, inject, eager) { * suffer from window globality. * * @example +<<<<<<< HEAD +======= + + + + + + + + +>>>>>>> changed the documentation @example to use */ angularServiceInject("$window", bind(window, identity, window), [], EAGER); @@ -63,10 +74,16 @@ angularServiceInject("$document", function(window){ * Notice that using browser's forward/back buttons changes the $location. * * @example - clear hash | - test hash
- -
$location = {{$location}}
+ + + clear hash | + test hash
+ +
$location = {{$location}}
+
+ + +
*/ angularServiceInject("$location", function($browser) { var scope = this, @@ -98,9 +115,15 @@ angularServiceInject("$location", function($browser) { * Browser is updated at the end of $eval() * * @example - * scope.$location.update('http://www.angularjs.org/path#hash?search=x'); - * scope.$location.update({host: 'www.google.com', protocol: 'https'}); - * scope.$location.update({hashPath: '/path', hashSearch: {a: 'b', x: true}}); + + + scope.$location.update('http://www.angularjs.org/path#hash?search=x'); + scope.$location.update({host: 'www.google.com', protocol: 'https'}); + scope.$location.update({hashPath: '/path', hashSearch: {a: 'b', x: true}}); + + + + * * @param {(string|Object)} href Full href as a string or object with properties */ @@ -133,14 +156,18 @@ angularServiceInject("$location", function($browser) { * @see update() * * @example - * scope.$location.updateHash('/hp') - * ==> update({hashPath: '/hp'}) - * - * scope.$location.updateHash({a: true, b: 'val'}) - * ==> update({hashSearch: {a: true, b: 'val'}}) - * - * scope.$location.updateHash('/hp', {a: true}) - * ==> update({hashPath: '/hp', hashSearch: {a: true}}) + + + scope.$location.updateHash('/hp') + ==> update({hashPath: '/hp'}) + scope.$location.updateHash({a: true, b: 'val'}) + ==> update({hashSearch: {a: true, b: 'val'}}) + scope.$location.updateHash('/hp', {a: true}) + ==> update({hashPath: '/hp', hashSearch: {a: true}}) + + + + * * @param {(string|Object)} path A hashPath or hashSearch object * @param {Object=} search A hashSearch object @@ -176,7 +203,9 @@ angularServiceInject("$location", function($browser) { * - everything else * * @example - * scope.$location.href = 'http://www.angularjs.org/path#a/b' + *
+   *   scope.$location.href = 'http://www.angularjs.org/path#a/b'
+   * 
* immediately after this call, other properties are still the old ones... * * This method checks the changes and update location to the consistent state @@ -298,13 +327,19 @@ angularServiceInject("$location", function($browser) { * The main purpose of this service is to simplify debugging and troubleshooting. * * @example -

Reload this page with open console, enter text and hit the log button...

- Message: - - - - - + + +

Reload this page with open console, enter text and hit the log button...

+ Message: + + + + + +
+ + +
*/ var $logFactory; //reference to be used only in tests angularServiceInject("$log", $logFactory = function($window){ @@ -622,42 +657,46 @@ function switchRouteMatcher(on, when, dstName) { * widget. * * @example -

- This example shows how changing the URL hash causes the $route - to match a route against the URL, and the [[ng:include]] pulls in the partial. - Try changing the URL in the input box to see changes. -

- - - -Chose: -Moby | -Moby: Ch1 | -Gatsby | -Gatsby: Ch4
- -
$location={{$location}}
-
$route.current.template={{$route.current.template}}
-
$route.current.params={{$route.current.params}}
-
$route.current.scope.name={{$route.current.scope.name}}
-
- + function ChapterCntl() { + this.name = "ChapterCntl"; + } + + + Chose: + Moby | + Moby: Ch1 | + Gatsby | + Gatsby: Ch4
+ +
$location={{$location}}
+
$route.current.template={{$route.current.template}}
+
$route.current.params={{$route.current.params}}
+
$route.current.scope.name={{$route.current.scope.name}}
+
+ + + + +
*/ angularServiceInject('$route', function(location) { var routes = {}, @@ -1122,43 +1161,49 @@ angularServiceInject('$xhr.cache', function($xhr, $defer, $log){ * @returns {Object} A resource "class". * * @example - - -
- - -
-
-

- - {{item.actor.name}} - Expand replies: {{item.links.replies[0].count}} -

- {{item.object.content | html}} -
- - {{reply.actor.name}}: {{reply.content | html}} + + + + +
+ + +
+
+

+ + {{item.actor.name}} + Expand replies: {{item.links.replies[0].count}} +

+ {{item.object.content | html}} +
+ + {{reply.actor.name}}: {{reply.content | html}} +
+
-
-
+ + + + */ angularServiceInject('$resource', function($xhr){ var resource = new ResourceFactory($xhr); diff --git a/src/validators.js b/src/validators.js index 30936574..e2a9d7f6 100644 --- a/src/validators.js +++ b/src/validators.js @@ -14,24 +14,27 @@ extend(angularValidator, { * @css ng-validation-error * * @example - * - * Enter valid SSN: - *
- * - *
- * - * @scenario - * it('should invalidate non ssn', function(){ - * var textBox = element('.doc-example :input'); - * expect(textBox.attr('className')).not().toMatch(/ng-validation-error/); - * expect(textBox.val()).toEqual('123-45-6789'); - * - * input('ssn').enter('123-45-67890'); - * expect(textBox.attr('className')).toMatch(/ng-validation-error/); - * }); + + + + Enter valid SSN: +
+ +
+
+ + it('should invalidate non ssn', function(){ + var textBox = element('.doc-example :input'); + expect(textBox.attr('className')).not().toMatch(/ng-validation-error/); + expect(textBox.val()).toEqual('123-45-6789'); + input('ssn').enter('123-45-67890'); + expect(textBox.attr('className')).toMatch(/ng-validation-error/); + }); + +
* */ 'regexp': function(value, regexp, msg) { @@ -57,28 +60,29 @@ extend(angularValidator, { * @css ng-validation-error * * @example - * Enter number:
- * Enter number greater than 10:
- * Enter number between 100 and 200:
- * - * @scenario - * it('should invalidate number', function(){ - * var n1 = element('.doc-example :input[name=n1]'); - * expect(n1.attr('className')).not().toMatch(/ng-validation-error/); - * input('n1').enter('1.x'); - * expect(n1.attr('className')).toMatch(/ng-validation-error/); - * - * var n2 = element('.doc-example :input[name=n2]'); - * expect(n2.attr('className')).not().toMatch(/ng-validation-error/); - * input('n2').enter('9'); - * expect(n2.attr('className')).toMatch(/ng-validation-error/); - * - * var n3 = element('.doc-example :input[name=n3]'); - * expect(n3.attr('className')).not().toMatch(/ng-validation-error/); - * input('n3').enter('201'); - * expect(n3.attr('className')).toMatch(/ng-validation-error/); - * - * }); + + + Enter number:
+ Enter number greater than 10:
+ Enter number between 100 and 200:
+
+ + it('should invalidate number', function(){ + var n1 = element('.doc-example :input[name=n1]'); + expect(n1.attr('className')).not().toMatch(/ng-validation-error/); + input('n1').enter('1.x'); + expect(n1.attr('className')).toMatch(/ng-validation-error/); + var n2 = element('.doc-example :input[name=n2]'); + expect(n2.attr('className')).not().toMatch(/ng-validation-error/); + input('n2').enter('9'); + expect(n2.attr('className')).toMatch(/ng-validation-error/); + var n3 = element('.doc-example :input[name=n3]'); + expect(n3.attr('className')).not().toMatch(/ng-validation-error/); + input('n3').enter('201'); + expect(n3.attr('className')).toMatch(/ng-validation-error/); + }); + +
* */ 'number': function(value, min, max) { @@ -110,28 +114,29 @@ extend(angularValidator, { * @css ng-validation-error * * @example - * Enter integer:
- * Enter integer equal or greater than 10:
- * Enter integer between 100 and 200 (inclusive):
- * - * @scenario - * it('should invalidate integer', function(){ - * var n1 = element('.doc-example :input[name=n1]'); - * expect(n1.attr('className')).not().toMatch(/ng-validation-error/); - * input('n1').enter('1.1'); - * expect(n1.attr('className')).toMatch(/ng-validation-error/); - * - * var n2 = element('.doc-example :input[name=n2]'); - * expect(n2.attr('className')).not().toMatch(/ng-validation-error/); - * input('n2').enter('10.1'); - * expect(n2.attr('className')).toMatch(/ng-validation-error/); - * - * var n3 = element('.doc-example :input[name=n3]'); - * expect(n3.attr('className')).not().toMatch(/ng-validation-error/); - * input('n3').enter('100.1'); - * expect(n3.attr('className')).toMatch(/ng-validation-error/); - * - * }); + + + Enter integer:
+ Enter integer equal or greater than 10:
+ Enter integer between 100 and 200 (inclusive):
+
+ + it('should invalidate integer', function(){ + var n1 = element('.doc-example :input[name=n1]'); + expect(n1.attr('className')).not().toMatch(/ng-validation-error/); + input('n1').enter('1.1'); + expect(n1.attr('className')).toMatch(/ng-validation-error/); + var n2 = element('.doc-example :input[name=n2]'); + expect(n2.attr('className')).not().toMatch(/ng-validation-error/); + input('n2').enter('10.1'); + expect(n2.attr('className')).toMatch(/ng-validation-error/); + var n3 = element('.doc-example :input[name=n3]'); + expect(n3.attr('className')).not().toMatch(/ng-validation-error/); + input('n3').enter('100.1'); + expect(n3.attr('className')).toMatch(/ng-validation-error/); + }); + +
*/ 'integer': function(value, min, max) { var numberError = angularValidator['number'](value, min, max); @@ -154,16 +159,20 @@ extend(angularValidator, { * @css ng-validation-error * * @example - * Enter valid date: - * - * - * @scenario - * it('should invalidate date', function(){ - * var n1 = element('.doc-example :input'); - * expect(n1.attr('className')).not().toMatch(/ng-validation-error/); - * input('text').enter('123/123/123'); - * expect(n1.attr('className')).toMatch(/ng-validation-error/); - * }); + + + Enter valid date: + + + + it('should invalidate date', function(){ + var n1 = element('.doc-example :input'); + expect(n1.attr('className')).not().toMatch(/ng-validation-error/); + input('text').enter('123/123/123'); + expect(n1.attr('className')).toMatch(/ng-validation-error/); + }); + + * */ 'date': function(value) { @@ -187,16 +196,20 @@ extend(angularValidator, { * @css ng-validation-error * * @example - * Enter valid email: - * - * - * @scenario - * it('should invalidate email', function(){ - * var n1 = element('.doc-example :input'); - * expect(n1.attr('className')).not().toMatch(/ng-validation-error/); - * input('text').enter('a@b.c'); - * expect(n1.attr('className')).toMatch(/ng-validation-error/); - * }); + + + Enter valid email: + + + + it('should invalidate email', function(){ + var n1 = element('.doc-example :input'); + expect(n1.attr('className')).not().toMatch(/ng-validation-error/); + input('text').enter('a@b.c'); + expect(n1.attr('className')).toMatch(/ng-validation-error/); + }); + + * */ 'email': function(value) { @@ -217,16 +230,20 @@ extend(angularValidator, { * @css ng-validation-error * * @example - * Enter valid phone number: - * - * - * @scenario - * it('should invalidate phone', function(){ - * var n1 = element('.doc-example :input'); - * expect(n1.attr('className')).not().toMatch(/ng-validation-error/); - * input('text').enter('+12345678'); - * expect(n1.attr('className')).toMatch(/ng-validation-error/); - * }); + + + Enter valid phone number: + + + + it('should invalidate phone', function(){ + var n1 = element('.doc-example :input'); + expect(n1.attr('className')).not().toMatch(/ng-validation-error/); + input('text').enter('+12345678'); + expect(n1.attr('className')).toMatch(/ng-validation-error/); + }); + + * */ 'phone': function(value) { @@ -250,16 +267,20 @@ extend(angularValidator, { * @css ng-validation-error * * @example - * Enter valid phone number: - * - * - * @scenario - * it('should invalidate url', function(){ - * var n1 = element('.doc-example :input'); - * expect(n1.attr('className')).not().toMatch(/ng-validation-error/); - * input('text').enter('abc://server/path'); - * expect(n1.attr('className')).toMatch(/ng-validation-error/); - * }); + + + Enter valid phone number: + + + + it('should invalidate url', function(){ + var n1 = element('.doc-example :input'); + expect(n1.attr('className')).not().toMatch(/ng-validation-error/); + input('text').enter('abc://server/path'); + expect(n1.attr('className')).toMatch(/ng-validation-error/); + }); + + * */ 'url': function(value) { @@ -280,17 +301,21 @@ extend(angularValidator, { * @css ng-validation-error * * @example - * - * - * @scenario - * it('should invalidate json', function(){ - * var n1 = element('.doc-example :input'); - * expect(n1.attr('className')).not().toMatch(/ng-validation-error/); - * input('json').enter('{name}'); - * expect(n1.attr('className')).toMatch(/ng-validation-error/); - * }); + + + + + + it('should invalidate json', function(){ + var n1 = element('.doc-example :input'); + expect(n1.attr('className')).not().toMatch(/ng-validation-error/); + input('json').enter('{name}'); + expect(n1.attr('className')).toMatch(/ng-validation-error/); + }); + + * */ 'json': function(value) { @@ -338,35 +363,35 @@ extend(angularValidator, { * @css ng-input-indicator-wait, ng-validation-error * * @example - * - * This input is validated asynchronously: - *
- * - *
- * - * @scenario - * it('should change color in delayed way', function(){ - * var textBox = element('.doc-example :input'); - * expect(textBox.attr('className')).not().toMatch(/ng-input-indicator-wait/); - * expect(textBox.attr('className')).not().toMatch(/ng-validation-error/); - * - * input('text').enter('X'); - * expect(textBox.attr('className')).toMatch(/ng-input-indicator-wait/); - * - * pause(.6); - * - * expect(textBox.attr('className')).not().toMatch(/ng-input-indicator-wait/); - * expect(textBox.attr('className')).toMatch(/ng-validation-error/); - * - * }); + + + + This input is validated asynchronously: +
+ +
+
+ + it('should change color in delayed way', function(){ + var textBox = element('.doc-example :input'); + expect(textBox.attr('className')).not().toMatch(/ng-input-indicator-wait/); + expect(textBox.attr('className')).not().toMatch(/ng-validation-error/); + input('text').enter('X'); + expect(textBox.attr('className')).toMatch(/ng-input-indicator-wait/); + pause(.6); + expect(textBox.attr('className')).not().toMatch(/ng-input-indicator-wait/); + expect(textBox.attr('className')).toMatch(/ng-validation-error/); + }); + +
* */ /* diff --git a/src/widgets.js b/src/widgets.js index cf65cd40..ea76cfc2 100644 --- a/src/widgets.js +++ b/src/widgets.js @@ -19,117 +19,122 @@ * * * @example - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameFormatHTMLUI{{input#}}
textString<input type="text" name="input1">{{input1|json}}
textareaString<textarea name="input2"></textarea>{{input2|json}}
radioString - <input type="radio" name="input3" value="A">
- <input type="radio" name="input3" value="B"> -
- - - {{input3|json}}
checkboxBoolean<input type="checkbox" name="input4" value="checked">{{input4|json}}
pulldownString - <select name="input5">
-   <option value="c">C</option>
-   <option value="d">D</option>
- </select>
-
- - {{input5|json}}
multiselectArray - <select name="input6" multiple size="4">
-   <option value="e">E</option>
-   <option value="f">F</option>
- </select>
-
- - {{input6|json}}
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameFormatHTMLUI{{input#}}
textString<input type="text" name="input1">{{input1|json}}
textareaString<textarea name="input2"></textarea>{{input2|json}}
radioString + <input type="radio" name="input3" value="A">
+ <input type="radio" name="input3" value="B"> +
+ + + {{input3|json}}
checkboxBoolean<input type="checkbox" name="input4" value="checked">{{input4|json}}
pulldownString + <select name="input5">
+   <option value="c">C</option>
+   <option value="d">D</option>
+ </select>
+
+ + {{input5|json}}
multiselectArray + <select name="input6" multiple size="4">
+   <option value="e">E</option>
+   <option value="f">F</option>
+ </select>
+
+ + {{input6|json}}
+
+ - * @scenario - * it('should exercise text', function(){ - * input('input1').enter('Carlos'); - * expect(binding('input1')).toEqual('"Carlos"'); - * }); - * it('should exercise textarea', function(){ - * input('input2').enter('Carlos'); - * expect(binding('input2')).toEqual('"Carlos"'); - * }); - * it('should exercise radio', function(){ - * expect(binding('input3')).toEqual('null'); - * input('input3').select('A'); - * expect(binding('input3')).toEqual('"A"'); - * input('input3').select('B'); - * expect(binding('input3')).toEqual('"B"'); - * }); - * it('should exercise checkbox', function(){ - * expect(binding('input4')).toEqual('false'); - * input('input4').check(); - * expect(binding('input4')).toEqual('true'); - * }); - * it('should exercise pulldown', function(){ - * expect(binding('input5')).toEqual('"c"'); - * select('input5').option('d'); - * expect(binding('input5')).toEqual('"d"'); - * }); - * it('should exercise multiselect', function(){ - * expect(binding('input6')).toEqual('[]'); - * select('input6').options('e'); - * expect(binding('input6')).toEqual('["e"]'); - * select('input6').options('e', 'f'); - * expect(binding('input6')).toEqual('["e","f"]'); - * }); + it('should exercise text', function(){ + input('input1').enter('Carlos'); + expect(binding('input1')).toEqual('"Carlos"'); + }); + it('should exercise textarea', function(){ + input('input2').enter('Carlos'); + expect(binding('input2')).toEqual('"Carlos"'); + }); + it('should exercise radio', function(){ + expect(binding('input3')).toEqual('null'); + input('input3').select('A'); + expect(binding('input3')).toEqual('"A"'); + input('input3').select('B'); + expect(binding('input3')).toEqual('"B"'); + }); + it('should exercise checkbox', function(){ + expect(binding('input4')).toEqual('false'); + input('input4').check(); + expect(binding('input4')).toEqual('true'); + }); + it('should exercise pulldown', function(){ + expect(binding('input5')).toEqual('"c"'); + select('input5').option('d'); + expect(binding('input5')).toEqual('"d"'); + }); + it('should exercise multiselect', function(){ + expect(binding('input6')).toEqual('[]'); + select('input6').options('e'); + expect(binding('input6')).toEqual('["e"]'); + select('input6').options('e', 'f'); + expect(binding('input6')).toEqual('["e","f"]'); + }); + +
*/ function modelAccessor(scope, element) { @@ -193,26 +198,29 @@ function compileFormatter(expr) { * @element INPUT * @css ng-validation-error * - * @exampleDescription + * @example * This example shows how the input element becomes red when it contains invalid input. Correct * the input to make the error disappear. * - * @example - I don't validate: -
+ + + I don't validate: +
- I need an integer or nothing: -
- * - * @scenario - it('should check ng:validate', function(){ - expect(element('.doc-example-live :input:last').attr('className')). - toMatch(/ng-validation-error/); + I need an integer or nothing: +
+
+ + it('should check ng:validate', function(){ + expect(element('.doc-example-live :input:last').attr('className')). + toMatch(/ng-validation-error/); - input('value').enter('123'); - expect(element('.doc-example-live :input:last').attr('className')). - not().toMatch(/ng-validation-error/); - }); + input('value').enter('123'); + expect(element('.doc-example-live :input:last').attr('className')). + not().toMatch(/ng-validation-error/); + }); + +
*/ /** * @workInProgress @@ -226,19 +234,22 @@ function compileFormatter(expr) { * @element INPUT * @css ng-validation-error * - * @exampleDescription + * @example * This example shows how the input element becomes red when it contains invalid input. Correct * the input to make the error disappear. * - * @example - I cannot be blank:
- * - * @scenario - it('should check ng:required', function(){ - expect(element('.doc-example-live :input').attr('className')).toMatch(/ng-validation-error/); - input('value').enter('123'); - expect(element('.doc-example-live :input').attr('className')).not().toMatch(/ng-validation-error/); - }); + + + I cannot be blank:
+
+ + it('should check ng:required', function(){ + expect(element('.doc-example-live :input').attr('className')).toMatch(/ng-validation-error/); + input('value').enter('123'); + expect(element('.doc-example-live :input').attr('className')).not().toMatch(/ng-validation-error/); + }); + +
*/ /** * @workInProgress @@ -256,21 +267,24 @@ function compileFormatter(expr) { * * @element INPUT * - * @exampleDescription + * @example * This example shows how the user input is converted from a string and internally represented as an * array. * - * @example - Enter a comma separated list of items: - -
list={{list}}
- * - * @scenario - it('should check ng:format', function(){ - expect(binding('list')).toBe('list=["table","chairs","plate"]'); - input('list').enter(',,, a ,,,'); - expect(binding('list')).toBe('list=["a"]'); - }); + + + Enter a comma separated list of items: + +
list={{list}}
+
+ + it('should check ng:format', function(){ + expect(binding('list')).toBe('list=["table","chairs","plate"]'); + input('list').enter(',,, a ,,,'); + expect(binding('list')).toBe('list=["a"]'); + }); + +
*/ function valueAccessor(scope, element) { var validatorName = element.attr('ng:validate') || NOOP, @@ -453,28 +467,32 @@ function radioInit(model, view, element) { * @element INPUT * @param {expression} expression to execute. * - * @exampleDescription * @example -
- - changeCount {{textCount}}
- - changeCount {{checkboxCount}}
- * - * @scenario - it('should check ng:change', function(){ - expect(binding('textCount')).toBe('0'); - expect(binding('checkboxCount')).toBe('0'); + * @example + + +
+ + changeCount {{textCount}}
+ + changeCount {{checkboxCount}}
+
+ + it('should check ng:change', function(){ + expect(binding('textCount')).toBe('0'); + expect(binding('checkboxCount')).toBe('0'); - using('.doc-example-live').input('text').enter('abc'); - expect(binding('textCount')).toBe('1'); - expect(binding('checkboxCount')).toBe('0'); + using('.doc-example-live').input('text').enter('abc'); + expect(binding('textCount')).toBe('1'); + expect(binding('checkboxCount')).toBe('0'); - using('.doc-example-live').input('checkbox').check(); - expect(binding('textCount')).toBe('1'); - expect(binding('checkboxCount')).toBe('1'); - }); + using('.doc-example-live').input('checkbox').check(); + expect(binding('textCount')).toBe('1'); + expect(binding('checkboxCount')).toBe('1'); + }); + +
*/ function inputWidget(events, modelAccessor, viewAccessor, initFn, textBox) { return injectService(['$updateView', '$defer'], function($updateView, $defer, element) { @@ -594,27 +612,31 @@ angularWidget('option', function(){ * @param {string=} onload Expression to evaluate when a new partial is loaded. * * @example - * - * url = {{url}} - *
- * - * - * @scenario - * it('should load date filter', function(){ - * expect(element('.doc-example ng\\:include').text()).toMatch(/angular\.filter\.date/); - * }); - * it('should change to hmtl filter', function(){ - * select('url').option('angular.filter.html.html'); - * expect(element('.doc-example ng\\:include').text()).toMatch(/angular\.filter\.html/); - * }); - * it('should change to blank', function(){ - * select('url').option('(blank)'); - * expect(element('.doc-example ng\\:include').text()).toEqual(''); - * }); + + + + url = {{url}} +
+ +
+ + it('should load date filter', function(){ + expect(element('.doc-example ng\\:include').text()).toMatch(/angular\.filter\.date/); + }); + it('should change to hmtl filter', function(){ + select('url').option('angular.filter.html.html'); + expect(element('.doc-example ng\\:include').text()).toMatch(/angular\.filter\.html/); + }); + it('should change to blank', function(){ + select('url').option('(blank)'); + expect(element('.doc-example ng\\:include').text()).toEqual(''); + }); + +
*/ angularWidget('ng:include', function(element){ var compiler = this, @@ -690,32 +712,36 @@ angularWidget('ng:include', function(element){ * * `ng:switch-default`: the default case when no other casses match. * * @example - - switch={{switch}} - - -
Settings Div
- Home Span - default -
- - * - * @scenario - * it('should start in settings', function(){ - * expect(element('.doc-example ng\\:switch').text()).toEqual('Settings Div'); - * }); - * it('should change to home', function(){ - * select('switch').option('home'); - * expect(element('.doc-example ng\\:switch').text()).toEqual('Home Span'); - * }); - * it('should select deafault', function(){ - * select('switch').option('other'); - * expect(element('.doc-example ng\\:switch').text()).toEqual('default'); - * }); + + + + switch={{switch}} + + +
Settings Div
+ Home Span + default +
+ +
+ + it('should start in settings', function(){ + expect(element('.doc-example ng\\:switch').text()).toEqual('Settings Div'); + }); + it('should change to home', function(){ + select('switch').option('home'); + expect(element('.doc-example ng\\:switch').text()).toEqual('Home Span'); + }); + it('should select deafault', function(){ + select('switch').option('other'); + expect(element('.doc-example ng\\:switch').text()).toEqual('default'); + }); + +
*/ var ngSwitch = angularWidget('ng:switch', function (element){ var compiler = this, @@ -838,25 +864,29 @@ angularWidget('a', function() { * * For example: `(name, age) in {'adam':10, 'amalie':12}`. * - * @exampleDescription + * @example * This example initializes the scope to a list of names and * than uses `ng:repeat` to display every person. - * @example -
- I have {{friends.length}} friends. They are: -
    -
  • - [{{$index + 1}}] {{friend.name}} who is {{friend.age}} years old. -
  • -
-
- * @scenario - it('should check ng:repeat', function(){ - var r = using('.doc-example-live').repeater('ul li'); - expect(r.count()).toBe(2); - expect(r.row(0)).toEqual(["1","John","25"]); - expect(r.row(1)).toEqual(["2","Mary","28"]); - }); + + +
+ I have {{friends.length}} friends. They are: +
    +
  • + [{{$index + 1}}] {{friend.name}} who is {{friend.age}} years old. +
  • +
+
+
+ + it('should check ng:repeat', function(){ + var r = using('.doc-example-live').repeater('ul li'); + expect(r.count()).toBe(2); + expect(r.row(0)).toEqual(["1","John","25"]); + expect(r.row(1)).toEqual(["2","Mary","28"]); + }); + +
*/ angularWidget("@ng:repeat", function(expression, element){ element.removeAttr('ng:repeat'); @@ -946,20 +976,24 @@ angularWidget("@ng:repeat", function(expression, element){ * * @element ANY * - * @exampleDescription + * @example * In this example there are two location where a siple binding (`{{}}`) is present, but the one * wrapped in `ng:non-bindable` is left alone. * * @example -
Normal: {{1 + 2}}
-
Ignored: {{1 + 2}}
- * - * @scenario - it('should check ng:non-bindable', function(){ - expect(using('.doc-example-live').binding('1 + 2')).toBe('3'); - expect(using('.doc-example-live').element('div:last').text()). - toMatch(/1 \+ 2/); - }); + + +
Normal: {{1 + 2}}
+
Ignored: {{1 + 2}}
+
+ + it('should check ng:non-bindable', function(){ + expect(using('.doc-example-live').binding('1 + 2')).toBe('3'); + expect(using('.doc-example-live').element('div:last').text()). + toMatch(/1 \+ 2/); + }); + +
*/ angularWidget("@ng:non-bindable", noop); @@ -989,26 +1023,30 @@ angularWidget("@ng:non-bindable", noop); * - doesn't require `$route` service to be available on the root scope * * - * # Example - * Because of the nature of this widget, we can't include the usual live example for it. Instead - * following is a code snippet showing the typical usage: - * -
-     
-     
- foo | bar | undefined
- The view is included below: -
- -
-
+ function BootstrapCtrl(){} + function OverviewCtrl(){} + +
+ overview | bootstrap | undefined
+ The view is included below: +
+ +
+ + + + */ angularWidget('ng:view', function(element) { var compiler = this; -- cgit v1.2.3