NodeUtils.spec.ts 15 KB

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