visitor.js 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. import { Visitor, parse, print, Exception } from '../dist/esm';
  2. import { equals, shouldThrow } from './utils';
  3. describe('Visitor', function() {
  4. it('should provide coverage', function() {
  5. // Simply run the thing and make sure it does not fail and that all of the
  6. // stub methods are executed
  7. let visitor = new Visitor();
  8. visitor.accept(
  9. parse(
  10. '{{foo}}{{#foo (bar 1 "1" true undefined null) foo=@data}}{{!comment}}{{> bar }} {{/foo}}'
  11. )
  12. );
  13. visitor.accept(parse('{{#> bar }} {{/bar}}'));
  14. visitor.accept(parse('{{#* bar }} {{/bar}}'));
  15. visitor.accept(parse('{{* bar }}'));
  16. });
  17. it('should traverse to stubs', function() {
  18. let visitor = new Visitor();
  19. visitor.StringLiteral = function(string) {
  20. equals(string.value, '2');
  21. };
  22. visitor.NumberLiteral = function(number) {
  23. equals(number.value, 1);
  24. };
  25. visitor.BooleanLiteral = function(bool) {
  26. equals(bool.value, true);
  27. equals(this.parents.length, 3);
  28. equals(this.parents[0].type, 'SubExpression');
  29. equals(this.parents[1].type, 'BlockStatement');
  30. equals(this.parents[2].type, 'Program');
  31. };
  32. visitor.PathExpression = function(id) {
  33. equals(/(foo\.)?bar$/.test(id.original), true);
  34. };
  35. visitor.ContentStatement = function(content) {
  36. equals(content.value, ' ');
  37. };
  38. visitor.CommentStatement = function(comment) {
  39. equals(comment.value, 'comment');
  40. };
  41. visitor.accept(
  42. parse(
  43. '{{#foo.bar (foo.bar 1 "2" true) foo=@foo.bar}}{{!comment}}{{> bar }} {{/foo.bar}}'
  44. )
  45. );
  46. });
  47. describe('mutating', function() {
  48. describe('fields', function() {
  49. it('should replace value', function() {
  50. let visitor = new Visitor();
  51. visitor.mutating = true;
  52. visitor.StringLiteral = function(string) {
  53. return { type: 'NumberLiteral', value: 42, loc: string.loc };
  54. };
  55. let ast = parse('{{foo foo="foo"}}');
  56. visitor.accept(ast);
  57. equals(
  58. print(ast),
  59. '{{ PATH:foo [] HASH{foo=NUMBER{42}} }}\n'
  60. );
  61. });
  62. it('should treat undefined resonse as identity', function() {
  63. let visitor = new Visitor();
  64. visitor.mutating = true;
  65. let ast = parse('{{foo foo=42}}');
  66. visitor.accept(ast);
  67. equals(
  68. print(ast),
  69. '{{ PATH:foo [] HASH{foo=NUMBER{42}} }}\n'
  70. );
  71. });
  72. it('should remove false responses', function() {
  73. let visitor = new Visitor();
  74. visitor.mutating = true;
  75. visitor.Hash = function() {
  76. return false;
  77. };
  78. let ast = parse('{{foo foo=42}}');
  79. visitor.accept(ast);
  80. equals(print(ast), '{{ PATH:foo [] }}\n');
  81. });
  82. it('should throw when removing required values', function() {
  83. shouldThrow(
  84. function() {
  85. let visitor = new Visitor();
  86. visitor.mutating = true;
  87. visitor.PathExpression = function() {
  88. return false;
  89. };
  90. let ast = parse('{{foo 42}}');
  91. visitor.accept(ast);
  92. },
  93. Exception,
  94. 'MustacheStatement requires path'
  95. );
  96. });
  97. it('should throw when returning non-node responses', function() {
  98. shouldThrow(
  99. function() {
  100. let visitor = new Visitor();
  101. visitor.mutating = true;
  102. visitor.PathExpression = function() {
  103. return {};
  104. };
  105. let ast = parse('{{foo 42}}');
  106. visitor.accept(ast);
  107. },
  108. Exception,
  109. 'Unexpected node type "undefined" found when accepting path on MustacheStatement'
  110. );
  111. });
  112. });
  113. describe('arrays', function() {
  114. it('should replace value', function() {
  115. let visitor = new Visitor();
  116. visitor.mutating = true;
  117. visitor.StringLiteral = function(string) {
  118. return { type: 'NumberLiteral', value: 42, loc: string.locInfo };
  119. };
  120. let ast = parse('{{foo "foo"}}');
  121. visitor.accept(ast);
  122. equals(print(ast), '{{ PATH:foo [NUMBER{42}] }}\n');
  123. });
  124. it('should treat undefined resonse as identity', function() {
  125. let visitor = new Visitor();
  126. visitor.mutating = true;
  127. let ast = parse('{{foo 42}}');
  128. visitor.accept(ast);
  129. equals(print(ast), '{{ PATH:foo [NUMBER{42}] }}\n');
  130. });
  131. it('should remove false responses', function() {
  132. let visitor = new Visitor();
  133. visitor.mutating = true;
  134. visitor.NumberLiteral = function() {
  135. return false;
  136. };
  137. let ast = parse('{{foo 42}}');
  138. visitor.accept(ast);
  139. equals(print(ast), '{{ PATH:foo [] }}\n');
  140. });
  141. });
  142. });
  143. });