2011-07-17 08:05:43 +00:00
'use strict' ;
2010-11-08 22:29:41 +00:00
describe ( 'parser' , function ( ) {
2013-10-07 16:58:37 +00:00
beforeEach ( function ( ) {
// clear caches
getterFnCache = { } ;
promiseWarningCache = { } ;
} ) ;
2010-11-08 22:29:41 +00:00
describe ( 'lexer' , function ( ) {
2013-08-21 00:19:49 +00:00
var lex ;
beforeEach ( function ( ) {
lex = function ( ) {
2013-10-07 16:58:37 +00:00
var lexer = new Lexer ( { csp : false , unwrapPromises : false } ) ;
2013-08-21 00:19:49 +00:00
return lexer . lex . apply ( lexer , arguments ) ;
} ;
} ) ;
2010-11-08 22:29:41 +00:00
it ( 'should tokenize a string' , function ( ) {
2010-10-15 20:44:53 +00:00
var tokens = lex ( "a.bc[22]+1.3|f:'a\\\'c':\"d\\\"e\"" ) ;
var i = 0 ;
2010-11-08 22:29:41 +00:00
expect ( tokens [ i ] . index ) . toEqual ( 0 ) ;
expect ( tokens [ i ] . text ) . toEqual ( 'a.bc' ) ;
2010-10-15 20:44:53 +00:00
i ++ ;
2010-11-08 22:29:41 +00:00
expect ( tokens [ i ] . index ) . toEqual ( 4 ) ;
expect ( tokens [ i ] . text ) . toEqual ( '[' ) ;
2010-10-15 20:44:53 +00:00
i ++ ;
2010-11-08 22:29:41 +00:00
expect ( tokens [ i ] . index ) . toEqual ( 5 ) ;
expect ( tokens [ i ] . text ) . toEqual ( 22 ) ;
2010-10-15 20:44:53 +00:00
i ++ ;
2010-11-08 22:29:41 +00:00
expect ( tokens [ i ] . index ) . toEqual ( 7 ) ;
expect ( tokens [ i ] . text ) . toEqual ( ']' ) ;
2010-10-15 20:44:53 +00:00
i ++ ;
2010-11-08 22:29:41 +00:00
expect ( tokens [ i ] . index ) . toEqual ( 8 ) ;
expect ( tokens [ i ] . text ) . toEqual ( '+' ) ;
2010-10-15 20:44:53 +00:00
i ++ ;
2010-11-08 22:29:41 +00:00
expect ( tokens [ i ] . index ) . toEqual ( 9 ) ;
expect ( tokens [ i ] . text ) . toEqual ( 1.3 ) ;
2010-10-15 20:44:53 +00:00
i ++ ;
2010-11-08 22:29:41 +00:00
expect ( tokens [ i ] . index ) . toEqual ( 12 ) ;
expect ( tokens [ i ] . text ) . toEqual ( '|' ) ;
2010-10-15 20:44:53 +00:00
i ++ ;
2010-11-08 22:29:41 +00:00
expect ( tokens [ i ] . index ) . toEqual ( 13 ) ;
expect ( tokens [ i ] . text ) . toEqual ( 'f' ) ;
2010-10-15 20:44:53 +00:00
i ++ ;
2010-11-08 22:29:41 +00:00
expect ( tokens [ i ] . index ) . toEqual ( 14 ) ;
expect ( tokens [ i ] . text ) . toEqual ( ':' ) ;
2010-10-15 20:44:53 +00:00
i ++ ;
2010-11-08 22:29:41 +00:00
expect ( tokens [ i ] . index ) . toEqual ( 15 ) ;
expect ( tokens [ i ] . string ) . toEqual ( "a'c" ) ;
2010-10-15 20:44:53 +00:00
i ++ ;
2010-11-08 22:29:41 +00:00
expect ( tokens [ i ] . index ) . toEqual ( 21 ) ;
expect ( tokens [ i ] . text ) . toEqual ( ':' ) ;
2010-10-15 20:44:53 +00:00
i ++ ;
2010-11-08 22:29:41 +00:00
expect ( tokens [ i ] . index ) . toEqual ( 22 ) ;
expect ( tokens [ i ] . string ) . toEqual ( 'd"e' ) ;
2010-10-15 20:44:53 +00:00
} ) ;
2010-11-08 22:29:41 +00:00
it ( 'should tokenize undefined' , function ( ) {
2010-10-15 20:44:53 +00:00
var tokens = lex ( "undefined" ) ;
var i = 0 ;
2010-11-08 22:29:41 +00:00
expect ( tokens [ i ] . index ) . toEqual ( 0 ) ;
expect ( tokens [ i ] . text ) . toEqual ( 'undefined' ) ;
expect ( undefined ) . toEqual ( tokens [ i ] . fn ( ) ) ;
2010-10-15 20:44:53 +00:00
} ) ;
2011-01-19 23:42:11 +00:00
2010-11-08 22:29:41 +00:00
it ( 'should tokenize quoted string' , function ( ) {
2010-10-15 20:44:53 +00:00
var str = "['\\'', \"\\\"\"]" ;
var tokens = lex ( str ) ;
2010-11-08 22:29:41 +00:00
expect ( tokens [ 1 ] . index ) . toEqual ( 1 ) ;
expect ( tokens [ 1 ] . string ) . toEqual ( "'" ) ;
2010-10-15 20:44:53 +00:00
2010-11-08 22:29:41 +00:00
expect ( tokens [ 3 ] . index ) . toEqual ( 7 ) ;
expect ( tokens [ 3 ] . string ) . toEqual ( '"' ) ;
2010-10-15 20:44:53 +00:00
} ) ;
2010-11-08 22:29:41 +00:00
it ( 'should tokenize escaped quoted string' , function ( ) {
2010-10-15 20:44:53 +00:00
var str = '"\\"\\n\\f\\r\\t\\v\\u00A0"' ;
var tokens = lex ( str ) ;
2010-11-08 22:29:41 +00:00
expect ( tokens [ 0 ] . string ) . toEqual ( '"\n\f\r\t\v\u00A0' ) ;
2010-10-15 20:44:53 +00:00
} ) ;
2010-11-08 22:29:41 +00:00
it ( 'should tokenize unicode' , function ( ) {
2010-10-15 20:44:53 +00:00
var tokens = lex ( '"\\u00A0"' ) ;
2010-11-08 22:29:41 +00:00
expect ( tokens . length ) . toEqual ( 1 ) ;
expect ( tokens [ 0 ] . string ) . toEqual ( '\u00a0' ) ;
2010-10-15 20:44:53 +00:00
} ) ;
2010-11-08 22:29:41 +00:00
it ( 'should ignore whitespace' , function ( ) {
2010-12-22 01:38:04 +00:00
var tokens = lex ( "a \t \n \r b" ) ;
2010-11-08 22:29:41 +00:00
expect ( tokens [ 0 ] . text ) . toEqual ( 'a' ) ;
expect ( tokens [ 1 ] . text ) . toEqual ( 'b' ) ;
2010-10-15 20:44:53 +00:00
} ) ;
2012-11-27 16:00:46 +00:00
it ( 'should tokenize relation and equality' , function ( ) {
var tokens = lex ( "! == != < > <= >= === !==" ) ;
2010-11-08 22:29:41 +00:00
expect ( tokens [ 0 ] . text ) . toEqual ( '!' ) ;
expect ( tokens [ 1 ] . text ) . toEqual ( '==' ) ;
expect ( tokens [ 2 ] . text ) . toEqual ( '!=' ) ;
expect ( tokens [ 3 ] . text ) . toEqual ( '<' ) ;
expect ( tokens [ 4 ] . text ) . toEqual ( '>' ) ;
expect ( tokens [ 5 ] . text ) . toEqual ( '<=' ) ;
expect ( tokens [ 6 ] . text ) . toEqual ( '>=' ) ;
2012-11-27 16:00:46 +00:00
expect ( tokens [ 7 ] . text ) . toEqual ( '===' ) ;
expect ( tokens [ 8 ] . text ) . toEqual ( '!==' ) ;
2010-10-15 20:44:53 +00:00
} ) ;
2013-06-24 21:14:54 +00:00
2013-04-23 00:42:34 +00:00
it ( 'should tokenize logical and ternary' , function ( ) {
var tokens = lex ( "&& || ? :" ) ;
expect ( tokens [ 0 ] . text ) . toEqual ( '&&' ) ;
expect ( tokens [ 1 ] . text ) . toEqual ( '||' ) ;
expect ( tokens [ 2 ] . text ) . toEqual ( '?' ) ;
expect ( tokens [ 3 ] . text ) . toEqual ( ':' ) ;
} ) ;
2010-10-15 20:44:53 +00:00
2010-11-08 22:29:41 +00:00
it ( 'should tokenize statements' , function ( ) {
2010-10-15 20:44:53 +00:00
var tokens = lex ( "a;b;" ) ;
2010-11-08 22:29:41 +00:00
expect ( tokens [ 0 ] . text ) . toEqual ( 'a' ) ;
expect ( tokens [ 1 ] . text ) . toEqual ( ';' ) ;
expect ( tokens [ 2 ] . text ) . toEqual ( 'b' ) ;
expect ( tokens [ 3 ] . text ) . toEqual ( ';' ) ;
2010-10-15 20:44:53 +00:00
} ) ;
2012-01-24 10:33:35 +00:00
it ( 'should tokenize function invocation' , function ( ) {
2013-10-30 19:14:00 +00:00
var tokens = lex ( "a()" ) ;
2012-01-24 10:33:35 +00:00
expect ( map ( tokens , function ( t ) { return t . text ; } ) ) . toEqual ( [ 'a' , '(' , ')' ] ) ;
} ) ;
it ( 'should tokenize method invocation' , function ( ) {
var tokens = lex ( "a.b.c (d) - e.f()" ) ;
expect ( map ( tokens , function ( t ) { return t . text ; } ) ) .
toEqual ( [ 'a.b' , '.' , 'c' , '(' , 'd' , ')' , '-' , 'e' , '.' , 'f' , '(' , ')' ] ) ;
} ) ;
2010-11-08 22:29:41 +00:00
it ( 'should tokenize number' , function ( ) {
2010-10-15 20:44:53 +00:00
var tokens = lex ( "0.5" ) ;
expect ( tokens [ 0 ] . text ) . toEqual ( 0.5 ) ;
} ) ;
2011-10-17 23:56:56 +00:00
it ( 'should tokenize negative number' , inject ( function ( $rootScope ) {
var value = $rootScope . $eval ( "-0.5" ) ;
2010-10-15 20:44:53 +00:00
expect ( value ) . toEqual ( - 0.5 ) ;
2011-10-17 23:56:56 +00:00
value = $rootScope . $eval ( "{a:-0.5}" ) ;
2010-10-15 20:44:53 +00:00
expect ( value ) . toEqual ( { a : - 0.5 } ) ;
2011-10-17 23:56:56 +00:00
} ) ) ;
2010-10-15 20:44:53 +00:00
2011-10-17 23:56:56 +00:00
it ( 'should tokenize number with exponent' , inject ( function ( $rootScope ) {
2010-10-15 20:44:53 +00:00
var tokens = lex ( "0.5E-10" ) ;
expect ( tokens [ 0 ] . text ) . toEqual ( 0.5 E - 10 ) ;
2011-10-17 23:56:56 +00:00
expect ( $rootScope . $eval ( "0.5E-10" ) ) . toEqual ( 0.5 E - 10 ) ;
2010-10-15 20:44:53 +00:00
tokens = lex ( "0.5E+10" ) ;
expect ( tokens [ 0 ] . text ) . toEqual ( 0.5 E + 10 ) ;
2011-10-17 23:56:56 +00:00
} ) ) ;
2010-10-15 20:44:53 +00:00
2010-12-22 01:38:04 +00:00
it ( 'should throws exception for invalid exponent' , function ( ) {
expect ( function ( ) {
lex ( "0.5E-" ) ;
2013-08-13 22:30:52 +00:00
} ) . toThrowMinErr ( '$parse' , 'lexerr' , 'Lexer Error: Invalid exponent at column 4 in expression [0.5E-].' ) ;
2011-01-19 23:42:11 +00:00
2010-12-22 01:38:04 +00:00
expect ( function ( ) {
lex ( "0.5E-A" ) ;
2013-08-13 22:30:52 +00:00
} ) . toThrowMinErr ( '$parse' , 'lexerr' , 'Lexer Error: Invalid exponent at column 4 in expression [0.5E-A].' ) ;
2010-12-22 01:38:04 +00:00
} ) ;
2010-11-08 22:29:41 +00:00
it ( 'should tokenize number starting with a dot' , function ( ) {
2010-10-15 20:44:53 +00:00
var tokens = lex ( ".5" ) ;
expect ( tokens [ 0 ] . text ) . toEqual ( 0.5 ) ;
} ) ;
2010-10-15 21:06:30 +00:00
2010-11-08 22:29:41 +00:00
it ( 'should throw error on invalid unicode' , function ( ) {
expect ( function ( ) {
2010-12-22 01:38:04 +00:00
lex ( "'\\u1''bla'" ) ;
2013-08-13 22:30:52 +00:00
} ) . toThrowMinErr ( "$parse" , "lexerr" , "Lexer Error: Invalid unicode escape [\\u1''b] at column 2 in expression ['\\u1''bla']." ) ;
2010-10-15 21:06:30 +00:00
} ) ;
2010-10-15 20:44:53 +00:00
} ) ;
2011-01-19 23:42:11 +00:00
2012-04-27 22:20:54 +00:00
var $filterProvider , scope ;
2012-01-12 19:06:10 +00:00
beforeEach ( module ( [ '$filterProvider' , function ( filterProvider ) {
$filterProvider = filterProvider ;
} ] ) ) ;
2010-10-15 20:44:53 +00:00
2012-04-27 22:20:54 +00:00
forEach ( [ true , false ] , function ( cspEnabled ) {
2013-10-30 19:14:00 +00:00
forEach ( [ true , false ] , function ( unwrapPromisesEnabled ) {
2010-10-15 20:44:53 +00:00
2013-10-30 19:14:00 +00:00
describe ( 'csp: ' + cspEnabled + ", unwrapPromises: " + unwrapPromisesEnabled , function ( ) {
2011-01-19 23:42:11 +00:00
2013-10-30 19:14:00 +00:00
beforeEach ( module ( function ( $parseProvider ) {
$parseProvider . unwrapPromises ( unwrapPromisesEnabled ) ;
} ) ) ;
2010-10-15 20:44:53 +00:00
2013-10-30 19:14:00 +00:00
beforeEach ( inject ( function ( $rootScope , $sniffer ) {
scope = $rootScope ;
$sniffer . csp = cspEnabled ;
} ) ) ;
2010-10-15 20:44:53 +00:00
2013-10-30 19:14:00 +00:00
it ( 'should parse expressions' , function ( ) {
expect ( scope . $eval ( "-1" ) ) . toEqual ( - 1 ) ;
expect ( scope . $eval ( "1 + 2.5" ) ) . toEqual ( 3.5 ) ;
expect ( scope . $eval ( "1 + -2.5" ) ) . toEqual ( - 1.5 ) ;
expect ( scope . $eval ( "1+2*3/4" ) ) . toEqual ( 1 + 2 * 3 / 4 ) ;
expect ( scope . $eval ( "0--1+1.5" ) ) . toEqual ( 0 - - 1 + 1.5 ) ;
expect ( scope . $eval ( "-0--1++2*-3/-4" ) ) . toEqual ( - 0 - - 1 + + 2 * - 3 / - 4 ) ;
expect ( scope . $eval ( "1/2*3" ) ) . toEqual ( 1 / 2 * 3 ) ;
} ) ;
2012-03-08 01:07:25 +00:00
2013-10-30 19:14:00 +00:00
it ( 'should parse comparison' , function ( ) {
expect ( scope . $eval ( "false" ) ) . toBeFalsy ( ) ;
expect ( scope . $eval ( "!true" ) ) . toBeFalsy ( ) ;
expect ( scope . $eval ( "1==1" ) ) . toBeTruthy ( ) ;
expect ( scope . $eval ( "1==true" ) ) . toBeTruthy ( ) ;
expect ( scope . $eval ( "1===1" ) ) . toBeTruthy ( ) ;
expect ( scope . $eval ( "1==='1'" ) ) . toBeFalsy ( ) ;
expect ( scope . $eval ( "1===true" ) ) . toBeFalsy ( ) ;
expect ( scope . $eval ( "'true'===true" ) ) . toBeFalsy ( ) ;
expect ( scope . $eval ( "1!==2" ) ) . toBeTruthy ( ) ;
expect ( scope . $eval ( "1!=='1'" ) ) . toBeTruthy ( ) ;
expect ( scope . $eval ( "1!=2" ) ) . toBeTruthy ( ) ;
expect ( scope . $eval ( "1<2" ) ) . toBeTruthy ( ) ;
expect ( scope . $eval ( "1<=1" ) ) . toBeTruthy ( ) ;
expect ( scope . $eval ( "1>2" ) ) . toEqual ( 1 > 2 ) ;
expect ( scope . $eval ( "2>=1" ) ) . toEqual ( 2 >= 1 ) ;
expect ( scope . $eval ( "true==2<3" ) ) . toEqual ( true == 2 < 3 ) ;
expect ( scope . $eval ( "true===2<3" ) ) . toEqual ( true === 2 < 3 ) ;
} ) ;
2013-06-24 21:14:54 +00:00
2013-10-30 19:14:00 +00:00
it ( 'should parse logical' , function ( ) {
expect ( scope . $eval ( "0&&2" ) ) . toEqual ( 0 && 2 ) ;
expect ( scope . $eval ( "0||2" ) ) . toEqual ( 0 || 2 ) ;
expect ( scope . $eval ( "0||1&&2" ) ) . toEqual ( 0 || 1 && 2 ) ;
} ) ;
2012-03-08 01:07:25 +00:00
2013-10-30 19:14:00 +00:00
it ( 'should parse ternary' , function ( ) {
var returnTrue = scope . returnTrue = function ( ) { return true ; } ;
var returnFalse = scope . returnFalse = function ( ) { return false ; } ;
var returnString = scope . returnString = function ( ) { return 'asd' ; } ;
var returnInt = scope . returnInt = function ( ) { return 123 ; } ;
var identity = scope . identity = function ( x ) { return x ; } ;
// Simple.
expect ( scope . $eval ( '0?0:2' ) ) . toEqual ( 0 ? 0 : 2 ) ;
expect ( scope . $eval ( '1?0:2' ) ) . toEqual ( 1 ? 0 : 2 ) ;
// Nested on the left.
expect ( scope . $eval ( '0?0?0:0:2' ) ) . toEqual ( 0 ? 0 ? 0 : 0 : 2 ) ;
expect ( scope . $eval ( '1?0?0:0:2' ) ) . toEqual ( 1 ? 0 ? 0 : 0 : 2 ) ;
expect ( scope . $eval ( '0?1?0:0:2' ) ) . toEqual ( 0 ? 1 ? 0 : 0 : 2 ) ;
expect ( scope . $eval ( '0?0?1:0:2' ) ) . toEqual ( 0 ? 0 ? 1 : 0 : 2 ) ;
expect ( scope . $eval ( '0?0?0:2:3' ) ) . toEqual ( 0 ? 0 ? 0 : 2 : 3 ) ;
expect ( scope . $eval ( '1?1?0:0:2' ) ) . toEqual ( 1 ? 1 ? 0 : 0 : 2 ) ;
expect ( scope . $eval ( '1?1?1:0:2' ) ) . toEqual ( 1 ? 1 ? 1 : 0 : 2 ) ;
expect ( scope . $eval ( '1?1?1:2:3' ) ) . toEqual ( 1 ? 1 ? 1 : 2 : 3 ) ;
expect ( scope . $eval ( '1?1?1:2:3' ) ) . toEqual ( 1 ? 1 ? 1 : 2 : 3 ) ;
// Nested on the right.
expect ( scope . $eval ( '0?0:0?0:2' ) ) . toEqual ( 0 ? 0 : 0 ? 0 : 2 ) ;
expect ( scope . $eval ( '1?0:0?0:2' ) ) . toEqual ( 1 ? 0 : 0 ? 0 : 2 ) ;
expect ( scope . $eval ( '0?1:0?0:2' ) ) . toEqual ( 0 ? 1 : 0 ? 0 : 2 ) ;
expect ( scope . $eval ( '0?0:1?0:2' ) ) . toEqual ( 0 ? 0 : 1 ? 0 : 2 ) ;
expect ( scope . $eval ( '0?0:0?2:3' ) ) . toEqual ( 0 ? 0 : 0 ? 2 : 3 ) ;
expect ( scope . $eval ( '1?1:0?0:2' ) ) . toEqual ( 1 ? 1 : 0 ? 0 : 2 ) ;
expect ( scope . $eval ( '1?1:1?0:2' ) ) . toEqual ( 1 ? 1 : 1 ? 0 : 2 ) ;
expect ( scope . $eval ( '1?1:1?2:3' ) ) . toEqual ( 1 ? 1 : 1 ? 2 : 3 ) ;
expect ( scope . $eval ( '1?1:1?2:3' ) ) . toEqual ( 1 ? 1 : 1 ? 2 : 3 ) ;
// Precedence with respect to logical operators.
expect ( scope . $eval ( '0&&1?0:1' ) ) . toEqual ( 0 && 1 ? 0 : 1 ) ;
expect ( scope . $eval ( '1||0?0:0' ) ) . toEqual ( 1 || 0 ? 0 : 0 ) ;
expect ( scope . $eval ( '0?0&&1:2' ) ) . toEqual ( 0 ? 0 && 1 : 2 ) ;
expect ( scope . $eval ( '0?1&&1:2' ) ) . toEqual ( 0 ? 1 && 1 : 2 ) ;
expect ( scope . $eval ( '0?0||0:1' ) ) . toEqual ( 0 ? 0 || 0 : 1 ) ;
expect ( scope . $eval ( '0?0||1:2' ) ) . toEqual ( 0 ? 0 || 1 : 2 ) ;
expect ( scope . $eval ( '1?0&&1:2' ) ) . toEqual ( 1 ? 0 && 1 : 2 ) ;
expect ( scope . $eval ( '1?1&&1:2' ) ) . toEqual ( 1 ? 1 && 1 : 2 ) ;
expect ( scope . $eval ( '1?0||0:1' ) ) . toEqual ( 1 ? 0 || 0 : 1 ) ;
expect ( scope . $eval ( '1?0||1:2' ) ) . toEqual ( 1 ? 0 || 1 : 2 ) ;
expect ( scope . $eval ( '0?1:0&&1' ) ) . toEqual ( 0 ? 1 : 0 && 1 ) ;
expect ( scope . $eval ( '0?2:1&&1' ) ) . toEqual ( 0 ? 2 : 1 && 1 ) ;
expect ( scope . $eval ( '0?1:0||0' ) ) . toEqual ( 0 ? 1 : 0 || 0 ) ;
expect ( scope . $eval ( '0?2:0||1' ) ) . toEqual ( 0 ? 2 : 0 || 1 ) ;
expect ( scope . $eval ( '1?1:0&&1' ) ) . toEqual ( 1 ? 1 : 0 && 1 ) ;
expect ( scope . $eval ( '1?2:1&&1' ) ) . toEqual ( 1 ? 2 : 1 && 1 ) ;
expect ( scope . $eval ( '1?1:0||0' ) ) . toEqual ( 1 ? 1 : 0 || 0 ) ;
expect ( scope . $eval ( '1?2:0||1' ) ) . toEqual ( 1 ? 2 : 0 || 1 ) ;
// Function calls.
expect ( scope . $eval ( 'returnTrue() ? returnString() : returnInt()' ) ) . toEqual ( returnTrue ( ) ? returnString ( ) : returnInt ( ) ) ;
expect ( scope . $eval ( 'returnFalse() ? returnString() : returnInt()' ) ) . toEqual ( returnFalse ( ) ? returnString ( ) : returnInt ( ) ) ;
expect ( scope . $eval ( 'returnTrue() ? returnString() : returnInt()' ) ) . toEqual ( returnTrue ( ) ? returnString ( ) : returnInt ( ) ) ;
expect ( scope . $eval ( 'identity(returnFalse() ? returnString() : returnInt())' ) ) . toEqual ( identity ( returnFalse ( ) ? returnString ( ) : returnInt ( ) ) ) ;
} ) ;
2010-10-15 20:44:53 +00:00
2013-10-30 19:14:00 +00:00
it ( 'should parse string' , function ( ) {
expect ( scope . $eval ( "'a' + 'b c'" ) ) . toEqual ( "ab c" ) ;
} ) ;
2010-10-15 20:44:53 +00:00
2013-10-30 19:14:00 +00:00
it ( 'should parse filters' , function ( ) {
$filterProvider . register ( 'substring' , valueFn ( function ( input , start , end ) {
return input . substring ( start , end ) ;
} ) ) ;
2010-10-15 20:44:53 +00:00
2013-10-30 19:14:00 +00:00
expect ( function ( ) {
scope . $eval ( "1|nonexistent" ) ;
} ) . toThrowMinErr ( '$injector' , 'unpr' , 'Unknown provider: nonexistentFilterProvider <- nonexistentFilter' ) ;
2010-10-15 20:44:53 +00:00
2013-10-30 19:14:00 +00:00
scope . offset = 3 ;
expect ( scope . $eval ( "'abcd'|substring:1:offset" ) ) . toEqual ( "bc" ) ;
expect ( scope . $eval ( "'abcd'|substring:1:3|uppercase" ) ) . toEqual ( "BC" ) ;
} ) ;
2010-10-15 20:44:53 +00:00
2013-10-30 19:14:00 +00:00
it ( 'should access scope' , function ( ) {
scope . a = 123 ;
scope . b = { c : 456 } ;
expect ( scope . $eval ( "a" , scope ) ) . toEqual ( 123 ) ;
expect ( scope . $eval ( "b.c" , scope ) ) . toEqual ( 456 ) ;
expect ( scope . $eval ( "x.y.z" , scope ) ) . not . toBeDefined ( ) ;
} ) ;
2010-10-15 20:44:53 +00:00
2013-10-30 19:14:00 +00:00
it ( 'should resolve deeply nested paths (important for CSP mode)' , function ( ) {
scope . a = { b : { c : { d : { e : { f : { g : { h : { i : { j : { k : { l : { m : { n : 'nooo!' } } } } } } } } } } } } } ;
expect ( scope . $eval ( "a.b.c.d.e.f.g.h.i.j.k.l.m.n" , scope ) ) . toBe ( 'nooo!' ) ;
} ) ;
2012-01-24 10:33:35 +00:00
2013-10-30 19:14:00 +00:00
it ( 'should be forgiving' , function ( ) {
scope . a = { b : 23 } ;
expect ( scope . $eval ( 'b' ) ) . toBeUndefined ( ) ;
expect ( scope . $eval ( 'a.x' ) ) . toBeUndefined ( ) ;
expect ( scope . $eval ( 'a.b.c.d' ) ) . toBeUndefined ( ) ;
} ) ;
2010-10-15 20:44:53 +00:00
2013-10-30 19:14:00 +00:00
it ( 'should support property names that collide with native object properties' , function ( ) {
// regression
scope . watch = 1 ;
scope . toString = function toString ( ) {
return "custom toString" ;
} ;
2010-10-15 20:44:53 +00:00
2013-10-30 19:14:00 +00:00
expect ( scope . $eval ( 'watch' , scope ) ) . toBe ( 1 ) ;
expect ( scope . $eval ( 'toString()' , scope ) ) . toBe ( 'custom toString' ) ;
} ) ;
2013-10-05 09:49:09 +00:00
2013-10-30 19:14:00 +00:00
it ( 'should not break if hasOwnProperty is referenced in an expression' , function ( ) {
scope . obj = { value : 1 } ;
// By evaluating an expression that calls hasOwnProperty, the getterFnCache
// will store a property called hasOwnProperty. This is effectively:
// getterFnCache['hasOwnProperty'] = null
scope . $eval ( 'obj.hasOwnProperty("value")' ) ;
// If we rely on this property then evaluating any expression will fail
// because it is not able to find out if obj.value is there in the cache
expect ( scope . $eval ( 'obj.value' ) ) . toBe ( 1 ) ;
} ) ;
2013-10-05 09:49:09 +00:00
2013-10-30 19:14:00 +00:00
it ( 'should not break if the expression is "hasOwnProperty"' , function ( ) {
scope . fooExp = 'barVal' ;
// By evaluating hasOwnProperty, the $parse cache will store a getter for
// the scope's own hasOwnProperty function, which will mess up future cache look ups.
// i.e. cache['hasOwnProperty'] = function(scope) { return scope.hasOwnProperty; }
scope . $eval ( 'hasOwnProperty' ) ;
expect ( scope . $eval ( 'fooExp' ) ) . toBe ( 'barVal' ) ;
} ) ;
2010-10-15 20:44:53 +00:00
2013-10-30 19:14:00 +00:00
it ( 'should evaluate grouped expressions' , function ( ) {
expect ( scope . $eval ( "(1+2)*3" ) ) . toEqual ( ( 1 + 2 ) * 3 ) ;
} ) ;
2010-10-15 20:44:53 +00:00
2013-10-30 19:14:00 +00:00
it ( 'should evaluate assignments' , function ( ) {
expect ( scope . $eval ( "a=12" ) ) . toEqual ( 12 ) ;
expect ( scope . a ) . toEqual ( 12 ) ;
2010-10-15 20:44:53 +00:00
2013-10-30 19:14:00 +00:00
expect ( scope . $eval ( "x.y.z=123;" ) ) . toEqual ( 123 ) ;
expect ( scope . x . y . z ) . toEqual ( 123 ) ;
2010-10-15 20:44:53 +00:00
2013-10-30 19:14:00 +00:00
expect ( scope . $eval ( "a=123; b=234" ) ) . toEqual ( 234 ) ;
expect ( scope . a ) . toEqual ( 123 ) ;
expect ( scope . b ) . toEqual ( 234 ) ;
} ) ;
2010-10-15 20:44:53 +00:00
2013-10-30 19:14:00 +00:00
it ( 'should evaluate function call without arguments' , function ( ) {
scope [ 'const' ] = function ( a , b ) { return 123 ; } ;
expect ( scope . $eval ( "const()" ) ) . toEqual ( 123 ) ;
} ) ;
2011-01-19 23:42:11 +00:00
2013-10-30 19:14:00 +00:00
it ( 'should evaluate function call with arguments' , function ( ) {
scope . add = function ( a , b ) {
return a + b ;
} ;
expect ( scope . $eval ( "add(1,2)" ) ) . toEqual ( 3 ) ;
} ) ;
2010-10-15 20:44:53 +00:00
2013-10-30 19:14:00 +00:00
it ( 'should evaluate function call from a return value' , function ( ) {
scope . val = 33 ;
scope . getter = function ( ) { return function ( ) { return this . val ; } } ;
expect ( scope . $eval ( "getter()()" ) ) . toBe ( 33 ) ;
} ) ;
2010-10-15 20:44:53 +00:00
2013-10-30 19:14:00 +00:00
it ( 'should evaluate multiplication and division' , function ( ) {
scope . taxRate = 8 ;
scope . subTotal = 100 ;
expect ( scope . $eval ( "taxRate / 100 * subTotal" ) ) . toEqual ( 8 ) ;
expect ( scope . $eval ( "subTotal * taxRate / 100" ) ) . toEqual ( 8 ) ;
} ) ;
2010-10-15 20:44:53 +00:00
2013-10-30 19:14:00 +00:00
it ( 'should evaluate array' , function ( ) {
expect ( scope . $eval ( "[]" ) . length ) . toEqual ( 0 ) ;
expect ( scope . $eval ( "[1, 2]" ) . length ) . toEqual ( 2 ) ;
expect ( scope . $eval ( "[1, 2]" ) [ 0 ] ) . toEqual ( 1 ) ;
expect ( scope . $eval ( "[1, 2]" ) [ 1 ] ) . toEqual ( 2 ) ;
} ) ;
2010-10-15 20:44:53 +00:00
2013-10-30 19:14:00 +00:00
it ( 'should evaluate array access' , function ( ) {
expect ( scope . $eval ( "[1][0]" ) ) . toEqual ( 1 ) ;
expect ( scope . $eval ( "[[1]][0][0]" ) ) . toEqual ( 1 ) ;
expect ( scope . $eval ( "[].length" ) ) . toEqual ( 0 ) ;
expect ( scope . $eval ( "[1, 2].length" ) ) . toEqual ( 2 ) ;
} ) ;
2010-10-15 20:44:53 +00:00
2013-10-30 19:14:00 +00:00
it ( 'should evaluate object' , function ( ) {
expect ( toJson ( scope . $eval ( "{}" ) ) ) . toEqual ( "{}" ) ;
expect ( toJson ( scope . $eval ( "{a:'b'}" ) ) ) . toEqual ( '{"a":"b"}' ) ;
expect ( toJson ( scope . $eval ( "{'a':'b'}" ) ) ) . toEqual ( '{"a":"b"}' ) ;
expect ( toJson ( scope . $eval ( "{\"a\":'b'}" ) ) ) . toEqual ( '{"a":"b"}' ) ;
} ) ;
2010-10-15 20:44:53 +00:00
2013-10-30 19:14:00 +00:00
it ( 'should evaluate object access' , function ( ) {
expect ( scope . $eval ( "{false:'WC', true:'CC'}[false]" ) ) . toEqual ( "WC" ) ;
} ) ;
2010-10-15 20:44:53 +00:00
2013-10-30 19:14:00 +00:00
it ( 'should evaluate JSON' , function ( ) {
expect ( toJson ( scope . $eval ( "[{}]" ) ) ) . toEqual ( "[{}]" ) ;
expect ( toJson ( scope . $eval ( "[{a:[]}, {b:1}]" ) ) ) . toEqual ( '[{"a":[]},{"b":1}]' ) ;
} ) ;
2010-10-15 20:44:53 +00:00
2013-10-30 19:14:00 +00:00
it ( 'should evaluate multiple statements' , function ( ) {
expect ( scope . $eval ( "a=1;b=3;a+b" ) ) . toEqual ( 4 ) ;
expect ( scope . $eval ( ";;1;;" ) ) . toEqual ( 1 ) ;
} ) ;
2010-10-15 20:44:53 +00:00
2013-10-30 19:14:00 +00:00
it ( 'should evaluate object methods in correct context (this)' , function ( ) {
var C = function ( ) {
this . a = 123 ;
} ;
C . prototype . getA = function ( ) {
return this . a ;
} ;
2010-10-15 20:44:53 +00:00
2013-10-30 19:14:00 +00:00
scope . obj = new C ( ) ;
expect ( scope . $eval ( "obj.getA()" ) ) . toEqual ( 123 ) ;
expect ( scope . $eval ( "obj['getA']()" ) ) . toEqual ( 123 ) ;
} ) ;
2010-10-15 20:44:53 +00:00
2013-10-30 19:14:00 +00:00
it ( 'should evaluate methods in correct context (this) in argument' , function ( ) {
var C = function ( ) {
this . a = 123 ;
} ;
C . prototype . sum = function ( value ) {
return this . a + value ;
} ;
C . prototype . getA = function ( ) {
return this . a ;
} ;
2010-10-15 20:44:53 +00:00
2013-10-30 19:14:00 +00:00
scope . obj = new C ( ) ;
expect ( scope . $eval ( "obj.sum(obj.getA())" ) ) . toEqual ( 246 ) ;
expect ( scope . $eval ( "obj['sum'](obj.getA())" ) ) . toEqual ( 246 ) ;
} ) ;
2010-10-15 20:44:53 +00:00
2013-10-30 19:14:00 +00:00
it ( 'should evaluate objects on scope context' , function ( ) {
scope . a = "abc" ;
expect ( scope . $eval ( "{a:a}" ) . a ) . toEqual ( "abc" ) ;
} ) ;
2010-10-15 20:44:53 +00:00
2013-10-30 19:14:00 +00:00
it ( 'should evaluate field access on function call result' , function ( ) {
scope . a = function ( ) {
return { name : 'misko' } ;
} ;
expect ( scope . $eval ( "a().name" ) ) . toEqual ( "misko" ) ;
} ) ;
2011-01-19 23:42:11 +00:00
2013-10-30 19:14:00 +00:00
it ( 'should evaluate field access after array access' , function ( ) {
scope . items = [ { } , { name : 'misko' } ] ;
expect ( scope . $eval ( 'items[1].name' ) ) . toEqual ( "misko" ) ;
} ) ;
2011-01-19 23:42:11 +00:00
2013-10-30 19:14:00 +00:00
it ( 'should evaluate array assignment' , function ( ) {
scope . items = [ ] ;
2011-09-30 23:55:01 +00:00
2013-10-30 19:14:00 +00:00
expect ( scope . $eval ( 'items[1] = "abc"' ) ) . toEqual ( "abc" ) ;
expect ( scope . $eval ( 'items[1]' ) ) . toEqual ( "abc" ) ;
// Dont know how to make this work....
// expect(scope.$eval('books[1] = "moby"')).toEqual("moby");
// expect(scope.$eval('books[1]')).toEqual("moby");
} ) ;
2011-09-30 23:55:01 +00:00
2013-10-30 19:14:00 +00:00
it ( 'should evaluate grouped filters' , function ( ) {
scope . name = 'MISKO' ;
expect ( scope . $eval ( 'n = (name|lowercase)' ) ) . toEqual ( 'misko' ) ;
expect ( scope . $eval ( 'n' ) ) . toEqual ( 'misko' ) ;
} ) ;
2011-01-19 23:42:11 +00:00
2013-10-30 19:14:00 +00:00
it ( 'should evaluate remainder' , function ( ) {
expect ( scope . $eval ( '1%2' ) ) . toEqual ( 1 ) ;
} ) ;
2011-11-23 23:53:06 +00:00
2013-10-30 19:14:00 +00:00
it ( 'should evaluate sum with undefined' , function ( ) {
expect ( scope . $eval ( '1+undefined' ) ) . toEqual ( 1 ) ;
expect ( scope . $eval ( 'undefined+1' ) ) . toEqual ( 1 ) ;
} ) ;
2011-11-23 23:53:06 +00:00
2013-10-30 19:14:00 +00:00
it ( 'should throw exception on non-closed bracket' , function ( ) {
expect ( function ( ) {
scope . $eval ( '[].count(' ) ;
} ) . toThrowMinErr ( '$parse' , 'ueoe' , 'Unexpected end of expression: [].count(' ) ;
} ) ;
2011-11-23 23:53:06 +00:00
2013-10-30 19:14:00 +00:00
it ( 'should evaluate double negation' , function ( ) {
expect ( scope . $eval ( 'true' ) ) . toBeTruthy ( ) ;
expect ( scope . $eval ( '!true' ) ) . toBeFalsy ( ) ;
expect ( scope . $eval ( '!!true' ) ) . toBeTruthy ( ) ;
expect ( scope . $eval ( '{true:"a", false:"b"}[!!true]' ) ) . toEqual ( 'a' ) ;
} ) ;
2011-11-23 23:53:06 +00:00
2013-10-30 19:14:00 +00:00
it ( 'should evaluate negation' , function ( ) {
expect ( scope . $eval ( "!false || true" ) ) . toEqual ( ! false || true ) ;
expect ( scope . $eval ( "!11 == 10" ) ) . toEqual ( ! 11 == 10 ) ;
expect ( scope . $eval ( "12/6/2" ) ) . toEqual ( 12 / 6 / 2 ) ;
} ) ;
2011-11-23 23:53:06 +00:00
2013-10-30 19:14:00 +00:00
it ( 'should evaluate exclamation mark' , function ( ) {
expect ( scope . $eval ( 'suffix = "!"' ) ) . toEqual ( '!' ) ;
} ) ;
2011-11-23 23:53:06 +00:00
2013-10-30 19:14:00 +00:00
it ( 'should evaluate minus' , function ( ) {
expect ( scope . $eval ( "{a:'-'}" ) ) . toEqual ( { a : "-" } ) ;
} ) ;
2011-11-23 23:53:06 +00:00
2013-10-30 19:14:00 +00:00
it ( 'should evaluate undefined' , function ( ) {
expect ( scope . $eval ( "undefined" ) ) . not . toBeDefined ( ) ;
expect ( scope . $eval ( "a=undefined" ) ) . not . toBeDefined ( ) ;
expect ( scope . a ) . not . toBeDefined ( ) ;
} ) ;
2011-11-23 23:53:06 +00:00
2013-10-30 19:14:00 +00:00
it ( 'should allow assignment after array dereference' , function ( ) {
scope . obj = [ { } ] ;
scope . $eval ( 'obj[0].name=1' ) ;
expect ( scope . obj . name ) . toBeUndefined ( ) ;
expect ( scope . obj [ 0 ] . name ) . toEqual ( 1 ) ;
} ) ;
2011-11-23 23:53:06 +00:00
2013-10-30 19:14:00 +00:00
it ( 'should short-circuit AND operator' , function ( ) {
scope . run = function ( ) {
throw "IT SHOULD NOT HAVE RUN" ;
} ;
expect ( scope . $eval ( 'false && run()' ) ) . toBe ( false ) ;
} ) ;
2011-11-23 23:53:06 +00:00
2013-10-30 19:14:00 +00:00
it ( 'should short-circuit OR operator' , function ( ) {
scope . run = function ( ) {
throw "IT SHOULD NOT HAVE RUN" ;
} ;
expect ( scope . $eval ( 'true || run()' ) ) . toBe ( true ) ;
} ) ;
2011-11-23 23:53:06 +00:00
2013-08-09 21:47:13 +00:00
2013-10-30 19:14:00 +00:00
it ( 'should support method calls on primitive types' , function ( ) {
scope . empty = '' ;
scope . zero = 0 ;
scope . bool = false ;
2013-08-09 21:47:13 +00:00
2013-10-30 19:14:00 +00:00
expect ( scope . $eval ( 'empty.substr(0)' ) ) . toBe ( '' ) ;
expect ( scope . $eval ( 'zero.toString()' ) ) . toBe ( '0' ) ;
expect ( scope . $eval ( 'bool.toString()' ) ) . toBe ( 'false' ) ;
} ) ;
2013-08-09 21:47:13 +00:00
2013-10-30 19:14:00 +00:00
it ( 'should evaluate expressions with line terminators' , function ( ) {
scope . a = "a" ;
scope . b = { c : "bc" } ;
expect ( scope . $eval ( 'a + \n b.c + \r "\td" + \t \r\n\r "\r\n\n"' ) ) . toEqual ( "abc\td\r\n\n" ) ;
} ) ;
2013-08-09 21:47:13 +00:00
2013-10-30 19:14:00 +00:00
describe ( 'sandboxing' , function ( ) {
describe ( 'Function constructor' , function ( ) {
it ( 'should NOT allow access to Function constructor in getter' , function ( ) {
expect ( function ( ) {
scope . $eval ( '{}.toString.constructor' ) ;
} ) . toThrowMinErr (
'$parse' , 'isecfld' , 'Referencing "constructor" field in Angular expressions is disallowed! ' +
'Expression: {}.toString.constructor' ) ;
expect ( function ( ) {
scope . $eval ( '{}.toString.constructor("alert(1)")' ) ;
} ) . toThrowMinErr (
'$parse' , 'isecfld' , 'Referencing "constructor" field in Angular expressions is disallowed! ' +
'Expression: {}.toString.constructor("alert(1)")' ) ;
expect ( function ( ) {
scope . $eval ( '[].toString.constructor.foo' ) ;
} ) . toThrowMinErr (
'$parse' , 'isecfld' , 'Referencing "constructor" field in Angular expressions is disallowed! ' +
'Expression: [].toString.constructor.foo' ) ;
expect ( function ( ) {
scope . $eval ( '{}.toString["constructor"]' ) ;
} ) . toThrowMinErr (
'$parse' , 'isecfn' , 'Referencing Function in Angular expressions is disallowed! ' +
'Expression: {}.toString["constructor"]' ) ;
expect ( function ( ) {
scope . $eval ( '{}["toString"]["constructor"]' ) ;
} ) . toThrowMinErr (
'$parse' , 'isecfn' , 'Referencing Function in Angular expressions is disallowed! ' +
'Expression: {}["toString"]["constructor"]' ) ;
scope . a = [ ] ;
expect ( function ( ) {
scope . $eval ( 'a.toString.constructor' , scope ) ;
} ) . toThrowMinErr (
'$parse' , 'isecfld' , 'Referencing "constructor" field in Angular expressions is disallowed! ' +
'Expression: a.toString.constructor' ) ;
expect ( function ( ) {
scope . $eval ( 'a.toString["constructor"]' , scope ) ;
} ) . toThrowMinErr (
'$parse' , 'isecfn' , 'Referencing Function in Angular expressions is disallowed! ' +
'Expression: a.toString["constructor"]' ) ;
} ) ;
it ( 'should NOT allow access to Function constructor in setter' , function ( ) {
expect ( function ( ) {
scope . $eval ( '{}.toString.constructor = 1' ) ;
} ) . toThrowMinErr (
'$parse' , 'isecfld' , 'Referencing "constructor" field in Angular expressions is disallowed! ' +
'Expression: {}.toString.constructor = 1' ) ;
expect ( function ( ) {
scope . $eval ( '{}.toString.constructor.a = 1' ) ;
} ) . toThrowMinErr (
'$parse' , 'isecfld' , 'Referencing "constructor" field in Angular expressions is disallowed! ' +
'Expression: {}.toString.constructor.a = 1' ) ;
expect ( function ( ) {
scope . $eval ( '{}.toString["constructor"]["constructor"] = 1' ) ;
} ) . toThrowMinErr (
'$parse' , 'isecfn' , 'Referencing Function in Angular expressions is disallowed! ' +
'Expression: {}.toString["constructor"]["constructor"] = 1' ) ;
scope . key1 = "const" ;
scope . key2 = "ructor" ;
expect ( function ( ) {
scope . $eval ( '{}.toString[key1 + key2].foo = 1' ) ;
} ) . toThrowMinErr (
'$parse' , 'isecfn' , 'Referencing Function in Angular expressions is disallowed! ' +
'Expression: {}.toString[key1 + key2].foo = 1' ) ;
expect ( function ( ) {
scope . $eval ( '{}.toString["constructor"]["a"] = 1' ) ;
} ) . toThrowMinErr (
'$parse' , 'isecfn' , 'Referencing Function in Angular expressions is disallowed! ' +
'Expression: {}.toString["constructor"]["a"] = 1' ) ;
scope . a = [ ] ;
expect ( function ( ) {
scope . $eval ( 'a.toString.constructor = 1' , scope ) ;
} ) . toThrowMinErr (
'$parse' , 'isecfld' , 'Referencing "constructor" field in Angular expressions is disallowed! ' +
'Expression: a.toString.constructor = 1' ) ;
} ) ;
it ( 'should NOT allow access to Function constructor that has been aliased' , function ( ) {
scope . foo = { "bar" : Function } ;
expect ( function ( ) {
scope . $eval ( 'foo["bar"]' ) ;
} ) . toThrowMinErr (
'$parse' , 'isecfn' , 'Referencing Function in Angular expressions is disallowed! ' +
'Expression: foo["bar"]' ) ;
} ) ;
it ( 'should NOT allow access to Function constructor in getter' , function ( ) {
expect ( function ( ) {
scope . $eval ( '{}.toString.constructor' ) ;
} ) . toThrowMinErr (
'$parse' , 'isecfld' , 'Referencing "constructor" field in Angular expressions is disallowed! ' +
'Expression: {}.toString.constructor' ) ;
} ) ;
2013-08-09 21:47:13 +00:00
} ) ;
2013-10-30 19:14:00 +00:00
describe ( 'Window and $element/node' , function ( ) {
it ( 'should NOT allow access to the Window or DOM when indexing' , inject ( function ( $window , $document ) {
scope . wrap = { w : $window , d : $document } ;
expect ( function ( ) {
scope . $eval ( 'wrap["w"]' , scope ) ;
} ) . toThrowMinErr (
'$parse' , 'isecwindow' , 'Referencing the Window in Angular expressions is ' +
'disallowed! Expression: wrap["w"]' ) ;
expect ( function ( ) {
scope . $eval ( 'wrap["d"]' , scope ) ;
} ) . toThrowMinErr (
'$parse' , 'isecdom' , 'Referencing DOM nodes in Angular expressions is ' +
'disallowed! Expression: wrap["d"]' ) ;
} ) ) ;
it ( 'should NOT allow access to the Window or DOM returned from a function' , inject ( function ( $window , $document ) {
scope . getWin = valueFn ( $window ) ;
scope . getDoc = valueFn ( $document ) ;
expect ( function ( ) {
scope . $eval ( 'getWin()' , scope ) ;
} ) . toThrowMinErr (
'$parse' , 'isecwindow' , 'Referencing the Window in Angular expressions is ' +
'disallowed! Expression: getWin()' ) ;
expect ( function ( ) {
scope . $eval ( 'getDoc()' , scope ) ;
} ) . toThrowMinErr (
'$parse' , 'isecdom' , 'Referencing DOM nodes in Angular expressions is ' +
'disallowed! Expression: getDoc()' ) ;
} ) ) ;
it ( 'should NOT allow calling functions on Window or DOM' , inject ( function ( $window , $document ) {
scope . a = { b : { win : $window , doc : $document } } ;
expect ( function ( ) {
scope . $eval ( 'a.b.win.alert(1)' , scope ) ;
} ) . toThrowMinErr (
'$parse' , 'isecwindow' , 'Referencing the Window in Angular expressions is ' +
'disallowed! Expression: a.b.win.alert(1)' ) ;
expect ( function ( ) {
scope . $eval ( 'a.b.doc.on("click")' , scope ) ;
} ) . toThrowMinErr (
'$parse' , 'isecdom' , 'Referencing DOM nodes in Angular expressions is ' +
'disallowed! Expression: a.b.doc.on("click")' ) ;
} ) ) ;
} ) ;
} ) ;
2013-08-09 21:47:13 +00:00
2013-10-30 19:14:00 +00:00
describe ( 'overriding constructor' , function ( ) {
it ( 'should evaluate grouped expressions' , function ( ) {
scope . foo = function foo ( ) {
return "foo" ;
} ;
// When not overridden, access should be restricted both by the dot operator and by the
// index operator.
2013-08-09 21:47:13 +00:00
expect ( function ( ) {
2013-10-30 19:14:00 +00:00
scope . $eval ( 'foo.constructor()' , scope )
2013-08-09 21:47:13 +00:00
} ) . toThrowMinErr (
'$parse' , 'isecfld' , 'Referencing "constructor" field in Angular expressions is disallowed! ' +
2013-10-30 19:14:00 +00:00
'Expression: foo.constructor()' ) ;
2013-08-09 21:47:13 +00:00
expect ( function ( ) {
2013-10-30 19:14:00 +00:00
scope . $eval ( 'foo["constructor"]()' , scope )
2013-08-09 21:47:13 +00:00
} ) . toThrowMinErr (
'$parse' , 'isecfn' , 'Referencing Function in Angular expressions is disallowed! ' +
2013-10-30 19:14:00 +00:00
'Expression: foo["constructor"]()' ) ;
2013-08-09 21:47:13 +00:00
2013-10-30 19:14:00 +00:00
// User defined value assigned to constructor.
scope . foo . constructor = function constructor ( ) {
return "custom constructor" ;
} ;
// Dot operator should still block it.
2013-08-09 21:47:13 +00:00
expect ( function ( ) {
2013-10-30 19:14:00 +00:00
scope . $eval ( 'foo.constructor()' , scope )
2013-08-09 21:47:13 +00:00
} ) . toThrowMinErr (
'$parse' , 'isecfld' , 'Referencing "constructor" field in Angular expressions is disallowed! ' +
2013-10-30 19:14:00 +00:00
'Expression: foo.constructor()' ) ;
// However, the index operator should allow it.
expect ( scope . $eval ( 'foo["constructor"]()' , scope ) ) . toBe ( 'custom constructor' ) ;
2013-08-09 21:47:13 +00:00
} ) ;
2013-06-24 21:14:54 +00:00
} ) ;
2013-10-30 19:14:00 +00:00
it ( 'should call the function from the received instance and not from a new one' , function ( ) {
var n = 0 ;
scope . fn = function ( ) {
var c = n ++ ;
return { c : c , anotherFn : function ( ) { return this . c == c ; } } ;
2013-06-24 21:14:54 +00:00
} ;
2013-10-30 19:14:00 +00:00
expect ( scope . $eval ( 'fn().anotherFn()' ) ) . toBe ( true ) ;
2013-06-24 21:14:54 +00:00
} ) ;
2013-04-29 18:07:05 +00:00
2013-10-30 19:14:00 +00:00
it ( 'should call the function once when it is part of the context' , function ( ) {
var count = 0 ;
scope . fn = function ( ) {
count ++ ;
return { anotherFn : function ( ) { return "lucas" ; } } ;
} ;
expect ( scope . $eval ( 'fn().anotherFn()' ) ) . toBe ( 'lucas' ) ;
expect ( count ) . toBe ( 1 ) ;
} ) ;
2013-04-29 18:07:05 +00:00
2013-10-30 19:14:00 +00:00
it ( 'should call the function once when it is not part of the context' , function ( ) {
var count = 0 ;
scope . fn = function ( ) {
count ++ ;
return function ( ) { return 'lucas' ; } ;
} ;
expect ( scope . $eval ( 'fn()()' ) ) . toBe ( 'lucas' ) ;
expect ( count ) . toBe ( 1 ) ;
} ) ;
2013-04-29 18:07:05 +00:00
2013-10-30 19:14:00 +00:00
it ( 'should call the function once when it is part of the context on assignments' , function ( ) {
var count = 0 ;
var element = { } ;
scope . fn = function ( ) {
count ++ ;
return element ;
} ;
expect ( scope . $eval ( 'fn().name = "lucas"' ) ) . toBe ( 'lucas' ) ;
expect ( element . name ) . toBe ( 'lucas' ) ;
expect ( count ) . toBe ( 1 ) ;
} ) ;
2013-04-29 18:07:05 +00:00
2013-10-30 19:14:00 +00:00
it ( 'should call the function once when it is part of the context on array lookups' , function ( ) {
var count = 0 ;
var element = [ ] ;
scope . fn = function ( ) {
count ++ ;
return element ;
} ;
expect ( scope . $eval ( 'fn()[0] = "lucas"' ) ) . toBe ( 'lucas' ) ;
expect ( element [ 0 ] ) . toBe ( 'lucas' ) ;
expect ( count ) . toBe ( 1 ) ;
} ) ;
2013-04-29 18:07:05 +00:00
2013-10-30 19:14:00 +00:00
it ( 'should call the function once when it is part of the context on array lookup function' , function ( ) {
var count = 0 ;
var element = [ { anotherFn : function ( ) { return 'lucas' ; } } ] ;
scope . fn = function ( ) {
count ++ ;
return element ;
} ;
expect ( scope . $eval ( 'fn()[0].anotherFn()' ) ) . toBe ( 'lucas' ) ;
expect ( count ) . toBe ( 1 ) ;
} ) ;
2013-04-29 18:07:05 +00:00
2013-10-30 19:14:00 +00:00
it ( 'should call the function once when it is part of the context on property lookup function' , function ( ) {
var count = 0 ;
var element = { name : { anotherFn : function ( ) { return 'lucas' ; } } } ;
scope . fn = function ( ) {
count ++ ;
return element ;
} ;
expect ( scope . $eval ( 'fn().name.anotherFn()' ) ) . toBe ( 'lucas' ) ;
expect ( count ) . toBe ( 1 ) ;
} ) ;
2013-04-29 18:07:05 +00:00
2013-10-30 19:14:00 +00:00
it ( 'should call the function once when it is part of a sub-expression' , function ( ) {
var count = 0 ;
scope . element = [ { } ] ;
scope . fn = function ( ) {
count ++ ;
return 0 ;
} ;
expect ( scope . $eval ( 'element[fn()].name = "lucas"' ) ) . toBe ( 'lucas' ) ;
expect ( scope . element [ 0 ] . name ) . toBe ( 'lucas' ) ;
expect ( count ) . toBe ( 1 ) ;
} ) ;
2013-04-29 18:07:05 +00:00
2013-10-30 19:14:00 +00:00
describe ( 'assignable' , function ( ) {
it ( 'should expose assignment function' , inject ( function ( $parse ) {
var fn = $parse ( 'a' ) ;
expect ( fn . assign ) . toBeTruthy ( ) ;
var scope = { } ;
fn . assign ( scope , 123 ) ;
expect ( scope ) . toEqual ( { a : 123 } ) ;
} ) ) ;
} ) ;
2013-10-07 16:58:37 +00:00
2013-10-30 19:14:00 +00:00
describe ( 'locals' , function ( ) {
it ( 'should expose local variables' , inject ( function ( $parse ) {
expect ( $parse ( 'a' ) ( { a : 0 } , { a : 1 } ) ) . toEqual ( 1 ) ;
expect ( $parse ( 'add(a,b)' ) ( { b : 1 , add : function ( a , b ) { return a + b ; } } , { a : 2 } ) ) . toEqual ( 3 ) ;
} ) ) ;
2013-10-07 16:58:37 +00:00
2013-10-30 19:14:00 +00:00
it ( 'should expose traverse locals' , inject ( function ( $parse ) {
expect ( $parse ( 'a.b' ) ( { a : { b : 0 } } , { a : { b : 1 } } ) ) . toEqual ( 1 ) ;
expect ( $parse ( 'a.b' ) ( { a : null } , { a : { b : 1 } } ) ) . toEqual ( 1 ) ;
expect ( $parse ( 'a.b' ) ( { a : { b : 0 } } , { a : null } ) ) . toEqual ( undefined ) ;
} ) ) ;
} ) ;
2013-10-07 16:58:37 +00:00
2013-10-30 19:14:00 +00:00
describe ( 'literal' , function ( ) {
it ( 'should mark scalar value expressions as literal' , inject ( function ( $parse ) {
expect ( $parse ( '0' ) . literal ) . toBe ( true ) ;
expect ( $parse ( '"hello"' ) . literal ) . toBe ( true ) ;
expect ( $parse ( 'true' ) . literal ) . toBe ( true ) ;
expect ( $parse ( 'false' ) . literal ) . toBe ( true ) ;
expect ( $parse ( 'null' ) . literal ) . toBe ( true ) ;
expect ( $parse ( 'undefined' ) . literal ) . toBe ( true ) ;
} ) ) ;
2013-10-07 16:58:37 +00:00
2013-10-30 19:14:00 +00:00
it ( 'should mark array expressions as literal' , inject ( function ( $parse ) {
expect ( $parse ( '[]' ) . literal ) . toBe ( true ) ;
expect ( $parse ( '[1, 2, 3]' ) . literal ) . toBe ( true ) ;
expect ( $parse ( '[1, identifier]' ) . literal ) . toBe ( true ) ;
} ) ) ;
2013-10-07 16:58:37 +00:00
2013-10-30 19:14:00 +00:00
it ( 'should mark object expressions as literal' , inject ( function ( $parse ) {
expect ( $parse ( '{}' ) . literal ) . toBe ( true ) ;
expect ( $parse ( '{x: 1}' ) . literal ) . toBe ( true ) ;
expect ( $parse ( '{foo: bar}' ) . literal ) . toBe ( true ) ;
} ) ) ;
2013-10-07 16:58:37 +00:00
2013-10-30 19:14:00 +00:00
it ( 'should not mark function calls or operator expressions as literal' , inject ( function ( $parse ) {
expect ( $parse ( '1 + 1' ) . literal ) . toBe ( false ) ;
expect ( $parse ( 'call()' ) . literal ) . toBe ( false ) ;
expect ( $parse ( '[].length' ) . literal ) . toBe ( false ) ;
} ) ) ;
} ) ;
2013-10-07 16:58:37 +00:00
2013-10-30 19:14:00 +00:00
describe ( 'constant' , function ( ) {
it ( 'should mark scalar value expressions as constant' , inject ( function ( $parse ) {
expect ( $parse ( '12.3' ) . constant ) . toBe ( true ) ;
expect ( $parse ( '"string"' ) . constant ) . toBe ( true ) ;
expect ( $parse ( 'true' ) . constant ) . toBe ( true ) ;
expect ( $parse ( 'false' ) . constant ) . toBe ( true ) ;
expect ( $parse ( 'null' ) . constant ) . toBe ( true ) ;
expect ( $parse ( 'undefined' ) . constant ) . toBe ( true ) ;
} ) ) ;
2013-10-07 16:58:37 +00:00
2013-10-30 19:14:00 +00:00
it ( 'should mark arrays as constant if they only contain constant elements' , inject ( function ( $parse ) {
expect ( $parse ( '[]' ) . constant ) . toBe ( true ) ;
expect ( $parse ( '[1, 2, 3]' ) . constant ) . toBe ( true ) ;
expect ( $parse ( '["string", null]' ) . constant ) . toBe ( true ) ;
expect ( $parse ( '[[]]' ) . constant ) . toBe ( true ) ;
expect ( $parse ( '[1, [2, 3], {4: 5}]' ) . constant ) . toBe ( true ) ;
} ) ) ;
2013-10-07 16:58:37 +00:00
2013-10-30 19:14:00 +00:00
it ( 'should not mark arrays as constant if they contain any non-constant elements' , inject ( function ( $parse ) {
expect ( $parse ( '[foo]' ) . constant ) . toBe ( false ) ;
expect ( $parse ( '[x + 1]' ) . constant ) . toBe ( false ) ;
expect ( $parse ( '[bar[0]]' ) . constant ) . toBe ( false ) ;
} ) ) ;
2013-10-07 16:58:37 +00:00
2013-10-30 19:14:00 +00:00
it ( 'should mark complex expressions involving constant values as constant' , inject ( function ( $parse ) {
expect ( $parse ( '!true' ) . constant ) . toBe ( true ) ;
expect ( $parse ( '1 - 1' ) . constant ) . toBe ( true ) ;
expect ( $parse ( '"foo" + "bar"' ) . constant ) . toBe ( true ) ;
expect ( $parse ( '5 != null' ) . constant ) . toBe ( true ) ;
expect ( $parse ( '{standard: 4/3, wide: 16/9}' ) . constant ) . toBe ( true ) ;
} ) ) ;
2013-10-07 16:58:37 +00:00
2013-10-30 19:14:00 +00:00
it ( 'should not mark any expression involving variables or function calls as constant' , inject ( function ( $parse ) {
expect ( $parse ( 'true.toString()' ) . constant ) . toBe ( false ) ;
expect ( $parse ( 'foo(1, 2, 3)' ) . constant ) . toBe ( false ) ;
expect ( $parse ( '"name" + id' ) . constant ) . toBe ( false ) ;
} ) ) ;
} ) ;
2013-10-07 16:58:37 +00:00
} ) ;
} ) ;
} ) ;
describe ( 'promises' , function ( ) {
var deferred , promise , q ;
describe ( 'unwrapPromises setting' , function ( ) {
beforeEach ( inject ( function ( $rootScope , $q ) {
scope = $rootScope ;
$rootScope . $apply ( function ( ) {
deferred = $q . defer ( ) ;
deferred . resolve ( 'Bobo' ) ;
promise = deferred . promise ;
} ) ;
} ) ) ;
it ( 'should not unwrap promises by default' , inject ( function ( $parse ) {
scope . person = promise ;
scope . things = { person : promise } ;
scope . getPerson = function ( ) { return promise ; } ;
var getter = $parse ( 'person' ) ;
var propGetter = $parse ( 'things.person' ) ;
var fnGetter = $parse ( 'getPerson()' ) ;
expect ( getter ( scope ) ) . toBe ( promise ) ;
expect ( propGetter ( scope ) ) . toBe ( promise ) ;
expect ( fnGetter ( scope ) ) . toBe ( promise ) ;
} ) ) ;
} ) ;
forEach ( [ true , false ] , function ( cspEnabled ) {
describe ( 'promise logging (csp:' + cspEnabled + ')' , function ( ) {
var $log ;
var PROMISE _WARNING _REGEXP = /\[\$parse\] Promise found in the expression `[^`]+`. Automatic unwrapping of promises in Angular expressions is deprecated\./ ;
beforeEach ( module ( function ( $parseProvider ) {
$parseProvider . unwrapPromises ( true ) ;
} ) ) ;
beforeEach ( inject ( function ( $rootScope , $q , _$log _ ) {
scope = $rootScope ;
$rootScope . $apply ( function ( ) {
deferred = $q . defer ( ) ;
deferred . resolve ( 'Bobo' ) ;
promise = deferred . promise ;
} ) ;
$log = _$log _ ;
} ) ) ;
it ( 'should log warnings by default' , function ( ) {
scope . person = promise ;
scope . $eval ( 'person' ) ;
expect ( $log . warn . logs . pop ( ) ) . toEqual ( [ '[$parse] Promise found in the expression `person`. ' +
'Automatic unwrapping of promises in Angular expressions is deprecated.' ] ) ;
} ) ;
it ( 'should log warnings for deep promises' , function ( ) {
scope . car = { wheel : { disc : promise } } ;
scope . $eval ( 'car.wheel.disc.pad' ) ;
expect ( $log . warn . logs . pop ( ) ) . toMatch ( PROMISE _WARNING _REGEXP ) ;
} ) ;
it ( 'should log warnings for setters' , function ( ) {
scope . person = promise ;
scope . $eval ( 'person.name = "Bubu"' ) ;
expect ( $log . warn . logs . pop ( ) ) . toMatch ( PROMISE _WARNING _REGEXP ) ;
} ) ;
it ( 'should log only a single warning for each expression' , function ( ) {
scope . person1 = promise ;
scope . person2 = promise ;
scope . $eval ( 'person1' ) ;
scope . $eval ( 'person1' ) ;
expect ( $log . warn . logs . pop ( ) ) . toMatch ( /`person1`/ ) ;
expect ( $log . warn . logs ) . toEqual ( [ ] ) ;
scope . $eval ( 'person1' ) ;
scope . $eval ( 'person2' ) ;
scope . $eval ( 'person1' ) ;
scope . $eval ( 'person2' ) ;
expect ( $log . warn . logs . pop ( ) ) . toMatch ( /`person2`/ ) ;
expect ( $log . warn . logs ) . toEqual ( [ ] ) ;
} ) ;
it ( 'should log warning for complex expressions' , function ( ) {
scope . person1 = promise ;
scope . person2 = promise ;
scope . $eval ( 'person1 + person2' ) ;
expect ( $log . warn . logs . pop ( ) ) . toMatch ( /`person1 \+ person2`/ ) ;
expect ( $log . warn . logs ) . toEqual ( [ ] ) ;
} ) ;
} ) ;
} ) ;
forEach ( [ true , false ] , function ( cspEnabled ) {
describe ( 'csp ' + cspEnabled , function ( ) {
beforeEach ( module ( function ( $parseProvider ) {
$parseProvider . unwrapPromises ( true ) ;
$parseProvider . logPromiseWarnings ( false ) ;
} ) ) ;
beforeEach ( inject ( function ( $rootScope , $sniffer , $q ) {
scope = $rootScope ;
$sniffer . csp = cspEnabled ;
2011-11-23 23:53:06 +00:00
2012-04-14 17:39:24 +00:00
q = $q ;
deferred = q . defer ( ) ;
promise = deferred . promise ;
} ) ) ;
2011-11-23 23:53:06 +00:00
2013-10-07 16:58:37 +00:00
2012-04-14 17:39:24 +00:00
describe ( '{{promise}}' , function ( ) {
it ( 'should evaluated resolved promise and get its value' , function ( ) {
deferred . resolve ( 'hello!' ) ;
scope . greeting = promise ;
expect ( scope . $eval ( 'greeting' ) ) . toBe ( undefined ) ;
scope . $digest ( ) ;
expect ( scope . $eval ( 'greeting' ) ) . toBe ( 'hello!' ) ;
} ) ;
2011-11-23 23:53:06 +00:00
2012-04-14 17:39:24 +00:00
it ( 'should evaluated rejected promise and ignore the rejection reason' , function ( ) {
deferred . reject ( 'sorry' ) ;
scope . greeting = promise ;
2013-10-07 16:58:37 +00:00
expect ( scope . $eval ( 'greeting' ) ) . toBe ( undefined ) ;
2012-04-14 17:39:24 +00:00
scope . $digest ( ) ;
expect ( scope . $eval ( 'greeting' ) ) . toBe ( undefined ) ;
} ) ;
2011-11-23 23:53:06 +00:00
2012-04-14 17:39:24 +00:00
it ( 'should evaluate a promise and eventualy get its value' , function ( ) {
scope . greeting = promise ;
expect ( scope . $eval ( 'greeting' ) ) . toBe ( undefined ) ;
2012-04-27 22:20:54 +00:00
2012-04-14 17:39:24 +00:00
scope . $digest ( ) ;
expect ( scope . $eval ( 'greeting' ) ) . toBe ( undefined ) ;
2012-04-27 22:20:54 +00:00
2012-04-14 17:39:24 +00:00
deferred . resolve ( 'hello!' ) ;
expect ( scope . $eval ( 'greeting' ) ) . toBe ( undefined ) ;
scope . $digest ( ) ;
expect ( scope . $eval ( 'greeting' ) ) . toBe ( 'hello!' ) ;
} ) ;
2011-11-23 23:53:06 +00:00
2012-04-14 17:39:24 +00:00
it ( 'should evaluate a promise and eventualy ignore its rejection' , function ( ) {
scope . greeting = promise ;
expect ( scope . $eval ( 'greeting' ) ) . toBe ( undefined ) ;
2011-11-23 23:53:06 +00:00
2012-04-14 17:39:24 +00:00
scope . $digest ( ) ;
expect ( scope . $eval ( 'greeting' ) ) . toBe ( undefined ) ;
deferred . reject ( 'sorry' ) ;
expect ( scope . $eval ( 'greeting' ) ) . toBe ( undefined ) ;
scope . $digest ( ) ;
expect ( scope . $eval ( 'greeting' ) ) . toBe ( undefined ) ;
} ) ;
2013-06-03 03:04:12 +00:00
describe ( 'assignment into promises' , function ( ) {
// This behavior is analogous to assignments to non-promise values
// that are lazily set on the scope.
it ( 'should evaluate a resolved object promise and set its value' , inject ( function ( $parse ) {
scope . person = promise ;
deferred . resolve ( { 'name' : 'Bill Gates' } ) ;
2013-10-07 16:58:37 +00:00
var getter = $parse ( 'person.name' , { unwrapPromises : true } ) ;
2013-06-03 03:04:12 +00:00
expect ( getter ( scope ) ) . toBe ( undefined ) ;
scope . $digest ( ) ;
expect ( getter ( scope ) ) . toBe ( 'Bill Gates' ) ;
getter . assign ( scope , 'Warren Buffet' ) ;
expect ( getter ( scope ) ) . toBe ( 'Warren Buffet' ) ;
} ) ) ;
2013-08-13 22:30:52 +00:00
it ( 'should evaluate a resolved primitive type promise and set its value' , inject ( function ( $parse ) {
2013-06-03 03:04:12 +00:00
scope . greeting = promise ;
deferred . resolve ( 'Salut!' ) ;
2013-08-13 22:30:52 +00:00
2013-10-07 16:58:37 +00:00
var getter = $parse ( 'greeting' , { unwrapPromises : true } ) ;
2013-06-03 03:04:12 +00:00
expect ( getter ( scope ) ) . toBe ( undefined ) ;
scope . $digest ( ) ;
expect ( getter ( scope ) ) . toBe ( 'Salut!' ) ;
getter . assign ( scope , 'Bonjour' ) ;
expect ( getter ( scope ) ) . toBe ( 'Bonjour' ) ;
} ) ) ;
it ( 'should evaluate an unresolved promise and set and remember its value' , inject ( function ( $parse ) {
scope . person = promise ;
2013-10-07 16:58:37 +00:00
var getter = $parse ( 'person.name' , { unwrapPromises : true } ) ;
2013-06-03 03:04:12 +00:00
expect ( getter ( scope ) ) . toBe ( undefined ) ;
scope . $digest ( ) ;
expect ( getter ( scope ) ) . toBe ( undefined ) ;
getter . assign ( scope , 'Bonjour' ) ;
scope . $digest ( ) ;
expect ( getter ( scope ) ) . toBe ( 'Bonjour' ) ;
2013-10-07 16:58:37 +00:00
var c1Getter = $parse ( 'person.A.B.C1' , { unwrapPromises : true } ) ;
2013-06-03 03:04:12 +00:00
scope . $digest ( ) ;
expect ( c1Getter ( scope ) ) . toBe ( undefined ) ;
c1Getter . assign ( scope , 'c1_value' ) ;
scope . $digest ( ) ;
expect ( c1Getter ( scope ) ) . toBe ( 'c1_value' ) ;
// Set another property on the person.A.B
2013-10-07 16:58:37 +00:00
var c2Getter = $parse ( 'person.A.B.C2' , { unwrapPromises : true } ) ;
2013-06-03 03:04:12 +00:00
scope . $digest ( ) ;
expect ( c2Getter ( scope ) ) . toBe ( undefined ) ;
c2Getter . assign ( scope , 'c2_value' ) ;
scope . $digest ( ) ;
expect ( c2Getter ( scope ) ) . toBe ( 'c2_value' ) ;
// c1 should be unchanged.
2013-10-07 16:58:37 +00:00
expect ( $parse ( 'person.A' , { unwrapPromises : true } ) ( scope ) ) . toEqual (
2013-06-03 03:04:12 +00:00
{ B : { C1 : 'c1_value' , C2 : 'c2_value' } } ) ;
} ) ) ;
it ( 'should evaluate a resolved promise and overwrite the previous set value in the absense of the getter' ,
2013-10-07 16:58:37 +00:00
inject ( function ( $parse ) {
2013-06-03 03:04:12 +00:00
scope . person = promise ;
2013-10-07 16:58:37 +00:00
var c1Getter = $parse ( 'person.A.B.C1' , { unwrapPromises : true } ) ;
2013-06-03 03:04:12 +00:00
c1Getter . assign ( scope , 'c1_value' ) ;
// resolving the promise should update the tree.
deferred . resolve ( { A : { B : { C1 : 'resolved_c1' } } } ) ;
scope . $digest ( ) ;
expect ( c1Getter ( scope ) ) . toEqual ( 'resolved_c1' ) ;
} ) ) ;
} ) ;
2012-04-27 22:20:54 +00:00
} ) ;
2011-11-23 23:53:06 +00:00
2012-04-14 17:39:24 +00:00
describe ( 'dereferencing' , function ( ) {
it ( 'should evaluate and dereference properties leading to and from a promise' , function ( ) {
scope . obj = { greeting : promise } ;
expect ( scope . $eval ( 'obj.greeting' ) ) . toBe ( undefined ) ;
expect ( scope . $eval ( 'obj.greeting.polite' ) ) . toBe ( undefined ) ;
2011-11-23 23:53:06 +00:00
2012-04-14 17:39:24 +00:00
scope . $digest ( ) ;
expect ( scope . $eval ( 'obj.greeting' ) ) . toBe ( undefined ) ;
expect ( scope . $eval ( 'obj.greeting.polite' ) ) . toBe ( undefined ) ;
2011-11-23 23:53:06 +00:00
2012-04-14 17:39:24 +00:00
deferred . resolve ( { polite : 'Good morning!' } ) ;
scope . $digest ( ) ;
expect ( scope . $eval ( 'obj.greeting' ) ) . toEqual ( { polite : 'Good morning!' } ) ;
expect ( scope . $eval ( 'obj.greeting.polite' ) ) . toBe ( 'Good morning!' ) ;
} ) ;
2011-11-23 23:53:06 +00:00
2012-04-14 17:39:24 +00:00
it ( 'should evaluate and dereference properties leading to and from a promise via bracket ' +
'notation' , function ( ) {
scope . obj = { greeting : promise } ;
expect ( scope . $eval ( 'obj["greeting"]' ) ) . toBe ( undefined ) ;
expect ( scope . $eval ( 'obj["greeting"]["polite"]' ) ) . toBe ( undefined ) ;
2011-11-23 23:53:06 +00:00
2012-04-14 17:39:24 +00:00
scope . $digest ( ) ;
expect ( scope . $eval ( 'obj["greeting"]' ) ) . toBe ( undefined ) ;
expect ( scope . $eval ( 'obj["greeting"]["polite"]' ) ) . toBe ( undefined ) ;
2011-11-23 23:53:06 +00:00
2012-04-14 17:39:24 +00:00
deferred . resolve ( { polite : 'Good morning!' } ) ;
scope . $digest ( ) ;
expect ( scope . $eval ( 'obj["greeting"]' ) ) . toEqual ( { polite : 'Good morning!' } ) ;
expect ( scope . $eval ( 'obj["greeting"]["polite"]' ) ) . toBe ( 'Good morning!' ) ;
} ) ;
2011-11-23 23:53:06 +00:00
2012-04-14 17:39:24 +00:00
it ( 'should evaluate and dereference array references leading to and from a promise' ,
function ( ) {
2013-10-07 16:58:37 +00:00
scope . greetings = [ promise ] ;
expect ( scope . $eval ( 'greetings[0]' ) ) . toBe ( undefined ) ;
expect ( scope . $eval ( 'greetings[0][0]' ) ) . toBe ( undefined ) ;
2011-11-23 23:53:06 +00:00
2013-10-07 16:58:37 +00:00
scope . $digest ( ) ;
expect ( scope . $eval ( 'greetings[0]' ) ) . toBe ( undefined ) ;
expect ( scope . $eval ( 'greetings[0][0]' ) ) . toBe ( undefined ) ;
2011-11-23 23:53:06 +00:00
2013-10-07 16:58:37 +00:00
deferred . resolve ( [ 'Hi!' , 'Cau!' ] ) ;
scope . $digest ( ) ;
expect ( scope . $eval ( 'greetings[0]' ) ) . toEqual ( [ 'Hi!' , 'Cau!' ] ) ;
expect ( scope . $eval ( 'greetings[0][0]' ) ) . toBe ( 'Hi!' ) ;
} ) ;
2011-11-23 23:53:06 +00:00
2012-04-14 17:39:24 +00:00
it ( 'should evaluate and dereference promises used as function arguments' , function ( ) {
scope . greet = function ( name ) { return 'Hi ' + name + '!' ; } ;
scope . name = promise ;
expect ( scope . $eval ( 'greet(name)' ) ) . toBe ( 'Hi undefined!' ) ;
2011-11-23 23:53:06 +00:00
2012-04-14 17:39:24 +00:00
scope . $digest ( ) ;
expect ( scope . $eval ( 'greet(name)' ) ) . toBe ( 'Hi undefined!' ) ;
2011-11-23 23:53:06 +00:00
2012-04-14 17:39:24 +00:00
deferred . resolve ( 'Veronica' ) ;
expect ( scope . $eval ( 'greet(name)' ) ) . toBe ( 'Hi undefined!' ) ;
2011-11-23 23:53:06 +00:00
2012-04-14 17:39:24 +00:00
scope . $digest ( ) ;
expect ( scope . $eval ( 'greet(name)' ) ) . toBe ( 'Hi Veronica!' ) ;
} ) ;
2011-11-23 23:53:06 +00:00
2012-04-14 17:39:24 +00:00
it ( 'should evaluate and dereference promises used as array indexes' , function ( ) {
scope . childIndex = promise ;
scope . kids = [ 'Adam' , 'Veronica' , 'Elisa' ] ;
expect ( scope . $eval ( 'kids[childIndex]' ) ) . toBe ( undefined ) ;
2011-11-23 23:53:06 +00:00
2012-04-14 17:39:24 +00:00
scope . $digest ( ) ;
expect ( scope . $eval ( 'kids[childIndex]' ) ) . toBe ( undefined ) ;
2011-11-23 23:53:06 +00:00
2012-04-14 17:39:24 +00:00
deferred . resolve ( 1 ) ;
expect ( scope . $eval ( 'kids[childIndex]' ) ) . toBe ( undefined ) ;
2012-04-27 22:20:54 +00:00
2012-04-14 17:39:24 +00:00
scope . $digest ( ) ;
expect ( scope . $eval ( 'kids[childIndex]' ) ) . toBe ( 'Veronica' ) ;
} ) ;
2012-04-27 22:20:54 +00:00
2012-04-14 17:39:24 +00:00
it ( 'should evaluate and dereference promises used as keys in bracket notation' , function ( ) {
scope . childKey = promise ;
scope . kids = { 'a' : 'Adam' , 'v' : 'Veronica' , 'e' : 'Elisa' } ;
2012-04-27 22:20:54 +00:00
2012-04-14 17:39:24 +00:00
expect ( scope . $eval ( 'kids[childKey]' ) ) . toBe ( undefined ) ;
scope . $digest ( ) ;
expect ( scope . $eval ( 'kids[childKey]' ) ) . toBe ( undefined ) ;
2012-04-27 22:20:54 +00:00
2012-04-14 17:39:24 +00:00
deferred . resolve ( 'v' ) ;
expect ( scope . $eval ( 'kids[childKey]' ) ) . toBe ( undefined ) ;
2012-04-27 22:20:54 +00:00
2012-04-14 17:39:24 +00:00
scope . $digest ( ) ;
expect ( scope . $eval ( 'kids[childKey]' ) ) . toBe ( 'Veronica' ) ;
} ) ;
it ( 'should not mess with the promise if it was not directly evaluated' , function ( ) {
scope . obj = { greeting : promise , username : 'hi' } ;
var obj = scope . $eval ( 'obj' ) ;
expect ( obj . username ) . toEqual ( 'hi' ) ;
expect ( typeof obj . greeting . then ) . toBe ( 'function' ) ;
} ) ;
2012-04-27 22:20:54 +00:00
} ) ;
2011-11-23 23:53:06 +00:00
} ) ;
2012-04-27 22:20:54 +00:00
} ) ;
2012-02-07 05:56:05 +00:00
} ) ;
2010-10-15 20:44:53 +00:00
} ) ;