NodeUtils.spec.ts 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  1. import { IBlockStatementNode } from "../src/interfaces/nodes/IBlockStatementNode";
  2. import { IFunctionDeclarationNode } from "../src/interfaces/nodes/IFunctionDeclarationNode";
  3. import { IIdentifierNode } from "../src/interfaces/nodes/IIdentifierNode";
  4. import { ILiteralNode } from "../src/interfaces/nodes/ILiteralNode";
  5. import { INode } from "../src/interfaces/nodes/INode";
  6. import { IProgramNode } from "../src/interfaces/nodes/IProgramNode";
  7. import { NodeType } from "../src/enums/NodeType";
  8. import { NodeUtils } from '../src/NodeUtils';
  9. let assert: any = require('chai').assert;
  10. function getProgramNode (bodyNodes: INode[] = []): IProgramNode {
  11. return {
  12. type: NodeType.Program,
  13. body: bodyNodes
  14. };
  15. }
  16. function getBlockStatementNode (bodyNodes: INode[] = []): IBlockStatementNode {
  17. return {
  18. type: NodeType.BlockStatement,
  19. body: bodyNodes
  20. };
  21. }
  22. function getFunctionDeclarationNode (blockStatementNode: IBlockStatementNode): IFunctionDeclarationNode {
  23. return {
  24. type: NodeType.FunctionDeclaration,
  25. id: {
  26. type: NodeType.Identifier,
  27. name: 'test'
  28. },
  29. params: [],
  30. body: blockStatementNode,
  31. generator: false,
  32. expression: false
  33. };
  34. }
  35. function getIdentifierNode (): IIdentifierNode {
  36. return {
  37. type: NodeType.Identifier,
  38. name: 'identifier',
  39. };
  40. }
  41. function getLiteralNode (): ILiteralNode {
  42. return {
  43. type: NodeType.Literal,
  44. value: 'string',
  45. raw: `'string'`,
  46. 'x-verbatim-property': `'string'`
  47. };
  48. }
  49. describe('NodeUtils', () => {
  50. describe('addXVerbatimPropertyToLiterals (node: INode): void', () => {
  51. let literalNode: any,
  52. expectedLiteralNode: any;
  53. beforeEach(() => {
  54. literalNode = getLiteralNode();
  55. expectedLiteralNode = Object.assign({}, literalNode);
  56. expectedLiteralNode['x-verbatim-property'] = `'string'`;
  57. NodeUtils.addXVerbatimPropertyToLiterals(literalNode)
  58. });
  59. it('should add `x-verbatim-property` to `Literal` node', () => {
  60. assert.deepEqual(literalNode, expectedLiteralNode);
  61. });
  62. });
  63. describe('appendNode (blockScopeBody: INode[], node: INode): void', () => {
  64. let blockStatementNode: IBlockStatementNode,
  65. expectedBlockStatementNode: IBlockStatementNode,
  66. identifierNode: IIdentifierNode;
  67. beforeEach(() => {
  68. identifierNode = getIdentifierNode();
  69. blockStatementNode = getBlockStatementNode();
  70. expectedBlockStatementNode = Object.assign({}, blockStatementNode);
  71. expectedBlockStatementNode.body.push(identifierNode);
  72. NodeUtils.appendNode(blockStatementNode.body, identifierNode)
  73. });
  74. it('should append given node to a `BlockStatement` node body', () => {
  75. assert.deepEqual(blockStatementNode, expectedBlockStatementNode);
  76. });
  77. });
  78. describe('getBlockStatementNodeByIndex (node: INode, index: number = 0): INode', () => {
  79. let blockStatementNode: IBlockStatementNode,
  80. identifierNode: IIdentifierNode,
  81. literalNode: ILiteralNode;
  82. beforeEach(() => {
  83. identifierNode = getIdentifierNode();
  84. literalNode = getLiteralNode();
  85. blockStatementNode = getBlockStatementNode([
  86. identifierNode,
  87. literalNode
  88. ]);
  89. });
  90. it('should return block-statement child node of given node if that node has block-statement', () => {
  91. assert.deepEqual(NodeUtils.getBlockStatementNodeByIndex(blockStatementNode), identifierNode);
  92. assert.deepEqual(NodeUtils.getBlockStatementNodeByIndex(blockStatementNode, 1), literalNode);
  93. });
  94. it('should throw a `ReferenceError` if index is out of boundaries', () => {
  95. assert.throws(function () {
  96. return NodeUtils.getBlockStatementNodeByIndex(blockStatementNode, 2);
  97. }, ReferenceError);
  98. });
  99. it('should throw a `TypeError` if node have no a block-statement', () => {
  100. assert.throws(function () {
  101. NodeUtils.getBlockStatementNodeByIndex(identifierNode, 1)
  102. }, TypeError);
  103. });
  104. });
  105. describe('getBlockScopeOfNode (node: INode, depth: number = 0): TNodeWithBlockStatement', () => {
  106. let blockStatementNode: IBlockStatementNode,
  107. identifierNode: IIdentifierNode,
  108. functionDeclarationNode: IFunctionDeclarationNode,
  109. literalNode: ILiteralNode,
  110. programNode: IProgramNode;
  111. beforeEach(() => {
  112. identifierNode = getIdentifierNode();
  113. literalNode = getLiteralNode();
  114. blockStatementNode = getBlockStatementNode([
  115. identifierNode,
  116. literalNode
  117. ]);
  118. functionDeclarationNode = getFunctionDeclarationNode(blockStatementNode);
  119. programNode = getProgramNode([
  120. functionDeclarationNode
  121. ]);
  122. programNode['parentNode'] = programNode;
  123. functionDeclarationNode['parentNode'] = programNode;
  124. blockStatementNode['parentNode'] = functionDeclarationNode;
  125. identifierNode['parentNode'] = blockStatementNode;
  126. });
  127. it('should return block-scope node for given node', () => {
  128. assert.deepEqual(NodeUtils.getBlockScopeOfNode(identifierNode), blockStatementNode);
  129. assert.deepEqual(NodeUtils.getBlockScopeOfNode(identifierNode, 1), programNode);
  130. assert.deepEqual(NodeUtils.getBlockScopeOfNode(functionDeclarationNode), programNode);
  131. assert.deepEqual(NodeUtils.getBlockScopeOfNode(blockStatementNode), programNode);
  132. assert.deepEqual(NodeUtils.getBlockScopeOfNode(programNode), programNode);
  133. });
  134. it('should throw a `ReferenceError` if node has no `parentNode` property', () => {
  135. assert.throws(function () {
  136. return NodeUtils.getBlockScopeOfNode(literalNode);
  137. }, ReferenceError);
  138. });
  139. });
  140. describe('insertNodeAtIndex (blockScopeBody: INode[], node: INode, index: number): void', () => {
  141. let blockStatementNode: IBlockStatementNode,
  142. expectedBlockStatementNode: IBlockStatementNode,
  143. identifierNode: IIdentifierNode,
  144. literalNode: ILiteralNode;
  145. beforeEach(() => {
  146. identifierNode = getIdentifierNode();
  147. literalNode = getLiteralNode();
  148. blockStatementNode = getBlockStatementNode([
  149. identifierNode
  150. ]);
  151. expectedBlockStatementNode = Object.assign({}, blockStatementNode);
  152. expectedBlockStatementNode['body'].push(literalNode);
  153. NodeUtils.insertNodeAtIndex(blockStatementNode.body, literalNode, 1);
  154. });
  155. it('should insert given node in block-scope body at index', () => {
  156. assert.deepEqual(blockStatementNode, expectedBlockStatementNode);
  157. });
  158. });
  159. describe('parentize (node: INode): void', () => {
  160. let blockStatementNode: IBlockStatementNode,
  161. identifierNode: IIdentifierNode,
  162. literalNode: ILiteralNode,
  163. programNode: IProgramNode;
  164. beforeEach(() => {
  165. identifierNode = getIdentifierNode();
  166. literalNode = getLiteralNode();
  167. blockStatementNode = getBlockStatementNode([
  168. identifierNode,
  169. literalNode
  170. ]);
  171. programNode = getProgramNode([
  172. blockStatementNode
  173. ]);
  174. NodeUtils.parentize(blockStatementNode);
  175. });
  176. it('should parentize given AST-tree', () => {
  177. assert.deepEqual(blockStatementNode['parentNode'], programNode);
  178. assert.deepEqual(identifierNode['parentNode'], blockStatementNode);
  179. assert.deepEqual(literalNode['parentNode'], blockStatementNode);
  180. });
  181. });
  182. describe('prependNode (blockScopeBody: INode[], node: INode): void', () => {
  183. let blockStatementNode: IBlockStatementNode,
  184. expectedBlockStatementNode: IBlockStatementNode,
  185. identifierNode: IIdentifierNode,
  186. literalNode: ILiteralNode;
  187. beforeEach(() => {
  188. identifierNode = getIdentifierNode();
  189. literalNode = getLiteralNode();
  190. blockStatementNode = getBlockStatementNode([
  191. identifierNode
  192. ]);
  193. expectedBlockStatementNode = Object.assign({}, blockStatementNode);
  194. expectedBlockStatementNode['body'].unshift(literalNode);
  195. NodeUtils.prependNode(blockStatementNode.body, literalNode)
  196. });
  197. it('should prepend given node to a `BlockStatement` node body', () => {
  198. assert.deepEqual(blockStatementNode, expectedBlockStatementNode);
  199. });
  200. });
  201. });