NodeUtils.spec.ts 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322
  1. import { IBlockStatementNode } from "../src/interfaces/nodes/IBlockStatementNode";
  2. import { IExpressionStatementNode } from "../src/interfaces/nodes/IExpressionStatementNode";
  3. import { IFunctionDeclarationNode } from "../src/interfaces/nodes/IFunctionDeclarationNode";
  4. import { IIdentifierNode } from "../src/interfaces/nodes/IIdentifierNode";
  5. import { IIfStatementNode } from "../src/interfaces/nodes/IIfStatementNode";
  6. import { ILiteralNode } from "../src/interfaces/nodes/ILiteralNode";
  7. import { INode } from "../src/interfaces/nodes/INode";
  8. import { IProgramNode } from "../src/interfaces/nodes/IProgramNode";
  9. import { IVariableDeclarationNode } from "../src/interfaces/nodes/IVariableDeclarationNode";
  10. import { IVariableDeclaratorNode } from "../src/interfaces/nodes/IVariableDeclaratorNode";
  11. import { NodeType } from "../src/enums/NodeType";
  12. import { NodeMocks } from './mocks/NodeMocks';
  13. import { NodeUtils } from '../src/NodeUtils';
  14. const assert: any = require('chai').assert;
  15. describe('NodeUtils', () => {
  16. describe('addXVerbatimPropertyToLiterals (node: INode): void', () => {
  17. let literalNode: any,
  18. expectedLiteralNode: any;
  19. beforeEach(() => {
  20. literalNode = NodeMocks.getLiteralNode();
  21. delete literalNode['x-verbatim-property'];
  22. expectedLiteralNode = NodeMocks.getLiteralNode();
  23. NodeUtils.addXVerbatimPropertyToLiterals(literalNode);
  24. });
  25. it('should add `x-verbatim-property` to `Literal` node', () => {
  26. assert.deepEqual(literalNode, expectedLiteralNode);
  27. });
  28. });
  29. describe('appendNode (blockScopeBody: INode[], node: INode): void', () => {
  30. let blockStatementNode: IBlockStatementNode,
  31. expectedBlockStatementNode: IBlockStatementNode,
  32. expressionStatementNode: IExpressionStatementNode;
  33. beforeEach(() => {
  34. expressionStatementNode = NodeMocks.getExpressionStatementNode();
  35. blockStatementNode = NodeMocks.getBlockStatementNode();
  36. expectedBlockStatementNode = NodeMocks.getBlockStatementNode([
  37. expressionStatementNode
  38. ]);
  39. NodeUtils.appendNode(blockStatementNode.body, expressionStatementNode);
  40. });
  41. it('should append given node to a `BlockStatement` node body', () => {
  42. assert.deepEqual(blockStatementNode, expectedBlockStatementNode);
  43. });
  44. it('should does not change `BlockStatement` node body if given node is not a valid Node', () => {
  45. assert.doesNotChange(
  46. () => NodeUtils.appendNode(blockStatementNode.body, <INode>null),
  47. blockStatementNode,
  48. 'body'
  49. );
  50. assert.doesNotChange(
  51. () => NodeUtils.appendNode(blockStatementNode.body, <INode>{}),
  52. blockStatementNode,
  53. 'body'
  54. );
  55. });
  56. });
  57. describe('convertCodeToStructure (code: string): INode', () => {
  58. let code: string,
  59. identifierNode: IIdentifierNode,
  60. literalNode: ILiteralNode,
  61. programNode: IProgramNode,
  62. variableDeclarationNode: IVariableDeclarationNode,
  63. variableDeclaratorNode: IVariableDeclaratorNode;
  64. beforeEach(() => {
  65. code = `
  66. var abc = 'cde';
  67. `;
  68. identifierNode = NodeMocks.getIdentifierNode('abc');
  69. literalNode = NodeMocks.getLiteralNode('cde');
  70. variableDeclaratorNode = NodeMocks.getVariableDeclaratorNode(identifierNode, literalNode);
  71. variableDeclarationNode = NodeMocks.getVariableDeclarationNode([
  72. variableDeclaratorNode
  73. ]);
  74. programNode = NodeMocks.getProgramNode([
  75. variableDeclarationNode
  76. ]);
  77. programNode['parentNode'] = programNode;
  78. variableDeclarationNode['parentNode'] = programNode;
  79. variableDeclaratorNode['parentNode'] = variableDeclarationNode;
  80. identifierNode['parentNode'] = variableDeclaratorNode;
  81. literalNode['parentNode'] = variableDeclaratorNode;
  82. });
  83. xit('should convert code to `INode` structure', () => {
  84. assert.deepEqual(NodeUtils.convertCodeToStructure(code), variableDeclarationNode);
  85. });
  86. });
  87. describe('getBlockStatementNodeByIndex (node: INode, index: number = 0): INode', () => {
  88. let blockStatementNode: IBlockStatementNode,
  89. expressionStatementNode1: IExpressionStatementNode,
  90. expressionStatementNode2: IExpressionStatementNode;
  91. beforeEach(() => {
  92. expressionStatementNode1 = NodeMocks.getExpressionStatementNode();
  93. expressionStatementNode2 = NodeMocks.getExpressionStatementNode();
  94. blockStatementNode = NodeMocks.getBlockStatementNode([
  95. expressionStatementNode1,
  96. expressionStatementNode2
  97. ]);
  98. });
  99. it('should return block-statement child node of given node if that node has block-statement', () => {
  100. assert.deepEqual(NodeUtils.getBlockStatementNodeByIndex(blockStatementNode), expressionStatementNode1);
  101. assert.deepEqual(NodeUtils.getBlockStatementNodeByIndex(blockStatementNode, 1), expressionStatementNode2);
  102. });
  103. it('should throw a `ReferenceError` if index is out of boundaries', () => {
  104. assert.throws(() => NodeUtils.getBlockStatementNodeByIndex(blockStatementNode, 2), ReferenceError);
  105. });
  106. it('should throw a `TypeError` if node have no a block-statement', () => {
  107. assert.throws(() => NodeUtils.getBlockStatementNodeByIndex(expressionStatementNode1, 1), TypeError);
  108. });
  109. });
  110. describe('getBlockScopeOfNode (node: INode, depth: number = 0): TNodeWithBlockStatement', () => {
  111. let functionDeclarationBlockStatementNode: IBlockStatementNode,
  112. ifStatementBlockStatementNode1: IBlockStatementNode,
  113. ifStatementBlockStatementNode2: IBlockStatementNode,
  114. ifStatementNode1: IIfStatementNode,
  115. ifStatementNode2: IIfStatementNode,
  116. expressionStatementNode1: IExpressionStatementNode,
  117. expressionStatementNode2: IExpressionStatementNode,
  118. expressionStatementNode3: IExpressionStatementNode,
  119. functionDeclarationNode: IFunctionDeclarationNode,
  120. programNode: IProgramNode;
  121. beforeEach(() => {
  122. expressionStatementNode1 = NodeMocks.getExpressionStatementNode();
  123. expressionStatementNode2 = NodeMocks.getExpressionStatementNode();
  124. expressionStatementNode3 = NodeMocks.getExpressionStatementNode();
  125. ifStatementBlockStatementNode2 = NodeMocks.getBlockStatementNode([
  126. expressionStatementNode1,
  127. expressionStatementNode2
  128. ]);
  129. ifStatementNode2 = NodeMocks.getIfStatementNode(ifStatementBlockStatementNode2);
  130. ifStatementBlockStatementNode1 = NodeMocks.getBlockStatementNode([
  131. ifStatementNode2
  132. ]);
  133. ifStatementNode1 = NodeMocks.getIfStatementNode(ifStatementBlockStatementNode1);
  134. functionDeclarationBlockStatementNode = NodeMocks.getBlockStatementNode([
  135. expressionStatementNode3,
  136. ifStatementNode1
  137. ]);
  138. functionDeclarationNode = NodeMocks.getFunctionDeclarationNode('test', functionDeclarationBlockStatementNode);
  139. programNode = NodeMocks.getProgramNode([
  140. functionDeclarationNode
  141. ]);
  142. programNode['parentNode'] = programNode;
  143. functionDeclarationNode['parentNode'] = programNode;
  144. functionDeclarationBlockStatementNode['parentNode'] = functionDeclarationNode;
  145. expressionStatementNode3['parentNode'] = functionDeclarationBlockStatementNode;
  146. ifStatementNode1['parentNode'] = functionDeclarationBlockStatementNode;
  147. ifStatementBlockStatementNode1['parentNode'] = ifStatementNode1;
  148. ifStatementNode2['parentNode'] = ifStatementBlockStatementNode1;
  149. ifStatementBlockStatementNode2['parentNode'] = ifStatementNode2;
  150. expressionStatementNode1['parentNode'] = ifStatementBlockStatementNode2;
  151. });
  152. it('should return block-scope node for given node', () => {
  153. assert.deepEqual(NodeUtils.getBlockScopeOfNode(expressionStatementNode3), functionDeclarationBlockStatementNode);
  154. assert.deepEqual(NodeUtils.getBlockScopeOfNode(expressionStatementNode3, 1), programNode);
  155. assert.deepEqual(NodeUtils.getBlockScopeOfNode(functionDeclarationNode), programNode);
  156. assert.deepEqual(NodeUtils.getBlockScopeOfNode(functionDeclarationBlockStatementNode), programNode);
  157. assert.deepEqual(NodeUtils.getBlockScopeOfNode(programNode), programNode);
  158. assert.deepEqual(NodeUtils.getBlockScopeOfNode(expressionStatementNode1), functionDeclarationBlockStatementNode);
  159. });
  160. it('should throw a `ReferenceError` if node has no `parentNode` property', () => {
  161. assert.throws(() => NodeUtils.getBlockScopeOfNode(expressionStatementNode2), ReferenceError);
  162. });
  163. });
  164. describe('insertNodeAtIndex (blockScopeBody: INode[], node: INode, index: number): void', () => {
  165. let blockStatementNode: IBlockStatementNode,
  166. expectedBlockStatementNode: IBlockStatementNode,
  167. expressionStatementNode1: IExpressionStatementNode,
  168. expressionStatementNode2: IExpressionStatementNode;
  169. beforeEach(() => {
  170. expressionStatementNode1 = NodeMocks.getExpressionStatementNode();
  171. expressionStatementNode2 = NodeMocks.getExpressionStatementNode();
  172. blockStatementNode = NodeMocks.getBlockStatementNode([
  173. expressionStatementNode1
  174. ]);
  175. expectedBlockStatementNode = NodeMocks.getBlockStatementNode([
  176. expressionStatementNode1,
  177. expressionStatementNode1
  178. ]);
  179. NodeUtils.insertNodeAtIndex(blockStatementNode.body, expressionStatementNode2, 1);
  180. });
  181. it('should insert given node in `BlockStatement` node body at index', () => {
  182. assert.deepEqual(blockStatementNode, expectedBlockStatementNode);
  183. });
  184. it('should does not change `BlockStatement` node body if given node is not a valid Node', () => {
  185. assert.doesNotChange(
  186. () => NodeUtils.insertNodeAtIndex(blockStatementNode.body, <INode>null, 1),
  187. blockStatementNode,
  188. 'body'
  189. );
  190. assert.doesNotChange(
  191. () => NodeUtils.insertNodeAtIndex(blockStatementNode.body, <INode>{}, 1),
  192. blockStatementNode,
  193. 'body'
  194. );
  195. });
  196. });
  197. describe('parentize (node: INode): void', () => {
  198. let ifStatementNode: IIfStatementNode,
  199. ifStatementBlockStatementNode: IBlockStatementNode,
  200. expressionStatementNode1: IExpressionStatementNode,
  201. expressionStatementNode2: IExpressionStatementNode,
  202. programNode: IProgramNode;
  203. beforeEach(() => {
  204. expressionStatementNode1 = NodeMocks.getExpressionStatementNode();
  205. expressionStatementNode2 = NodeMocks.getExpressionStatementNode();
  206. ifStatementBlockStatementNode = NodeMocks.getBlockStatementNode([
  207. expressionStatementNode1,
  208. expressionStatementNode2
  209. ]);
  210. ifStatementNode = NodeMocks.getIfStatementNode(ifStatementBlockStatementNode);
  211. programNode = NodeMocks.getProgramNode([
  212. ifStatementNode
  213. ]);
  214. NodeUtils.parentize(ifStatementNode);
  215. });
  216. it('should parentize given AST-tree', () => {
  217. assert.deepEqual(ifStatementNode['parentNode'], programNode);
  218. assert.deepEqual(ifStatementBlockStatementNode['parentNode'], ifStatementNode);
  219. assert.deepEqual(expressionStatementNode1['parentNode'], ifStatementBlockStatementNode);
  220. assert.deepEqual(expressionStatementNode2['parentNode'], ifStatementBlockStatementNode);
  221. });
  222. });
  223. describe('prependNode (blockScopeBody: INode[], node: INode): void', () => {
  224. let blockStatementNode: IBlockStatementNode,
  225. expectedBlockStatementNode: IBlockStatementNode,
  226. expressionStatementNode1: IExpressionStatementNode,
  227. expressionStatementNode2: IExpressionStatementNode;
  228. beforeEach(() => {
  229. expressionStatementNode1 = NodeMocks.getExpressionStatementNode();
  230. expressionStatementNode2 = NodeMocks.getExpressionStatementNode();
  231. blockStatementNode = NodeMocks.getBlockStatementNode([
  232. expressionStatementNode1
  233. ]);
  234. expectedBlockStatementNode = NodeMocks.getBlockStatementNode([
  235. expressionStatementNode2,
  236. expressionStatementNode1
  237. ]);
  238. NodeUtils.prependNode(blockStatementNode.body, expressionStatementNode2);
  239. });
  240. it('should prepend given node to a `BlockStatement` node body', () => {
  241. assert.deepEqual(blockStatementNode, expectedBlockStatementNode);
  242. });
  243. it('should does not change `BlockStatement` node body if given node is not a valid Node', () => {
  244. assert.doesNotChange(
  245. () => NodeUtils.prependNode(blockStatementNode.body, <INode>null),
  246. blockStatementNode,
  247. 'body'
  248. );
  249. assert.doesNotChange(
  250. () => NodeUtils.prependNode(blockStatementNode.body, <INode>{}),
  251. blockStatementNode,
  252. 'body'
  253. );
  254. });
  255. });
  256. });