From 5bcd7198664dca2bf85ddf8b3a89f417cd4e4796 Mon Sep 17 00:00:00 2001 From: Vojta Jina Date: Tue, 10 Apr 2012 16:50:31 -0700 Subject: chore(ngSanitize): extract $sanitize, ngBindHtml, linkyFilter into a module Create build for other modules as well (ngResource, ngCookies): - wrap into a function - add license - add version Breaks `$sanitize` service, `ngBindHtml` directive and `linky` filter were moved to the `ngSanitize` module. Apps that depend on any of these will need to load `angular-sanitize.js` and include `ngSanitize` in their dependency list: `var myApp = angular.module('myApp', ['ngSanitize']);` --- test/ng/directive/ngBindSpec.js | 28 +-- test/ng/filter/filtersSpec.js | 26 --- test/ng/sanitizeSpec.js | 281 --------------------------- test/ngSanitize/directive/ngBindHtmlSpec.js | 25 +++ test/ngSanitize/filter/linkySpec.js | 27 +++ test/ngSanitize/sanitizeSpec.js | 286 ++++++++++++++++++++++++++++ test/ngScenario/dslSpec.js | 2 + 7 files changed, 341 insertions(+), 334 deletions(-) delete mode 100644 test/ng/sanitizeSpec.js create mode 100644 test/ngSanitize/directive/ngBindHtmlSpec.js create mode 100644 test/ngSanitize/filter/linkySpec.js create mode 100644 test/ngSanitize/sanitizeSpec.js (limited to 'test') diff --git a/test/ng/directive/ngBindSpec.js b/test/ng/directive/ngBindSpec.js index b3c63b34..da291fa4 100644 --- a/test/ng/directive/ngBindSpec.js +++ b/test/ng/directive/ngBindSpec.js @@ -67,39 +67,13 @@ describe('ngBind*', function() { }); - describe('ngBindHtml', function() { - - it('should set html', inject(function($rootScope, $compile) { - element = $compile('
')($rootScope); - $rootScope.html = '
hello
'; - $rootScope.$digest(); - expect(lowercase(element.html())).toEqual('
hello
'); - })); - - - it('should reset html when value is null or undefined', inject(function($compile, $rootScope) { - element = $compile('
')($rootScope); - - forEach([null, undefined, ''], function(val) { - $rootScope.html = 'some val'; - $rootScope.$digest(); - expect(lowercase(element.html())).toEqual('some val'); - - $rootScope.html = val; - $rootScope.$digest(); - expect(lowercase(element.html())).toEqual(''); - }); - })); - }); - - describe('ngBindHtmlUnsafe', function() { it('should set unsafe html', inject(function($rootScope, $compile) { element = $compile('
')($rootScope); $rootScope.html = '
hello
'; $rootScope.$digest(); - expect(lowercase(element.html())).toEqual('
hello
'); + expect(angular.lowercase(element.html())).toEqual('
hello
'); })); }); }); diff --git a/test/ng/filter/filtersSpec.js b/test/ng/filter/filtersSpec.js index 9ea200a3..55476882 100644 --- a/test/ng/filter/filtersSpec.js +++ b/test/ng/filter/filtersSpec.js @@ -153,32 +153,6 @@ describe('filters', function() { }); }); - describe('linky', function() { - var linky; - - beforeEach(inject(function($filter){ - linky = $filter('linky') - })); - - it('should do basic filter', function() { - expect(linky("http://ab/ (http://a/) http://1.2/v:~-123. c")). - toEqual('http://ab/ ' + - '(http://a/) ' + - '<http://a/> ' + - 'http://1.2/v:~-123. c'); - expect(linky(undefined)).not.toBeDefined(); - }); - - it('should handle mailto:', function() { - expect(linky("mailto:me@example.com")). - toEqual('me@example.com'); - expect(linky("me@example.com")). - toEqual('me@example.com'); - expect(linky("send email to me@example.com, but")). - toEqual('send email to me@example.com, but'); - }); - }); - describe('date', function() { var morning = new angular.mock.TzDate(+5, '2010-09-03T12:05:08.000Z'); //7am diff --git a/test/ng/sanitizeSpec.js b/test/ng/sanitizeSpec.js deleted file mode 100644 index a33d8992..00000000 --- a/test/ng/sanitizeSpec.js +++ /dev/null @@ -1,281 +0,0 @@ -'use strict'; - -describe('HTML', function() { - - var expectHTML; - - beforeEach(inject(function($sanitize) { - expectHTML = function(html){ - return expect($sanitize(html)); - }; - })); - - describe('htmlParser', function() { - var handler, start, text; - beforeEach(function() { - handler = { - start: function(tag, attrs, unary){ - start = { - tag: tag, - attrs: attrs, - unary: unary - }; - // Since different browsers handle newlines differenttly we trim - // so that it is easier to write tests. - forEach(attrs, function(value, key){ - attrs[key] = trim(value); - }); - }, - chars: function(text_){ - text = text_; - }, - end:function(tag) { - expect(tag).toEqual(start.tag); - } - }; - }); - - it('should parse basic format', function() { - htmlParser('text', handler); - expect(start).toEqual({tag:'tag', attrs:{attr:'value'}, unary:false}); - expect(text).toEqual('text'); - }); - - it('should parse newlines in tags', function() { - htmlParser('<\ntag\n attr="value"\n>text<\n/\ntag\n>', handler); - expect(start).toEqual({tag:'tag', attrs:{attr:'value'}, unary:false}); - expect(text).toEqual('text'); - }); - - it('should parse newlines in attributes', function() { - htmlParser('text', handler); - expect(start).toEqual({tag:'tag', attrs:{attr:'value'}, unary:false}); - expect(text).toEqual('text'); - }); - - it('should parse namespace', function() { - htmlParser('text', handler); - expect(start).toEqual({tag:'ns:t-a-g', attrs:{'ns:a-t-t-r':'value'}, unary:false}); - expect(text).toEqual('text'); - }); - - it('should parse empty value attribute of node', function() { - htmlParser('', handler); - expect(start).toEqual({tag:'option', attrs:{selected:'', value:''}, unary:false}); - expect(text).toEqual('abc'); - }); - - }); - - it('should echo html', function() { - expectHTML('helloworld.'). - toEqual('helloworld.'); - }); - - it('should remove script', function() { - expectHTML('ac.').toEqual('ac.'); - }); - - it('should remove double nested script', function() { - expectHTML('ailc.').toEqual('ac.'); - }); - - it('should remove unknown names', function() { - expectHTML('abc').toEqual('abc'); - }); - - it('should remove unsafe value', function() { - expectHTML('').toEqual(''); - }); - - it('should handle self closed elements', function() { - expectHTML('a
c').toEqual('a
c'); - }); - - it('should handle namespace', function() { - expectHTML('abc').toEqual('abc'); - }); - - it('should handle entities', function() { - var everything = '
' + - '!@#$%^&*()_+-={}[]:";\'<>?,./`~ ħ
'; - expectHTML(everything).toEqual(everything); - }); - - it('should handle improper html', function() { - expectHTML('< div rel="" alt=abc dir=\'"\' >text< /div>'). - toEqual('
text
'); - }); - - it('should handle improper html2', function() { - expectHTML('< div rel="" / >'). - toEqual('
'); - }); - - it('should ignore back slash as escape', function() { - expectHTML('xxx\\'). - toEqual('xxx\\'); - }); - - it('should ignore object attributes', function() { - expectHTML(':)'). - toEqual(':)'); - expectHTML(':)'). - toEqual(''); - }); - - describe('htmlSanitizerWriter', function() { - var writer, html; - beforeEach(function() { - html = ''; - writer = htmlSanitizeWriter({push:function(text){html+=text;}}); - }); - - it('should write basic HTML', function() { - writer.chars('before'); - writer.start('div', {rel:'123'}, false); - writer.chars('in'); - writer.end('div'); - writer.chars('after'); - - expect(html).toEqual('before
in
after'); - }); - - it('should escape text nodes', function() { - writer.chars('a
&
c'); - expect(html).toEqual('a<div>&</div>c'); - }); - - it('should escape IE script', function() { - writer.chars('&<>{}'); - expect(html).toEqual('&<>{}'); - }); - - it('should escape attributes', function() { - writer.start('div', {rel:'!@#$%^&*()_+-={}[]:";\'<>?,./`~ \n\0\r\u0127'}); - expect(html).toEqual('
'); - }); - - it('should ignore missformed elements', function() { - writer.start('d>i&v', {}); - expect(html).toEqual(''); - }); - - it('should ignore unknown attributes', function() { - writer.start('div', {unknown:""}); - expect(html).toEqual('
'); - }); - - describe('explicitly dissallow', function() { - it('should not allow attributes', function() { - writer.start('div', {id:'a', name:'a', style:'a'}); - expect(html).toEqual('
'); - }); - - it('should not allow tags', function() { - function tag(name) { - writer.start(name, {}); - writer.end(name); - } - tag('frameset'); - tag('frame'); - tag('form'); - tag('param'); - tag('object'); - tag('embed'); - tag('textarea'); - tag('input'); - tag('button'); - tag('option'); - tag('select'); - tag('script'); - tag('style'); - tag('link'); - tag('base'); - tag('basefont'); - expect(html).toEqual(''); - }); - }); - - describe('isUri', function() { - - function isUri(value) { - return value.match(URI_REGEXP); - } - - it('should be URI', function() { - expect(isUri('http://abc')).toBeTruthy(); - expect(isUri('https://abc')).toBeTruthy(); - expect(isUri('ftp://abc')).toBeTruthy(); - expect(isUri('mailto:me@example.com')).toBeTruthy(); - expect(isUri('#anchor')).toBeTruthy(); - }); - - it('should not be UIR', function() { - expect(isUri('')).toBeFalsy(); - expect(isUri('javascript:alert')).toBeFalsy(); - }); - }); - - describe('javascript URL attribute', function() { - beforeEach(function() { - this.addMatchers({ - toBeValidUrl: function() { - return URI_REGEXP.exec(this.actual); - } - }); - }); - - it('should ignore javascript:', function() { - expect('JavaScript:abc').not.toBeValidUrl(); - expect(' \n Java\n Script:abc').not.toBeValidUrl(); - expect('http://JavaScript/my.js').toBeValidUrl(); - }); - - it('should ignore dec encoded javascript:', function() { - expect('javascript:').not.toBeValidUrl(); - expect('javascript:').not.toBeValidUrl(); - expect('j avascript:').not.toBeValidUrl(); - }); - - it('should ignore decimal with leading 0 encodede javascript:', function() { - expect('javascript:').not.toBeValidUrl(); - expect('j avascript:').not.toBeValidUrl(); - expect('j avascript:').not.toBeValidUrl(); - }); - - it('should ignore hex encoded javascript:', function() { - expect('javascript:').not.toBeValidUrl(); - expect('javascript:').not.toBeValidUrl(); - expect('j avascript:').not.toBeValidUrl(); - }); - - it('should ignore hex encoded whitespace javascript:', function() { - expect('jav ascript:alert("A");').not.toBeValidUrl(); - expect('jav ascript:alert("B");').not.toBeValidUrl(); - expect('jav ascript:alert("C");').not.toBeValidUrl(); - expect('jav\u0000ascript:alert("D");').not.toBeValidUrl(); - expect('java\u0000\u0000script:alert("D");').not.toBeValidUrl(); - expect('  java\u0000\u0000script:alert("D");').not.toBeValidUrl(); - }); - }); - - }); - -}); diff --git a/test/ngSanitize/directive/ngBindHtmlSpec.js b/test/ngSanitize/directive/ngBindHtmlSpec.js new file mode 100644 index 00000000..be23e5a5 --- /dev/null +++ b/test/ngSanitize/directive/ngBindHtmlSpec.js @@ -0,0 +1,25 @@ +describe('ngBindHtml', function() { + beforeEach(module('ngSanitize')); + + it('should set html', inject(function($rootScope, $compile) { + element = $compile('
')($rootScope); + $rootScope.html = '
hello
'; + $rootScope.$digest(); + expect(angular.lowercase(element.html())).toEqual('
hello
'); + })); + + + it('should reset html when value is null or undefined', inject(function($compile, $rootScope) { + element = $compile('
')($rootScope); + + angular.forEach([null, undefined, ''], function(val) { + $rootScope.html = 'some val'; + $rootScope.$digest(); + expect(angular.lowercase(element.html())).toEqual('some val'); + + $rootScope.html = val; + $rootScope.$digest(); + expect(angular.lowercase(element.html())).toEqual(''); + }); + })); +}); diff --git a/test/ngSanitize/filter/linkySpec.js b/test/ngSanitize/filter/linkySpec.js new file mode 100644 index 00000000..0448159a --- /dev/null +++ b/test/ngSanitize/filter/linkySpec.js @@ -0,0 +1,27 @@ +describe('linky', function() { + var linky; + + beforeEach(module('ngSanitize')); + + beforeEach(inject(function($filter){ + linky = $filter('linky'); + })); + + it('should do basic filter', function() { + expect(linky("http://ab/ (http://a/) http://1.2/v:~-123. c")). + toEqual('http://ab/ ' + + '(http://a/) ' + + '<http://a/> ' + + 'http://1.2/v:~-123. c'); + expect(linky(undefined)).not.toBeDefined(); + }); + + it('should handle mailto:', function() { + expect(linky("mailto:me@example.com")). + toEqual('me@example.com'); + expect(linky("me@example.com")). + toEqual('me@example.com'); + expect(linky("send email to me@example.com, but")). + toEqual('send email to me@example.com, but'); + }); +}); diff --git a/test/ngSanitize/sanitizeSpec.js b/test/ngSanitize/sanitizeSpec.js new file mode 100644 index 00000000..b4fd8a2a --- /dev/null +++ b/test/ngSanitize/sanitizeSpec.js @@ -0,0 +1,286 @@ +'use strict'; + +describe('HTML', function() { + + var expectHTML; + + beforeEach(module('ngSanitize')); + + beforeEach(inject(function($sanitize) { + expectHTML = function(html){ + return expect($sanitize(html)); + }; + })); + + describe('htmlParser', function() { + if (angular.isUndefined(window.htmlParser)) return; + + var handler, start, text; + beforeEach(function() { + handler = { + start: function(tag, attrs, unary){ + start = { + tag: tag, + attrs: attrs, + unary: unary + }; + // Since different browsers handle newlines differenttly we trim + // so that it is easier to write tests. + angular.forEach(attrs, function(value, key) { + attrs[key] = value.replace(/^\s*/, '').replace(/\s*$/, '') + }); + }, + chars: function(text_){ + text = text_; + }, + end:function(tag) { + expect(tag).toEqual(start.tag); + } + }; + }); + + it('should parse basic format', function() { + htmlParser('text', handler); + expect(start).toEqual({tag:'tag', attrs:{attr:'value'}, unary:false}); + expect(text).toEqual('text'); + }); + + it('should parse newlines in tags', function() { + htmlParser('<\ntag\n attr="value"\n>text<\n/\ntag\n>', handler); + expect(start).toEqual({tag:'tag', attrs:{attr:'value'}, unary:false}); + expect(text).toEqual('text'); + }); + + it('should parse newlines in attributes', function() { + htmlParser('text', handler); + expect(start).toEqual({tag:'tag', attrs:{attr:'value'}, unary:false}); + expect(text).toEqual('text'); + }); + + it('should parse namespace', function() { + htmlParser('text', handler); + expect(start).toEqual({tag:'ns:t-a-g', attrs:{'ns:a-t-t-r':'value'}, unary:false}); + expect(text).toEqual('text'); + }); + + it('should parse empty value attribute of node', function() { + htmlParser('', handler); + expect(start).toEqual({tag:'option', attrs:{selected:'', value:''}, unary:false}); + expect(text).toEqual('abc'); + }); + }); + + // THESE TESTS ARE EXECUTED WITH COMPILED ANGULAR + it('should echo html', function() { + expectHTML('helloworld.'). + toEqual('helloworld.'); + }); + + it('should remove script', function() { + expectHTML('ac.').toEqual('ac.'); + }); + + it('should remove double nested script', function() { + expectHTML('ailc.').toEqual('ac.'); + }); + + it('should remove unknown names', function() { + expectHTML('abc').toEqual('abc'); + }); + + it('should remove unsafe value', function() { + expectHTML('').toEqual(''); + }); + + it('should handle self closed elements', function() { + expectHTML('a
c').toEqual('a
c'); + }); + + it('should handle namespace', function() { + expectHTML('abc').toEqual('abc'); + }); + + it('should handle entities', function() { + var everything = '
' + + '!@#$%^&*()_+-={}[]:";\'<>?,./`~ ħ
'; + expectHTML(everything).toEqual(everything); + }); + + it('should handle improper html', function() { + expectHTML('< div rel="
" alt=abc dir=\'"\' >text< /div>'). + toEqual('
text
'); + }); + + it('should handle improper html2', function() { + expectHTML('< div rel="
" / >'). + toEqual('
'); + }); + + it('should ignore back slash as escape', function() { + expectHTML('xxx\\'). + toEqual('xxx\\'); + }); + + it('should ignore object attributes', function() { + expectHTML(':)'). + toEqual(':)'); + expectHTML(':)'). + toEqual(''); + }); + + describe('htmlSanitizerWriter', function() { + if (angular.isUndefined(window.htmlSanitizeWriter)) return; + + var writer, html; + beforeEach(function() { + html = ''; + writer = htmlSanitizeWriter({push:function(text){html+=text;}}); + }); + + it('should write basic HTML', function() { + writer.chars('before'); + writer.start('div', {rel:'123'}, false); + writer.chars('in'); + writer.end('div'); + writer.chars('after'); + + expect(html).toEqual('before
in
after'); + }); + + it('should escape text nodes', function() { + writer.chars('a
&
c'); + expect(html).toEqual('a<div>&</div>c'); + }); + + it('should escape IE script', function() { + writer.chars('&<>{}'); + expect(html).toEqual('&<>{}'); + }); + + it('should escape attributes', function() { + writer.start('div', {rel:'!@#$%^&*()_+-={}[]:";\'<>?,./`~ \n\0\r\u0127'}); + expect(html).toEqual('
'); + }); + + it('should ignore missformed elements', function() { + writer.start('d>i&v', {}); + expect(html).toEqual(''); + }); + + it('should ignore unknown attributes', function() { + writer.start('div', {unknown:""}); + expect(html).toEqual('
'); + }); + + describe('explicitly dissallow', function() { + it('should not allow attributes', function() { + writer.start('div', {id:'a', name:'a', style:'a'}); + expect(html).toEqual('
'); + }); + + it('should not allow tags', function() { + function tag(name) { + writer.start(name, {}); + writer.end(name); + } + tag('frameset'); + tag('frame'); + tag('form'); + tag('param'); + tag('object'); + tag('embed'); + tag('textarea'); + tag('input'); + tag('button'); + tag('option'); + tag('select'); + tag('script'); + tag('style'); + tag('link'); + tag('base'); + tag('basefont'); + expect(html).toEqual(''); + }); + }); + + describe('isUri', function() { + + function isUri(value) { + return value.match(URI_REGEXP); + } + + it('should be URI', function() { + expect(isUri('http://abc')).toBeTruthy(); + expect(isUri('https://abc')).toBeTruthy(); + expect(isUri('ftp://abc')).toBeTruthy(); + expect(isUri('mailto:me@example.com')).toBeTruthy(); + expect(isUri('#anchor')).toBeTruthy(); + }); + + it('should not be UIR', function() { + expect(isUri('')).toBeFalsy(); + expect(isUri('javascript:alert')).toBeFalsy(); + }); + }); + + describe('javascript URL attribute', function() { + beforeEach(function() { + this.addMatchers({ + toBeValidUrl: function() { + return URI_REGEXP.exec(this.actual); + } + }); + }); + + it('should ignore javascript:', function() { + expect('JavaScript:abc').not.toBeValidUrl(); + expect(' \n Java\n Script:abc').not.toBeValidUrl(); + expect('http://JavaScript/my.js').toBeValidUrl(); + }); + + it('should ignore dec encoded javascript:', function() { + expect('javascript:').not.toBeValidUrl(); + expect('javascript:').not.toBeValidUrl(); + expect('j avascript:').not.toBeValidUrl(); + }); + + it('should ignore decimal with leading 0 encodede javascript:', function() { + expect('javascript:').not.toBeValidUrl(); + expect('j avascript:').not.toBeValidUrl(); + expect('j avascript:').not.toBeValidUrl(); + }); + + it('should ignore hex encoded javascript:', function() { + expect('javascript:').not.toBeValidUrl(); + expect('javascript:').not.toBeValidUrl(); + expect('j avascript:').not.toBeValidUrl(); + }); + + it('should ignore hex encoded whitespace javascript:', function() { + expect('jav ascript:alert("A");').not.toBeValidUrl(); + expect('jav ascript:alert("B");').not.toBeValidUrl(); + expect('jav ascript:alert("C");').not.toBeValidUrl(); + expect('jav\u0000ascript:alert("D");').not.toBeValidUrl(); + expect('java\u0000\u0000script:alert("D");').not.toBeValidUrl(); + expect('  java\u0000\u0000script:alert("D");').not.toBeValidUrl(); + }); + }); + + }); +}); diff --git a/test/ngScenario/dslSpec.js b/test/ngScenario/dslSpec.js index 0a8ab762..fee5c3b5 100644 --- a/test/ngScenario/dslSpec.js +++ b/test/ngScenario/dslSpec.js @@ -9,6 +9,8 @@ describe("angular.scenario.dsl", function() { dealoc(element); }); + beforeEach(module('ngSanitize')); + beforeEach(inject(function($injector) { eventLog = []; $window = { -- cgit v1.2.3