utils.spec.ts 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. import type { TransformContext } from '../src'
  2. import type { Position } from '../src/ast'
  3. import {
  4. advancePositionWithClone,
  5. isMemberExpressionBrowser,
  6. isMemberExpressionNode,
  7. toValidAssetId,
  8. } from '../src/utils'
  9. function p(line: number, column: number, offset: number): Position {
  10. return { column, line, offset }
  11. }
  12. describe('advancePositionWithClone', () => {
  13. test('same line', () => {
  14. const pos = p(1, 1, 0)
  15. const newPos = advancePositionWithClone(pos, 'foo\nbar', 2)
  16. expect(newPos.column).toBe(3)
  17. expect(newPos.line).toBe(1)
  18. expect(newPos.offset).toBe(2)
  19. })
  20. test('same line', () => {
  21. const pos = p(1, 1, 0)
  22. const newPos = advancePositionWithClone(pos, 'foo\nbar', 4)
  23. expect(newPos.column).toBe(1)
  24. expect(newPos.line).toBe(2)
  25. expect(newPos.offset).toBe(4)
  26. })
  27. test('multiple lines', () => {
  28. const pos = p(1, 1, 0)
  29. const newPos = advancePositionWithClone(pos, 'foo\nbar\nbaz', 10)
  30. expect(newPos.column).toBe(3)
  31. expect(newPos.line).toBe(3)
  32. expect(newPos.offset).toBe(10)
  33. })
  34. })
  35. describe('isMemberExpression', () => {
  36. function commonAssertions(fn: (str: string) => boolean) {
  37. // should work
  38. expect(fn('obj.foo')).toBe(true)
  39. expect(fn('obj[foo]')).toBe(true)
  40. expect(fn('obj[arr[0]]')).toBe(true)
  41. expect(fn('obj[arr[ret.bar]]')).toBe(true)
  42. expect(fn('obj[arr[ret[bar]]]')).toBe(true)
  43. expect(fn('obj[arr[ret[bar]]].baz')).toBe(true)
  44. expect(fn('obj[1 + 1]')).toBe(true)
  45. expect(fn(`obj[x[0]]`)).toBe(true)
  46. expect(fn('obj[1][2]')).toBe(true)
  47. expect(fn('obj[1][2].foo[3].bar.baz')).toBe(true)
  48. expect(fn(`a[b[c.d]][0]`)).toBe(true)
  49. expect(fn('obj?.foo')).toBe(true)
  50. expect(fn('foo().test')).toBe(true)
  51. // strings
  52. expect(fn(`a['foo' + bar[baz]["qux"]]`)).toBe(true)
  53. // multiline whitespaces
  54. expect(fn('obj \n .foo \n [bar \n + baz]')).toBe(true)
  55. expect(fn(`\n model\n.\nfoo \n`)).toBe(true)
  56. // should fail
  57. expect(fn('a \n b')).toBe(false)
  58. expect(fn('obj[foo')).toBe(false)
  59. expect(fn('objfoo]')).toBe(false)
  60. expect(fn('obj[arr[0]')).toBe(false)
  61. expect(fn('obj[arr0]]')).toBe(false)
  62. expect(fn('a + b')).toBe(false)
  63. expect(fn('foo()')).toBe(false)
  64. expect(fn('a?b:c')).toBe(false)
  65. expect(fn(`state['text'] = $event`)).toBe(false)
  66. }
  67. test('browser', () => {
  68. commonAssertions(isMemberExpressionBrowser)
  69. expect(isMemberExpressionBrowser('123[a]')).toBe(false)
  70. })
  71. test('node', () => {
  72. const ctx = { expressionPlugins: ['typescript'] } as any as TransformContext
  73. const fn = (str: string) => isMemberExpressionNode(str, ctx)
  74. commonAssertions(fn)
  75. // TS-specific checks
  76. expect(fn('foo as string')).toBe(true)
  77. expect(fn(`foo.bar as string`)).toBe(true)
  78. expect(fn(`foo['bar'] as string`)).toBe(true)
  79. expect(fn(`foo[bar as string]`)).toBe(true)
  80. expect(fn(`(foo as string)`)).toBe(true)
  81. expect(fn(`123[a]`)).toBe(true)
  82. expect(fn(`foo() as string`)).toBe(false)
  83. expect(fn(`a + b as string`)).toBe(false)
  84. // #9865
  85. expect(fn('""')).toBe(false)
  86. expect(fn('undefined')).toBe(false)
  87. expect(fn('null')).toBe(false)
  88. })
  89. })
  90. test('toValidAssetId', () => {
  91. expect(toValidAssetId('foo', 'component')).toBe('_component_foo')
  92. expect(toValidAssetId('p', 'directive')).toBe('_directive_p')
  93. expect(toValidAssetId('div', 'filter')).toBe('_filter_div')
  94. expect(toValidAssetId('foo-bar', 'component')).toBe('_component_foo_bar')
  95. expect(toValidAssetId('test-测试-1', 'component')).toBe(
  96. '_component_test_2797935797_1',
  97. )
  98. })