github.com/insionng/yougam@v0.0.0-20170714101924-2bc18d833463/public/libs/vue-1.0.24/test/unit/specs/parsers/expression_spec.js (about)

     1  var expParser = require('src/parsers/expression')
     2  
     3  var testCases = [
     4    {
     5      // simple path
     6      exp: 'a.b.d',
     7      scope: {
     8        a: { b: { d: 123 }}
     9      },
    10      expected: 123,
    11      paths: ['a']
    12    },
    13    // complex path
    14    {
    15      exp: 'a["b"].c',
    16      scope: {
    17        a: { b: { c: 234 }}
    18      },
    19      expected: 234,
    20      paths: ['a']
    21    },
    22    {
    23      // string concat
    24      exp: 'a+b',
    25      scope: {
    26        a: 'hello',
    27        b: 'world'
    28      },
    29      expected: 'helloworld',
    30      paths: ['a', 'b']
    31    },
    32    {
    33      // math
    34      exp: 'a - b * 2 + 45',
    35      scope: {
    36        a: 100,
    37        b: 23
    38      },
    39      expected: 100 - 23 * 2 + 45,
    40      paths: ['a', 'b']
    41    },
    42    {
    43      // boolean logic
    44      exp: '(a && b) ? c : d || e',
    45      scope: {
    46        a: true,
    47        b: false,
    48        c: null,
    49        d: false,
    50        e: 'worked'
    51      },
    52      expected: 'worked',
    53      paths: ['a', 'b', 'c', 'd', 'e']
    54    },
    55    {
    56      // inline string with newline
    57      exp: "a + 'hel\nlo'",
    58      scope: {
    59        a: 'inline '
    60      },
    61      expected: 'inline hel\nlo',
    62      paths: ['a']
    63    },
    64    {
    65      // multiline expressions
    66      exp: "{\n a: '35',\n b: c}",
    67      scope: {c: 32},
    68      expected: { a: '35', b: 32 }
    69    },
    70    {
    71      // dollar signs and underscore
    72      exp: "_a + ' ' + $b",
    73      scope: {
    74        _a: 'underscore',
    75        $b: 'dollar'
    76      },
    77      expected: 'underscore dollar',
    78      paths: ['_a', '$b']
    79    },
    80    {
    81      // complex with nested values
    82      exp: "todo.title + ' : ' + (todo['done'] ? 'yep' : 'nope')",
    83      scope: {
    84        todo: {
    85          title: 'write tests',
    86          done: false
    87        }
    88      },
    89      expected: 'write tests : nope',
    90      paths: ['todo']
    91    },
    92    {
    93      // expression with no data variables
    94      exp: "'a' + 'b'",
    95      scope: {},
    96      expected: 'ab',
    97      paths: []
    98    },
    99    {
   100      // values with same variable name inside strings
   101      exp: "'\"test\"' + test + \"'hi'\" + hi",
   102      scope: {
   103        test: 1,
   104        hi: 2
   105      },
   106      expected: '"test"1\'hi\'2',
   107      paths: ['test', 'hi']
   108    },
   109    {
   110      // expressions with inline object literals
   111      exp: "sortRows({ column: 'name', test: foo, durrr: 123 })",
   112      scope: {
   113        sortRows: function (params) {
   114          return params.column + params.test + params.durrr
   115        },
   116        foo: 'bar'
   117      },
   118      expected: 'namebar123',
   119      paths: ['sortRows', 'bar']
   120    },
   121    {
   122      // space between path segments
   123      exp: '  a    .   b    .  c + d',
   124      scope: {
   125        a: { b: { c: 12 }},
   126        d: 3
   127      },
   128      expected: 15,
   129      paths: ['a', 'd']
   130    },
   131    {
   132      // space in bracket identifiers
   133      exp: ' a[ " a.b.c " ] + b  [ \' e \' ]',
   134      scope: {
   135        a: {' a.b.c ': 123},
   136        b: {' e ': 234}
   137      },
   138      expected: 357,
   139      paths: ['a', 'b']
   140    },
   141    {
   142      // number literal
   143      exp: 'a * 1e2 + 1.1',
   144      scope: {
   145        a: 3
   146      },
   147      expected: 301.1,
   148      paths: ['a']
   149    },
   150    {
   151      // keyowrd + keyword literal
   152      exp: 'true && a.true',
   153      scope: {
   154        a: { 'true': false }
   155      },
   156      expected: false,
   157      paths: ['a']
   158    },
   159    {
   160      // super complex
   161      exp: ' $a + b[ "  a.b.c  " ][\'123\'].$e&&c[ " d " ].e + Math.round(e) ',
   162      scope: {
   163        $a: 1,
   164        b: {
   165          '  a.b.c  ': {
   166            '123': { $e: 2 }
   167          }
   168        },
   169        c: { ' d ': {e: 3}},
   170        e: 4.5
   171      },
   172      expected: 8,
   173      paths: ['$a', 'b', 'c', 'e']
   174    },
   175    {
   176      // string with escaped quotes
   177      exp: "'a\\'b' + c",
   178      scope: {
   179        c: '\'c'
   180      },
   181      expected: "a'b'c",
   182      paths: ['c']
   183    },
   184    {
   185      // dynamic sub path
   186      exp: "a['b' + i + 'c']",
   187      scope: {
   188        i: 0,
   189        a: {
   190          'b0c': 123
   191        }
   192      },
   193      expected: 123,
   194      paths: ['a', 'i']
   195    },
   196    {
   197      // Math global, simple path
   198      exp: 'Math.PI',
   199      scope: {},
   200      expected: Math.PI,
   201      paths: []
   202    },
   203    {
   204      // Math global, exp
   205      exp: 'Math.sin(a)',
   206      scope: {
   207        a: 1
   208      },
   209      expected: Math.sin(1),
   210      paths: ['a']
   211    },
   212    {
   213      // boolean literal
   214      exp: 'true',
   215      scope: {
   216        true: false
   217      },
   218      expected: true,
   219      paths: []
   220    },
   221    {
   222      // Date global
   223      exp: 'Date.now() > new Date("2000-01-01")',
   224      scope: {},
   225      expected: true,
   226      paths: []
   227    },
   228    // typeof operator
   229    {
   230      exp: 'typeof test === "string"',
   231      scope: { test: '123' },
   232      expected: true,
   233      paths: ['test']
   234    },
   235    // isNaN
   236    {
   237      exp: 'isNaN(a)',
   238      scope: { a: 2 },
   239      expected: false,
   240      paths: ['a']
   241    },
   242    // parseFloat & parseInt
   243    {
   244      exp: 'parseInt(a, 10) + parseFloat(b)',
   245      scope: { a: 2.33, b: '3.45' },
   246      expected: 5.45,
   247      paths: ['a', 'b']
   248    }
   249  ]
   250  
   251  describe('Expression Parser', function () {
   252    testCases.forEach(function (testCase) {
   253      it('parse getter: ' + testCase.exp, function () {
   254        var res = expParser.parseExpression(testCase.exp, true)
   255        expect(res.get(testCase.scope)).toEqual(testCase.expected)
   256      })
   257    })
   258  
   259    it('dynamic setter', function () {
   260      // make sure checkSetter works:
   261      // should add setter if a cache hit doesn't have hit function.
   262      expParser.parseExpression('a[b]')
   263      var res = expParser.parseExpression('a[b]', true)
   264      var scope = {
   265        a: { c: 1 },
   266        b: 'c'
   267      }
   268      res.set(scope, 2)
   269      expect(scope.a.c).toBe(2)
   270    })
   271  
   272    it('simple path setter', function () {
   273      var res = expParser.parseExpression('a.b.c', true)
   274      var scope = {}
   275      expect(function () {
   276        res.set(scope, 123)
   277      }).not.toThrow()
   278      scope.a = {b: {c: 0}}
   279      res.set(scope, 123)
   280      expect(scope.a.b.c).toBe(123)
   281    })
   282  
   283    it('cache', function () {
   284      var res1 = expParser.parseExpression('a + b')
   285      var res2 = expParser.parseExpression('a + b')
   286      expect(res1).toBe(res2)
   287    })
   288  
   289    if (canMakeTemplateStringFunction()) {
   290      it('ES2015 template string handling', function () {
   291        var res = expParser.parseExpression('a + `hi ${ b }` + c')
   292        expect(res.get.toString().indexOf('scope.a+`hi ${scope.b}`+scope.c') > -1).toBe(true)
   293        res = expParser.parseExpression('`hi ${ b + `${ d }` }`')
   294        expect(res.get.toString().indexOf('`hi ${scope.b+`${scope.d}`}`') > -1).toBe(true)
   295        res = expParser.parseExpression('{transform:`rotate(${x}deg)`}')
   296        expect(res.get.toString().indexOf('{transform:`rotate(${scope.x}deg)`}') > -1).toBe(true)
   297      })
   298    }
   299  
   300    describe('invalid expression', function () {
   301      it('should warn on invalid expression', function () {
   302        expect(getWarnCount()).toBe(0)
   303        expParser.parseExpression('a--b"ffff')
   304        expect('Invalid expression').toHaveBeenWarned()
   305      })
   306  
   307      it('should warn on invalid setter expression', function () {
   308        expect(getWarnCount()).toBe(0)
   309        expParser.parseExpression('a+b', true)
   310        expect('Invalid setter expression').toHaveBeenWarned()
   311      })
   312  
   313      it('should warn if expression contains improper reserved keywords', function () {
   314        expect(getWarnCount()).toBe(0)
   315        expParser.parseExpression('break + 1')
   316        expect('Avoid using reserved keywords').toHaveBeenWarned()
   317      })
   318    })
   319  })
   320  
   321  function canMakeTemplateStringFunction () {
   322    try {
   323      /* eslint-disable no-new-func */
   324      new Function('a', 'return `${a}`')
   325    } catch (e) {
   326      return false
   327    }
   328    return true
   329  }