tm1npm 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (451) hide show
  1. package/.env.example +16 -0
  2. package/.eslintrc.js +28 -0
  3. package/.github/ISSUE_TEMPLATE/bug_report.md +36 -0
  4. package/.github/ISSUE_TEMPLATE/feature_request.md +20 -0
  5. package/.github/ISSUE_TEMPLATE/question.md +24 -0
  6. package/.github/workflows/publish-npm.yml +53 -0
  7. package/.github/workflows/test-on-tag.yml +172 -0
  8. package/DEVELOPMENT_GUIDE.md +587 -0
  9. package/LICENSE +21 -0
  10. package/README.md +580 -0
  11. package/jest.ci.config.js +83 -0
  12. package/jest.config.js +68 -0
  13. package/lib/exceptions/TM1Exception.d.ts +17 -0
  14. package/lib/exceptions/TM1Exception.d.ts.map +1 -0
  15. package/lib/exceptions/TM1Exception.js +36 -0
  16. package/lib/exceptions/TM1RestException.d.ts +10 -0
  17. package/lib/exceptions/TM1RestException.d.ts.map +1 -0
  18. package/lib/exceptions/TM1RestException.js +17 -0
  19. package/lib/exceptions/TM1TimeoutException.d.ts +9 -0
  20. package/lib/exceptions/TM1TimeoutException.d.ts.map +1 -0
  21. package/lib/exceptions/TM1TimeoutException.js +16 -0
  22. package/lib/index.d.ts +41 -0
  23. package/lib/index.d.ts.map +1 -0
  24. package/lib/index.js +132 -0
  25. package/lib/objects/Annotation.d.ts +36 -0
  26. package/lib/objects/Annotation.d.ts.map +1 -0
  27. package/lib/objects/Annotation.js +134 -0
  28. package/lib/objects/Application.d.ts +67 -0
  29. package/lib/objects/Application.d.ts.map +1 -0
  30. package/lib/objects/Application.js +125 -0
  31. package/lib/objects/Axis.d.ts +36 -0
  32. package/lib/objects/Axis.d.ts.map +1 -0
  33. package/lib/objects/Axis.js +103 -0
  34. package/lib/objects/Chore.d.ts +43 -0
  35. package/lib/objects/Chore.d.ts.map +1 -0
  36. package/lib/objects/Chore.js +129 -0
  37. package/lib/objects/ChoreFrequency.d.ts +23 -0
  38. package/lib/objects/ChoreFrequency.d.ts.map +1 -0
  39. package/lib/objects/ChoreFrequency.js +61 -0
  40. package/lib/objects/ChoreStartTime.d.ts +15 -0
  41. package/lib/objects/ChoreStartTime.d.ts.map +1 -0
  42. package/lib/objects/ChoreStartTime.js +85 -0
  43. package/lib/objects/ChoreTask.d.ts +28 -0
  44. package/lib/objects/ChoreTask.d.ts.map +1 -0
  45. package/lib/objects/ChoreTask.js +66 -0
  46. package/lib/objects/Cube.d.ts +26 -0
  47. package/lib/objects/Cube.d.ts.map +1 -0
  48. package/lib/objects/Cube.js +109 -0
  49. package/lib/objects/Dimension.d.ts +26 -0
  50. package/lib/objects/Dimension.d.ts.map +1 -0
  51. package/lib/objects/Dimension.js +86 -0
  52. package/lib/objects/Element.d.ts +35 -0
  53. package/lib/objects/Element.d.ts.map +1 -0
  54. package/lib/objects/Element.js +115 -0
  55. package/lib/objects/ElementAttribute.d.ts +28 -0
  56. package/lib/objects/ElementAttribute.d.ts.map +1 -0
  57. package/lib/objects/ElementAttribute.js +97 -0
  58. package/lib/objects/Git.d.ts +21 -0
  59. package/lib/objects/Git.d.ts.map +1 -0
  60. package/lib/objects/Git.js +49 -0
  61. package/lib/objects/GitCommit.d.ts +12 -0
  62. package/lib/objects/GitCommit.d.ts.map +1 -0
  63. package/lib/objects/GitCommit.js +26 -0
  64. package/lib/objects/GitPlan.d.ts +35 -0
  65. package/lib/objects/GitPlan.d.ts.map +1 -0
  66. package/lib/objects/GitPlan.js +78 -0
  67. package/lib/objects/GitRemote.d.ts +12 -0
  68. package/lib/objects/GitRemote.d.ts.map +1 -0
  69. package/lib/objects/GitRemote.js +26 -0
  70. package/lib/objects/Hierarchy.d.ts +47 -0
  71. package/lib/objects/Hierarchy.d.ts.map +1 -0
  72. package/lib/objects/Hierarchy.js +165 -0
  73. package/lib/objects/MDXView.d.ts +19 -0
  74. package/lib/objects/MDXView.d.ts.map +1 -0
  75. package/lib/objects/MDXView.js +67 -0
  76. package/lib/objects/NativeView.d.ts +39 -0
  77. package/lib/objects/NativeView.d.ts.map +1 -0
  78. package/lib/objects/NativeView.js +209 -0
  79. package/lib/objects/Process.d.ts +70 -0
  80. package/lib/objects/Process.d.ts.map +1 -0
  81. package/lib/objects/Process.js +210 -0
  82. package/lib/objects/ProcessDebugBreakpoint.d.ts +60 -0
  83. package/lib/objects/ProcessDebugBreakpoint.d.ts.map +1 -0
  84. package/lib/objects/ProcessDebugBreakpoint.js +168 -0
  85. package/lib/objects/ProcessParameter.d.ts +23 -0
  86. package/lib/objects/ProcessParameter.d.ts.map +1 -0
  87. package/lib/objects/ProcessParameter.js +55 -0
  88. package/lib/objects/ProcessVariable.d.ts +26 -0
  89. package/lib/objects/ProcessVariable.d.ts.map +1 -0
  90. package/lib/objects/ProcessVariable.js +63 -0
  91. package/lib/objects/Rules.d.ts +30 -0
  92. package/lib/objects/Rules.d.ts.map +1 -0
  93. package/lib/objects/Rules.js +103 -0
  94. package/lib/objects/Sandbox.d.ts +21 -0
  95. package/lib/objects/Sandbox.d.ts.map +1 -0
  96. package/lib/objects/Sandbox.js +64 -0
  97. package/lib/objects/Server.d.ts +27 -0
  98. package/lib/objects/Server.d.ts.map +1 -0
  99. package/lib/objects/Server.js +26 -0
  100. package/lib/objects/Subset.d.ts +44 -0
  101. package/lib/objects/Subset.d.ts.map +1 -0
  102. package/lib/objects/Subset.js +222 -0
  103. package/lib/objects/TM1Object.d.ts +8 -0
  104. package/lib/objects/TM1Object.d.ts.map +1 -0
  105. package/lib/objects/TM1Object.js +17 -0
  106. package/lib/objects/TM1Project.d.ts +74 -0
  107. package/lib/objects/TM1Project.d.ts.map +1 -0
  108. package/lib/objects/TM1Project.js +409 -0
  109. package/lib/objects/User.d.ts +42 -0
  110. package/lib/objects/User.d.ts.map +1 -0
  111. package/lib/objects/User.js +157 -0
  112. package/lib/objects/View.d.ts +19 -0
  113. package/lib/objects/View.d.ts.map +1 -0
  114. package/lib/objects/View.js +33 -0
  115. package/lib/objects/index.d.ts +30 -0
  116. package/lib/objects/index.d.ts.map +1 -0
  117. package/lib/objects/index.js +68 -0
  118. package/lib/services/AnnotationService.d.ts +17 -0
  119. package/lib/services/AnnotationService.d.ts.map +1 -0
  120. package/lib/services/AnnotationService.js +91 -0
  121. package/lib/services/ApplicationService.d.ts +21 -0
  122. package/lib/services/ApplicationService.d.ts.map +1 -0
  123. package/lib/services/ApplicationService.js +227 -0
  124. package/lib/services/AuditLogService.d.ts +15 -0
  125. package/lib/services/AuditLogService.d.ts.map +1 -0
  126. package/lib/services/AuditLogService.js +153 -0
  127. package/lib/services/CellService.d.ts +191 -0
  128. package/lib/services/CellService.d.ts.map +1 -0
  129. package/lib/services/CellService.js +597 -0
  130. package/lib/services/ChoreService.d.ts +24 -0
  131. package/lib/services/ChoreService.d.ts.map +1 -0
  132. package/lib/services/ChoreService.js +219 -0
  133. package/lib/services/ConfigurationService.d.ts +18 -0
  134. package/lib/services/ConfigurationService.d.ts.map +1 -0
  135. package/lib/services/ConfigurationService.js +60 -0
  136. package/lib/services/CubeService.d.ts +43 -0
  137. package/lib/services/CubeService.d.ts.map +1 -0
  138. package/lib/services/CubeService.js +296 -0
  139. package/lib/services/DimensionService.d.ts +21 -0
  140. package/lib/services/DimensionService.d.ts.map +1 -0
  141. package/lib/services/DimensionService.js +146 -0
  142. package/lib/services/ElementService.d.ts +132 -0
  143. package/lib/services/ElementService.d.ts.map +1 -0
  144. package/lib/services/ElementService.js +579 -0
  145. package/lib/services/FileService.d.ts +14 -0
  146. package/lib/services/FileService.d.ts.map +1 -0
  147. package/lib/services/FileService.js +65 -0
  148. package/lib/services/GitService.d.ts +23 -0
  149. package/lib/services/GitService.d.ts.map +1 -0
  150. package/lib/services/GitService.js +225 -0
  151. package/lib/services/HierarchyService.d.ts +32 -0
  152. package/lib/services/HierarchyService.d.ts.map +1 -0
  153. package/lib/services/HierarchyService.js +235 -0
  154. package/lib/services/JobService.d.ts +13 -0
  155. package/lib/services/JobService.d.ts.map +1 -0
  156. package/lib/services/JobService.js +83 -0
  157. package/lib/services/LoggerService.d.ts +16 -0
  158. package/lib/services/LoggerService.d.ts.map +1 -0
  159. package/lib/services/LoggerService.js +101 -0
  160. package/lib/services/ManageService.d.ts +47 -0
  161. package/lib/services/ManageService.d.ts.map +1 -0
  162. package/lib/services/ManageService.js +221 -0
  163. package/lib/services/MessageLogService.d.ts +13 -0
  164. package/lib/services/MessageLogService.d.ts.map +1 -0
  165. package/lib/services/MessageLogService.js +175 -0
  166. package/lib/services/MonitoringService.d.ts +29 -0
  167. package/lib/services/MonitoringService.d.ts.map +1 -0
  168. package/lib/services/MonitoringService.js +86 -0
  169. package/lib/services/ObjectService.d.ts +8 -0
  170. package/lib/services/ObjectService.d.ts.map +1 -0
  171. package/lib/services/ObjectService.js +20 -0
  172. package/lib/services/PowerBiService.d.ts +13 -0
  173. package/lib/services/PowerBiService.d.ts.map +1 -0
  174. package/lib/services/PowerBiService.js +52 -0
  175. package/lib/services/ProcessService.d.ts +57 -0
  176. package/lib/services/ProcessService.d.ts.map +1 -0
  177. package/lib/services/ProcessService.js +499 -0
  178. package/lib/services/RestService.d.ts +68 -0
  179. package/lib/services/RestService.d.ts.map +1 -0
  180. package/lib/services/RestService.js +166 -0
  181. package/lib/services/SandboxService.d.ts +28 -0
  182. package/lib/services/SandboxService.d.ts.map +1 -0
  183. package/lib/services/SandboxService.js +197 -0
  184. package/lib/services/SecurityService.d.ts +33 -0
  185. package/lib/services/SecurityService.d.ts.map +1 -0
  186. package/lib/services/SecurityService.js +249 -0
  187. package/lib/services/ServerService.d.ts +55 -0
  188. package/lib/services/ServerService.d.ts.map +1 -0
  189. package/lib/services/ServerService.js +247 -0
  190. package/lib/services/SessionService.d.ts +15 -0
  191. package/lib/services/SessionService.d.ts.map +1 -0
  192. package/lib/services/SessionService.js +68 -0
  193. package/lib/services/SubsetService.d.ts +13 -0
  194. package/lib/services/SubsetService.d.ts.map +1 -0
  195. package/lib/services/SubsetService.js +46 -0
  196. package/lib/services/TM1Service.d.ts +39 -0
  197. package/lib/services/TM1Service.d.ts.map +1 -0
  198. package/lib/services/TM1Service.js +94 -0
  199. package/lib/services/ThreadService.d.ts +15 -0
  200. package/lib/services/ThreadService.d.ts.map +1 -0
  201. package/lib/services/ThreadService.js +104 -0
  202. package/lib/services/TransactionLogService.d.ts +11 -0
  203. package/lib/services/TransactionLogService.d.ts.map +1 -0
  204. package/lib/services/TransactionLogService.js +124 -0
  205. package/lib/services/UserService.d.ts +14 -0
  206. package/lib/services/UserService.d.ts.map +1 -0
  207. package/lib/services/UserService.js +103 -0
  208. package/lib/services/ViewService.d.ts +30 -0
  209. package/lib/services/ViewService.d.ts.map +1 -0
  210. package/lib/services/ViewService.js +331 -0
  211. package/lib/services/index.d.ts +26 -0
  212. package/lib/services/index.d.ts.map +1 -0
  213. package/lib/services/index.js +56 -0
  214. package/lib/tests/100PercentParityCheck.test.d.ts +6 -0
  215. package/lib/tests/100PercentParityCheck.test.d.ts.map +1 -0
  216. package/lib/tests/100PercentParityCheck.test.js +143 -0
  217. package/lib/tests/basic.test.d.ts +6 -0
  218. package/lib/tests/basic.test.d.ts.map +1 -0
  219. package/lib/tests/basic.test.js +52 -0
  220. package/lib/tests/cellService.test.d.ts +6 -0
  221. package/lib/tests/cellService.test.d.ts.map +1 -0
  222. package/lib/tests/cellService.test.js +311 -0
  223. package/lib/tests/ciSetup.d.ts +6 -0
  224. package/lib/tests/ciSetup.d.ts.map +1 -0
  225. package/lib/tests/ciSetup.js +23 -0
  226. package/lib/tests/comprehensive.service.test.d.ts +6 -0
  227. package/lib/tests/comprehensive.service.test.d.ts.map +1 -0
  228. package/lib/tests/comprehensive.service.test.js +507 -0
  229. package/lib/tests/connection.test.d.ts +6 -0
  230. package/lib/tests/connection.test.d.ts.map +1 -0
  231. package/lib/tests/connection.test.js +89 -0
  232. package/lib/tests/cubeService.test.d.ts +6 -0
  233. package/lib/tests/cubeService.test.d.ts.map +1 -0
  234. package/lib/tests/cubeService.test.js +368 -0
  235. package/lib/tests/dimensionService.comprehensive.test.d.ts +7 -0
  236. package/lib/tests/dimensionService.comprehensive.test.d.ts.map +1 -0
  237. package/lib/tests/dimensionService.comprehensive.test.js +614 -0
  238. package/lib/tests/dimensionService.test.d.ts +6 -0
  239. package/lib/tests/dimensionService.test.d.ts.map +1 -0
  240. package/lib/tests/dimensionService.test.js +293 -0
  241. package/lib/tests/edgeCases.test.d.ts +6 -0
  242. package/lib/tests/edgeCases.test.d.ts.map +1 -0
  243. package/lib/tests/edgeCases.test.js +301 -0
  244. package/lib/tests/elementService.comprehensive.test.d.ts +7 -0
  245. package/lib/tests/elementService.comprehensive.test.d.ts.map +1 -0
  246. package/lib/tests/elementService.comprehensive.test.js +846 -0
  247. package/lib/tests/elementService.test.d.ts +6 -0
  248. package/lib/tests/elementService.test.d.ts.map +1 -0
  249. package/lib/tests/elementService.test.js +350 -0
  250. package/lib/tests/enhancedCellService.test.d.ts +2 -0
  251. package/lib/tests/enhancedCellService.test.d.ts.map +1 -0
  252. package/lib/tests/enhancedCellService.test.js +152 -0
  253. package/lib/tests/enhancedCubeService.test.d.ts +2 -0
  254. package/lib/tests/enhancedCubeService.test.d.ts.map +1 -0
  255. package/lib/tests/enhancedCubeService.test.js +246 -0
  256. package/lib/tests/enhancedElementService.test.d.ts +2 -0
  257. package/lib/tests/enhancedElementService.test.d.ts.map +1 -0
  258. package/lib/tests/enhancedElementService.test.js +199 -0
  259. package/lib/tests/enhancedViewService.test.d.ts +2 -0
  260. package/lib/tests/enhancedViewService.test.d.ts.map +1 -0
  261. package/lib/tests/enhancedViewService.test.js +260 -0
  262. package/lib/tests/errorHandling.test.d.ts +6 -0
  263. package/lib/tests/errorHandling.test.d.ts.map +1 -0
  264. package/lib/tests/errorHandling.test.js +227 -0
  265. package/lib/tests/exceptions.test.d.ts +7 -0
  266. package/lib/tests/exceptions.test.d.ts.map +1 -0
  267. package/lib/tests/exceptions.test.js +257 -0
  268. package/lib/tests/hierarchyService.test.d.ts +6 -0
  269. package/lib/tests/hierarchyService.test.d.ts.map +1 -0
  270. package/lib/tests/hierarchyService.test.js +294 -0
  271. package/lib/tests/index.test.d.ts +6 -0
  272. package/lib/tests/index.test.d.ts.map +1 -0
  273. package/lib/tests/index.test.js +346 -0
  274. package/lib/tests/integration.test.d.ts +6 -0
  275. package/lib/tests/integration.test.d.ts.map +1 -0
  276. package/lib/tests/integration.test.js +302 -0
  277. package/lib/tests/integrationTests.test.d.ts +2 -0
  278. package/lib/tests/integrationTests.test.d.ts.map +1 -0
  279. package/lib/tests/integrationTests.test.js +252 -0
  280. package/lib/tests/mdx.advanced.test.d.ts +6 -0
  281. package/lib/tests/mdx.advanced.test.d.ts.map +1 -0
  282. package/lib/tests/mdx.advanced.test.js +437 -0
  283. package/lib/tests/objects.improved.test.d.ts +7 -0
  284. package/lib/tests/objects.improved.test.d.ts.map +1 -0
  285. package/lib/tests/objects.improved.test.js +302 -0
  286. package/lib/tests/performance.test.d.ts +6 -0
  287. package/lib/tests/performance.test.d.ts.map +1 -0
  288. package/lib/tests/performance.test.js +264 -0
  289. package/lib/tests/processService.comprehensive.test.d.ts +7 -0
  290. package/lib/tests/processService.comprehensive.test.d.ts.map +1 -0
  291. package/lib/tests/processService.comprehensive.test.js +656 -0
  292. package/lib/tests/processService.test.d.ts +6 -0
  293. package/lib/tests/processService.test.d.ts.map +1 -0
  294. package/lib/tests/processService.test.js +322 -0
  295. package/lib/tests/restService.test.d.ts +6 -0
  296. package/lib/tests/restService.test.d.ts.map +1 -0
  297. package/lib/tests/restService.test.js +177 -0
  298. package/lib/tests/security.advanced.test.d.ts +6 -0
  299. package/lib/tests/security.advanced.test.d.ts.map +1 -0
  300. package/lib/tests/security.advanced.test.js +407 -0
  301. package/lib/tests/security.test.d.ts +6 -0
  302. package/lib/tests/security.test.d.ts.map +1 -0
  303. package/lib/tests/security.test.js +204 -0
  304. package/lib/tests/securityService.comprehensive.test.d.ts +7 -0
  305. package/lib/tests/securityService.comprehensive.test.d.ts.map +1 -0
  306. package/lib/tests/securityService.comprehensive.test.js +457 -0
  307. package/lib/tests/setup.d.ts +4 -0
  308. package/lib/tests/setup.d.ts.map +1 -0
  309. package/lib/tests/setup.js +40 -0
  310. package/lib/tests/simpleCoverage.test.d.ts +6 -0
  311. package/lib/tests/simpleCoverage.test.d.ts.map +1 -0
  312. package/lib/tests/simpleCoverage.test.js +236 -0
  313. package/lib/tests/stress.performance.test.d.ts +6 -0
  314. package/lib/tests/stress.performance.test.d.ts.map +1 -0
  315. package/lib/tests/stress.performance.test.js +423 -0
  316. package/lib/tests/subsetService.test.d.ts +6 -0
  317. package/lib/tests/subsetService.test.d.ts.map +1 -0
  318. package/lib/tests/subsetService.test.js +271 -0
  319. package/lib/tests/testConfig.d.ts +18 -0
  320. package/lib/tests/testConfig.d.ts.map +1 -0
  321. package/lib/tests/testConfig.js +38 -0
  322. package/lib/tests/testUtils.d.ts +9 -0
  323. package/lib/tests/testUtils.d.ts.map +1 -0
  324. package/lib/tests/testUtils.js +100 -0
  325. package/lib/tests/tm1Service.test.d.ts +7 -0
  326. package/lib/tests/tm1Service.test.d.ts.map +1 -0
  327. package/lib/tests/tm1Service.test.js +290 -0
  328. package/lib/tests/viewService.test.d.ts +6 -0
  329. package/lib/tests/viewService.test.d.ts.map +1 -0
  330. package/lib/tests/viewService.test.js +240 -0
  331. package/lib/utils/Utils.d.ts +90 -0
  332. package/lib/utils/Utils.d.ts.map +1 -0
  333. package/lib/utils/Utils.js +379 -0
  334. package/package.json +81 -0
  335. package/run-all-tests.js +296 -0
  336. package/src/exceptions/TM1Exception.ts +38 -0
  337. package/src/exceptions/TM1RestException.ts +17 -0
  338. package/src/exceptions/TM1TimeoutException.ts +15 -0
  339. package/src/index.ts +94 -0
  340. package/src/objects/Annotation.ts +194 -0
  341. package/src/objects/Application.ts +146 -0
  342. package/src/objects/Axis.ts +149 -0
  343. package/src/objects/Chore.ts +174 -0
  344. package/src/objects/ChoreFrequency.ts +83 -0
  345. package/src/objects/ChoreStartTime.ts +111 -0
  346. package/src/objects/ChoreTask.ts +92 -0
  347. package/src/objects/Cube.ts +125 -0
  348. package/src/objects/Dimension.ts +107 -0
  349. package/src/objects/Element.ts +153 -0
  350. package/src/objects/ElementAttribute.ts +115 -0
  351. package/src/objects/Git.ts +86 -0
  352. package/src/objects/GitCommit.ts +31 -0
  353. package/src/objects/GitPlan.ts +121 -0
  354. package/src/objects/GitRemote.ts +31 -0
  355. package/src/objects/Hierarchy.ts +229 -0
  356. package/src/objects/MDXView.ts +91 -0
  357. package/src/objects/NativeView.ts +268 -0
  358. package/src/objects/Process.ts +320 -0
  359. package/src/objects/ProcessDebugBreakpoint.ts +239 -0
  360. package/src/objects/ProcessParameter.ts +76 -0
  361. package/src/objects/ProcessVariable.ts +89 -0
  362. package/src/objects/Rules.ts +117 -0
  363. package/src/objects/Sandbox.ts +90 -0
  364. package/src/objects/Server.ts +45 -0
  365. package/src/objects/Subset.ts +323 -0
  366. package/src/objects/TM1Object.ts +17 -0
  367. package/src/objects/TM1Project.ts +587 -0
  368. package/src/objects/User.ts +198 -0
  369. package/src/objects/View.ts +43 -0
  370. package/src/objects/index.ts +36 -0
  371. package/src/services/AnnotationService.ts +107 -0
  372. package/src/services/ApplicationService.ts +279 -0
  373. package/src/services/AuditLogService.ts +172 -0
  374. package/src/services/CellService.ts +814 -0
  375. package/src/services/ChoreService.ts +219 -0
  376. package/src/services/ConfigurationService.ts +69 -0
  377. package/src/services/CubeService.ts +338 -0
  378. package/src/services/DimensionService.ts +168 -0
  379. package/src/services/ElementService.ts +966 -0
  380. package/src/services/FileService.ts +67 -0
  381. package/src/services/GitService.ts +324 -0
  382. package/src/services/HierarchyService.ts +284 -0
  383. package/src/services/JobService.ts +59 -0
  384. package/src/services/LoggerService.ts +118 -0
  385. package/src/services/ManageService.ts +322 -0
  386. package/src/services/MessageLogService.ts +211 -0
  387. package/src/services/MonitoringService.ts +105 -0
  388. package/src/services/ObjectService.ts +21 -0
  389. package/src/services/PowerBiService.ts +85 -0
  390. package/src/services/ProcessService.ts +589 -0
  391. package/src/services/RestService.ts +224 -0
  392. package/src/services/SandboxService.ts +217 -0
  393. package/src/services/SecurityService.ts +284 -0
  394. package/src/services/ServerService.ts +313 -0
  395. package/src/services/SessionService.ts +81 -0
  396. package/src/services/SubsetService.ts +52 -0
  397. package/src/services/TM1Service.ts +133 -0
  398. package/src/services/ThreadService.ts +83 -0
  399. package/src/services/TransactionLogService.ts +148 -0
  400. package/src/services/UserService.ts +77 -0
  401. package/src/services/ViewService.ts +398 -0
  402. package/src/services/index.ts +28 -0
  403. package/src/tests/100PercentParityCheck.test.ts +166 -0
  404. package/src/tests/basic.test.ts +59 -0
  405. package/src/tests/cellService.test.ts +405 -0
  406. package/src/tests/ciSetup.ts +26 -0
  407. package/src/tests/comprehensive.service.test.ts +653 -0
  408. package/src/tests/config.ini.template +23 -0
  409. package/src/tests/connection.test.ts +90 -0
  410. package/src/tests/cubeService.test.ts +458 -0
  411. package/src/tests/dimensionService.comprehensive.test.ts +786 -0
  412. package/src/tests/dimensionService.test.ts +373 -0
  413. package/src/tests/edgeCases.test.ts +358 -0
  414. package/src/tests/elementService.comprehensive.test.ts +1190 -0
  415. package/src/tests/elementService.test.ts +472 -0
  416. package/src/tests/enhancedCellService.test.ts +237 -0
  417. package/src/tests/enhancedCubeService.test.ts +384 -0
  418. package/src/tests/enhancedElementService.test.ts +301 -0
  419. package/src/tests/enhancedViewService.test.ts +373 -0
  420. package/src/tests/errorHandling.test.ts +264 -0
  421. package/src/tests/exceptions.test.ts +313 -0
  422. package/src/tests/hierarchyService.test.ts +386 -0
  423. package/src/tests/index.test.ts +376 -0
  424. package/src/tests/integration.test.ts +333 -0
  425. package/src/tests/integrationTests.test.ts +302 -0
  426. package/src/tests/mdx.advanced.test.ts +513 -0
  427. package/src/tests/objects.improved.test.ts +385 -0
  428. package/src/tests/performance.test.ts +314 -0
  429. package/src/tests/processService.comprehensive.test.ts +933 -0
  430. package/src/tests/processService.test.ts +409 -0
  431. package/src/tests/restService.test.ts +218 -0
  432. package/src/tests/security.advanced.test.ts +464 -0
  433. package/src/tests/security.test.ts +233 -0
  434. package/src/tests/securityService.comprehensive.test.ts +582 -0
  435. package/src/tests/setup.ts +42 -0
  436. package/src/tests/simpleCoverage.test.ts +287 -0
  437. package/src/tests/stress.performance.test.ts +531 -0
  438. package/src/tests/subsetService.test.ts +350 -0
  439. package/src/tests/testConfig.ts +53 -0
  440. package/src/tests/testUtils.ts +94 -0
  441. package/src/tests/tm1Service.test.ts +361 -0
  442. package/src/tests/viewService.test.ts +324 -0
  443. package/src/utils/Utils.ts +395 -0
  444. package/tests/README.md +57 -0
  445. package/tests/connection/test-connection.ts +86 -0
  446. package/tests/edge-cases/edge-cases-test.ts +244 -0
  447. package/tests/integration/working-test.ts +193 -0
  448. package/tests/performance/performance-test.ts +133 -0
  449. package/tests/run-all-tests.sh +106 -0
  450. package/tests/security/security-test.ts +103 -0
  451. package/tsconfig.json +20 -0
@@ -0,0 +1,1190 @@
1
+ /**
2
+ * Comprehensive ElementService Tests
3
+ * Target: Achieve 80%+ coverage for ElementService (currently 48%)
4
+ * Testing all element operations including CRUD, hierarchy management, attributes, and advanced features
5
+ */
6
+
7
+ import { ElementService, MDXDrillMethod } from '../services/ElementService';
8
+ import { RestService } from '../services/RestService';
9
+ import { Element, ElementType } from '../objects/Element';
10
+ import { ElementAttribute } from '../objects/ElementAttribute';
11
+ import { CaseAndSpaceInsensitiveDict } from '../utils/Utils';
12
+
13
+ // Mock dependencies
14
+ jest.mock('../objects/Element');
15
+ jest.mock('../objects/ElementAttribute');
16
+
17
+ describe('ElementService - Comprehensive Tests', () => {
18
+ let elementService: ElementService;
19
+ let mockRestService: jest.Mocked<RestService>;
20
+
21
+ const mockResponse = (data: any) => ({
22
+ data: data,
23
+ status: 200,
24
+ statusText: 'OK',
25
+ headers: {},
26
+ config: { headers: {} }
27
+ } as any);
28
+
29
+ const mockElement = {
30
+ name: 'TestElement',
31
+ elementType: ElementType.NUMERIC,
32
+ body: {
33
+ Name: 'TestElement',
34
+ Type: 'Numeric'
35
+ }
36
+ } as any;
37
+
38
+ const mockElementAttribute = {
39
+ name: 'TestAttribute',
40
+ attributeType: 'String',
41
+ body: {
42
+ Name: 'TestAttribute',
43
+ Type: 'String'
44
+ }
45
+ } as any;
46
+
47
+ beforeEach(() => {
48
+ mockRestService = {
49
+ get: jest.fn(),
50
+ post: jest.fn(),
51
+ patch: jest.fn(),
52
+ put: jest.fn(),
53
+ delete: jest.fn()
54
+ } as any;
55
+
56
+ elementService = new ElementService(mockRestService);
57
+
58
+ // Mock Element.fromDict
59
+ (Element as any).fromDict = jest.fn().mockReturnValue(mockElement);
60
+
61
+ // Mock ElementAttribute.fromDict
62
+ (ElementAttribute as any).fromDict = jest.fn().mockReturnValue(mockElementAttribute);
63
+ });
64
+
65
+ afterEach(() => {
66
+ jest.clearAllMocks();
67
+ });
68
+
69
+ describe('Constructor and Initialization', () => {
70
+ test('should initialize ElementService properly', () => {
71
+ expect(elementService).toBeDefined();
72
+ expect(elementService).toBeInstanceOf(ElementService);
73
+ });
74
+
75
+ test('should extend ObjectService', () => {
76
+ expect(elementService).toBeInstanceOf(ElementService);
77
+ });
78
+ });
79
+
80
+ describe('Element CRUD Operations', () => {
81
+ test('should get element by dimension, hierarchy, and name', async () => {
82
+ const elementData = {
83
+ Name: 'TestElement',
84
+ Type: 'Numeric'
85
+ };
86
+ mockRestService.get.mockResolvedValue(mockResponse(elementData));
87
+
88
+ const result = await elementService.get('TestDim', 'TestHierarchy', 'TestElement');
89
+
90
+ expect(Element.fromDict).toHaveBeenCalledWith(elementData);
91
+ expect(mockRestService.get).toHaveBeenCalledWith(
92
+ "/Dimensions('TestDim')/Hierarchies('TestHierarchy')/Elements('TestElement')?$expand=*"
93
+ );
94
+ expect(result).toEqual(mockElement);
95
+ });
96
+
97
+ test('should create element', async () => {
98
+ mockRestService.post.mockResolvedValue(mockResponse({}));
99
+
100
+ const result = await elementService.create('TestDim', 'TestHierarchy', mockElement);
101
+
102
+ expect(result).toBeDefined();
103
+ expect(mockRestService.post).toHaveBeenCalledWith(
104
+ "/Dimensions('TestDim')/Hierarchies('TestHierarchy')/Elements",
105
+ mockElement.body
106
+ );
107
+ });
108
+
109
+ test('should update element', async () => {
110
+ mockRestService.patch.mockResolvedValue(mockResponse({}));
111
+
112
+ const result = await elementService.update('TestDim', 'TestHierarchy', mockElement);
113
+
114
+ expect(result).toBeDefined();
115
+ expect(mockRestService.patch).toHaveBeenCalledWith(
116
+ "/Dimensions('TestDim')/Hierarchies('TestHierarchy')/Elements('TestElement')",
117
+ mockElement.body
118
+ );
119
+ });
120
+
121
+ test('should delete element', async () => {
122
+ mockRestService.delete.mockResolvedValue(mockResponse({}));
123
+
124
+ const result = await elementService.delete('TestDim', 'TestHierarchy', 'TestElement');
125
+
126
+ expect(result).toBeDefined();
127
+ expect(mockRestService.delete).toHaveBeenCalledWith(
128
+ "/Dimensions('TestDim')/Hierarchies('TestHierarchy')/Elements('TestElement')"
129
+ );
130
+ });
131
+
132
+ test('should check if element exists', async () => {
133
+ mockRestService.get.mockResolvedValue(mockResponse({}));
134
+
135
+ const result = await elementService.exists('TestDim', 'TestHierarchy', 'TestElement');
136
+
137
+ expect(result).toBe(true);
138
+ });
139
+
140
+ test('should return false when element does not exist', async () => {
141
+ mockRestService.get.mockRejectedValue(new Error('Element not found'));
142
+
143
+ const result = await elementService.exists('TestDim', 'TestHierarchy', 'NonExistent');
144
+
145
+ expect(result).toBe(false);
146
+ });
147
+
148
+ test('should update or create element - update existing', async () => {
149
+ jest.spyOn(elementService, 'exists').mockResolvedValue(true);
150
+ jest.spyOn(elementService, 'update').mockResolvedValue(mockResponse({}));
151
+
152
+ const result = await elementService.updateOrCreate('TestDim', 'TestHierarchy', mockElement);
153
+
154
+ expect(elementService.exists).toHaveBeenCalledWith('TestDim', 'TestHierarchy', 'TestElement');
155
+ expect(elementService.update).toHaveBeenCalledWith('TestDim', 'TestHierarchy', mockElement);
156
+ expect(result).toBeDefined();
157
+ });
158
+
159
+ test('should update or create element - create new', async () => {
160
+ jest.spyOn(elementService, 'exists').mockResolvedValue(false);
161
+ jest.spyOn(elementService, 'create').mockResolvedValue(mockResponse({}));
162
+
163
+ const result = await elementService.updateOrCreate('TestDim', 'TestHierarchy', mockElement);
164
+
165
+ expect(elementService.exists).toHaveBeenCalledWith('TestDim', 'TestHierarchy', 'TestElement');
166
+ expect(elementService.create).toHaveBeenCalledWith('TestDim', 'TestHierarchy', mockElement);
167
+ expect(result).toBeDefined();
168
+ });
169
+ });
170
+
171
+ describe('Element Retrieval Operations', () => {
172
+ test('should get element names', async () => {
173
+ const elementsData = {
174
+ value: [
175
+ { Name: 'Element1' },
176
+ { Name: 'Element2' },
177
+ { Name: 'ConsolElement' }
178
+ ]
179
+ };
180
+ mockRestService.get.mockResolvedValue(mockResponse(elementsData));
181
+
182
+ const result = await elementService.getNames('TestDim', 'TestHierarchy');
183
+
184
+ expect(result).toEqual(['Element1', 'Element2', 'ConsolElement']);
185
+ expect(mockRestService.get).toHaveBeenCalledWith(
186
+ "/Dimensions('TestDim')/Hierarchies('TestHierarchy')/Elements?$select=Name"
187
+ );
188
+ });
189
+
190
+ test('should get element names with default hierarchy', async () => {
191
+ const elementsData = {
192
+ value: [
193
+ { Name: 'Element1' },
194
+ { Name: 'Element2' }
195
+ ]
196
+ };
197
+ mockRestService.get.mockResolvedValue(mockResponse(elementsData));
198
+
199
+ const result = await elementService.getNames('TestDim');
200
+
201
+ expect(result).toEqual(['Element1', 'Element2']);
202
+ expect(mockRestService.get).toHaveBeenCalledWith(
203
+ "/Dimensions('TestDim')/Hierarchies('TestDim')/Elements?$select=Name"
204
+ );
205
+ });
206
+
207
+ test('should get element names excluding consolidated elements', async () => {
208
+ const elementsData = {
209
+ value: [
210
+ { Name: 'Element1' },
211
+ { Name: 'Element2' }
212
+ ]
213
+ };
214
+ mockRestService.get.mockResolvedValue(mockResponse(elementsData));
215
+
216
+ const result = await elementService.getNames('TestDim', 'TestHierarchy', true);
217
+
218
+ expect(result).toEqual(['Element1', 'Element2']);
219
+ expect(mockRestService.get).toHaveBeenCalledWith(
220
+ "/Dimensions('TestDim')/Hierarchies('TestHierarchy')/Elements?$select=Name&$filter=Type ne 'Consolidated'"
221
+ );
222
+ });
223
+
224
+ test('should get all elements', async () => {
225
+ const elementsData = {
226
+ value: [
227
+ { Name: 'Element1', Type: 'Numeric' },
228
+ { Name: 'Element2', Type: 'String' }
229
+ ]
230
+ };
231
+ mockRestService.get.mockResolvedValue(mockResponse(elementsData));
232
+
233
+ const result = await elementService.getElements('TestDim', 'TestHierarchy');
234
+
235
+ expect(result).toHaveLength(2);
236
+ expect(Element.fromDict).toHaveBeenCalledTimes(2);
237
+ expect(mockRestService.get).toHaveBeenCalledWith(
238
+ "/Dimensions('TestDim')/Hierarchies('TestHierarchy')/Elements?$expand=*"
239
+ );
240
+ });
241
+
242
+ test('should get leaf element names', async () => {
243
+ const leafElementsData = {
244
+ value: [
245
+ { Name: 'NumericLeaf' },
246
+ { Name: 'StringLeaf' }
247
+ ]
248
+ };
249
+ mockRestService.get.mockResolvedValue(mockResponse(leafElementsData));
250
+
251
+ const result = await elementService.getLeafElementNames('TestDim', 'TestHierarchy');
252
+
253
+ expect(result).toEqual(['NumericLeaf', 'StringLeaf']);
254
+ expect(mockRestService.get).toHaveBeenCalledWith(
255
+ "/Dimensions('TestDim')/Hierarchies('TestHierarchy')/Elements?$select=Name&$filter=Type eq 'Numeric' or Type eq 'String'"
256
+ );
257
+ });
258
+
259
+ test('should get consolidated element names', async () => {
260
+ const consolidatedData = {
261
+ value: [
262
+ { Name: 'ConsolElement1' },
263
+ { Name: 'ConsolElement2' }
264
+ ]
265
+ };
266
+ mockRestService.get.mockResolvedValue(mockResponse(consolidatedData));
267
+
268
+ const result = await elementService.getConsolidatedElementNames('TestDim', 'TestHierarchy');
269
+
270
+ expect(result).toEqual(['ConsolElement1', 'ConsolElement2']);
271
+ expect(mockRestService.get).toHaveBeenCalledWith(
272
+ "/Dimensions('TestDim')/Hierarchies('TestHierarchy')/Elements?$select=Name&$filter=Type eq 'Consolidated'"
273
+ );
274
+ });
275
+
276
+ test('should get numeric element names', async () => {
277
+ const numericData = {
278
+ value: [
279
+ { Name: 'NumericElement1' },
280
+ { Name: 'NumericElement2' }
281
+ ]
282
+ };
283
+ mockRestService.get.mockResolvedValue(mockResponse(numericData));
284
+
285
+ const result = await elementService.getNumericElementNames('TestDim', 'TestHierarchy');
286
+
287
+ expect(result).toEqual(['NumericElement1', 'NumericElement2']);
288
+ expect(mockRestService.get).toHaveBeenCalledWith(
289
+ "/Dimensions('TestDim')/Hierarchies('TestHierarchy')/Elements?$select=Name&$filter=Type eq 'Numeric'"
290
+ );
291
+ });
292
+
293
+ test('should get string element names', async () => {
294
+ const stringData = {
295
+ value: [
296
+ { Name: 'StringElement1' },
297
+ { Name: 'StringElement2' }
298
+ ]
299
+ };
300
+ mockRestService.get.mockResolvedValue(mockResponse(stringData));
301
+
302
+ const result = await elementService.getStringElementNames('TestDim', 'TestHierarchy');
303
+
304
+ expect(result).toEqual(['StringElement1', 'StringElement2']);
305
+ expect(mockRestService.get).toHaveBeenCalledWith(
306
+ "/Dimensions('TestDim')/Hierarchies('TestHierarchy')/Elements?$select=Name&$filter=Type eq 'String'"
307
+ );
308
+ });
309
+
310
+ test('should get element types', async () => {
311
+ const typesData = {
312
+ value: [
313
+ { Name: 'Element1', Type: 'Numeric' },
314
+ { Name: 'Element2', Type: 'String' },
315
+ { Name: 'Element3', Type: 'Consolidated' }
316
+ ]
317
+ };
318
+ mockRestService.get.mockResolvedValue(mockResponse(typesData));
319
+
320
+ const result = await elementService.getElementTypes('TestDim', 'TestHierarchy');
321
+
322
+ expect(result).toBeInstanceOf(CaseAndSpaceInsensitiveDict);
323
+ expect(mockRestService.get).toHaveBeenCalledWith(
324
+ "/Dimensions('TestDim')/Hierarchies('TestHierarchy')/Elements?$select=Name,Type"
325
+ );
326
+ });
327
+
328
+ test('should get elements count', async () => {
329
+ mockRestService.get.mockResolvedValue(mockResponse('15'));
330
+
331
+ const result = await elementService.getElementsCount('TestDim', 'TestHierarchy');
332
+
333
+ expect(result).toBe(15);
334
+ expect(mockRestService.get).toHaveBeenCalledWith(
335
+ "/Dimensions('TestDim')/Hierarchies('TestHierarchy')/Elements/$count"
336
+ );
337
+ });
338
+
339
+ test('should get elements count excluding consolidated elements', async () => {
340
+ mockRestService.get.mockResolvedValue(mockResponse('10'));
341
+
342
+ const result = await elementService.getElementsCount('TestDim', 'TestHierarchy', true);
343
+
344
+ expect(result).toBe(10);
345
+ expect(mockRestService.get).toHaveBeenCalledWith(
346
+ "/Dimensions('TestDim')/Hierarchies('TestHierarchy')/Elements/$count?$filter=Type ne 'Consolidated'"
347
+ );
348
+ });
349
+ });
350
+
351
+ describe('Hierarchy Relationship Operations', () => {
352
+ test('should get element parents', async () => {
353
+ const parentsData = {
354
+ value: [
355
+ { Name: 'Parent1' },
356
+ { Name: 'Parent2' }
357
+ ]
358
+ };
359
+ mockRestService.get.mockResolvedValue(mockResponse(parentsData));
360
+
361
+ const result = await elementService.getParents('TestDim', 'TestHierarchy', 'ChildElement');
362
+
363
+ expect(result).toEqual(['Parent1', 'Parent2']);
364
+ expect(mockRestService.get).toHaveBeenCalledWith(
365
+ "/Dimensions('TestDim')/Hierarchies('TestHierarchy')/Elements('ChildElement')/Parents?$select=Name"
366
+ );
367
+ });
368
+
369
+ test('should get element children', async () => {
370
+ const childrenData = {
371
+ value: [
372
+ { Name: 'Child1' },
373
+ { Name: 'Child2' }
374
+ ]
375
+ };
376
+ mockRestService.get.mockResolvedValue(mockResponse(childrenData));
377
+
378
+ const result = await elementService.getChildren('TestDim', 'TestHierarchy', 'ParentElement');
379
+
380
+ expect(result).toEqual(['Child1', 'Child2']);
381
+ expect(mockRestService.get).toHaveBeenCalledWith(
382
+ "/Dimensions('TestDim')/Hierarchies('TestHierarchy')/Elements('ParentElement')/Components?$select=Name"
383
+ );
384
+ });
385
+
386
+ test('should get element ancestors', async () => {
387
+ // Mock parent chain: Element -> Parent1 -> GrandParent1
388
+ mockRestService.get
389
+ .mockResolvedValueOnce(mockResponse({ value: [{ Name: 'Parent1' }] })) // First call - direct parents
390
+ .mockResolvedValueOnce(mockResponse({ value: [{ Name: 'GrandParent1' }] })) // Second call - grandparents
391
+ .mockResolvedValueOnce(mockResponse({ value: [] })); // Third call - no more ancestors
392
+
393
+ const result = await elementService.getAncestors('TestDim', 'TestHierarchy', 'Element');
394
+
395
+ expect(result).toEqual(['Parent1', 'GrandParent1']);
396
+ expect(mockRestService.get).toHaveBeenCalledTimes(3);
397
+ });
398
+
399
+ test('should get element descendants', async () => {
400
+ // Mock child chain: Element -> Child1 -> GrandChild1
401
+ mockRestService.get
402
+ .mockResolvedValueOnce(mockResponse({ value: [{ Name: 'Child1' }] })) // First call - direct children
403
+ .mockResolvedValueOnce(mockResponse({ value: [{ Name: 'GrandChild1' }] })) // Second call - grandchildren
404
+ .mockResolvedValueOnce(mockResponse({ value: [] })); // Third call - no more descendants
405
+
406
+ const result = await elementService.getDescendants('TestDim', 'TestHierarchy', 'Element');
407
+
408
+ expect(result).toEqual(['Child1', 'GrandChild1']);
409
+ expect(mockRestService.get).toHaveBeenCalledTimes(3);
410
+ });
411
+
412
+ test('should handle circular references in ancestors', async () => {
413
+ // Mock circular reference: Element -> Parent1 -> Element
414
+ mockRestService.get
415
+ .mockResolvedValueOnce(mockResponse({ value: [{ Name: 'Parent1' }] }))
416
+ .mockResolvedValueOnce(mockResponse({ value: [{ Name: 'Element' }] }));
417
+
418
+ const result = await elementService.getAncestors('TestDim', 'TestHierarchy', 'Element');
419
+
420
+ // Should include both Parent1 and Element (the circular reference is handled by processed set)
421
+ expect(result).toEqual(['Parent1', 'Element']);
422
+ });
423
+
424
+ test('should handle circular references in descendants', async () => {
425
+ // Mock circular reference: Element -> Child1 -> Element
426
+ mockRestService.get
427
+ .mockResolvedValueOnce(mockResponse({ value: [{ Name: 'Child1' }] }))
428
+ .mockResolvedValueOnce(mockResponse({ value: [{ Name: 'Element' }] }));
429
+
430
+ const result = await elementService.getDescendants('TestDim', 'TestHierarchy', 'Element');
431
+
432
+ // Should include both Child1 and Element (the circular reference is handled by processed set)
433
+ expect(result).toEqual(['Child1', 'Element']);
434
+ });
435
+ });
436
+
437
+ describe('Edge Management Operations', () => {
438
+ test('should add edges', async () => {
439
+ mockRestService.post.mockResolvedValue(mockResponse({}));
440
+
441
+ const edges = [
442
+ { parent: 'Parent1', child: 'Child1', weight: 1.5 },
443
+ { parent: 'Parent1', child: 'Child2', weight: 2.0 },
444
+ { parent: 'Parent2', child: 'Child1' } // No weight specified
445
+ ];
446
+
447
+ await elementService.addEdges('TestDim', 'TestHierarchy', edges);
448
+
449
+ expect(mockRestService.post).toHaveBeenCalledTimes(3);
450
+ expect(mockRestService.post).toHaveBeenNthCalledWith(1,
451
+ "/Dimensions('TestDim')/Hierarchies('TestHierarchy')/Elements('Parent1')/Components",
452
+ { Name: 'Child1', Weight: 1.5 }
453
+ );
454
+ expect(mockRestService.post).toHaveBeenNthCalledWith(2,
455
+ "/Dimensions('TestDim')/Hierarchies('TestHierarchy')/Elements('Parent1')/Components",
456
+ { Name: 'Child2', Weight: 2.0 }
457
+ );
458
+ expect(mockRestService.post).toHaveBeenNthCalledWith(3,
459
+ "/Dimensions('TestDim')/Hierarchies('TestHierarchy')/Elements('Parent2')/Components",
460
+ { Name: 'Child1', Weight: 1 }
461
+ );
462
+ });
463
+
464
+ test('should delete edges using REST API', async () => {
465
+ mockRestService.delete.mockResolvedValue(mockResponse({}));
466
+
467
+ const edges = [
468
+ { parent: 'Parent1', child: 'Child1' },
469
+ { parent: 'Parent2', child: 'Child2' }
470
+ ];
471
+
472
+ await elementService.deleteEdges('TestDim', 'TestHierarchy', edges, false);
473
+
474
+ expect(mockRestService.delete).toHaveBeenCalledTimes(2);
475
+ expect(mockRestService.delete).toHaveBeenNthCalledWith(1,
476
+ "/Dimensions('TestDim')/Hierarchies('TestHierarchy')/Elements('Parent1')/Components('Child1')"
477
+ );
478
+ expect(mockRestService.delete).toHaveBeenNthCalledWith(2,
479
+ "/Dimensions('TestDim')/Hierarchies('TestHierarchy')/Elements('Parent2')/Components('Child2')"
480
+ );
481
+ });
482
+
483
+ test('should delete edges using TI', async () => {
484
+ mockRestService.post.mockResolvedValue(mockResponse({}));
485
+
486
+ const edges = [
487
+ { parent: 'Parent1', child: 'Child1' },
488
+ { parent: 'Parent2', child: 'Child2' }
489
+ ];
490
+
491
+ await elementService.deleteEdges('TestDim', 'TestHierarchy', edges, true);
492
+
493
+ expect(mockRestService.post).toHaveBeenCalledWith(
494
+ "/ExecuteProcessWithReturn",
495
+ expect.objectContaining({
496
+ Name: expect.stringContaining('tm1npm_delete_edges_'),
497
+ PrologProcedure: expect.stringContaining("HierarchyElementComponentDelete('TestDim','TestHierarchy','Parent1','Child1');")
498
+ })
499
+ );
500
+ });
501
+
502
+ test('should get edges under consolidation', async () => {
503
+ const componentsData = {
504
+ value: [
505
+ { Name: 'Child1', Weight: 1.5 },
506
+ { Name: 'Child2', Weight: 2.0 },
507
+ { Name: 'Child3' } // No weight
508
+ ]
509
+ };
510
+ mockRestService.get.mockResolvedValue(mockResponse(componentsData));
511
+
512
+ const result = await elementService.getEdgesUnderConsolidation('TestDim', 'TestHierarchy', 'Parent1');
513
+
514
+ expect(result).toEqual([
515
+ { parent: 'Parent1', child: 'Child1', weight: 1.5 },
516
+ { parent: 'Parent1', child: 'Child2', weight: 2.0 },
517
+ { parent: 'Parent1', child: 'Child3', weight: 1 }
518
+ ]);
519
+ });
520
+ });
521
+
522
+ describe('Element Bulk Operations', () => {
523
+ test('should add multiple elements', async () => {
524
+ mockRestService.post.mockResolvedValue(mockResponse({}));
525
+
526
+ const elements = [mockElement, mockElement, mockElement];
527
+
528
+ await elementService.addElements('TestDim', 'TestHierarchy', elements);
529
+
530
+ expect(mockRestService.post).toHaveBeenCalledTimes(3);
531
+ });
532
+
533
+ test('should delete multiple elements using REST API', async () => {
534
+ mockRestService.delete.mockResolvedValue(mockResponse({}));
535
+
536
+ const elementNames = ['Element1', 'Element2', 'Element3'];
537
+
538
+ await elementService.deleteElements('TestDim', 'TestHierarchy', elementNames, false);
539
+
540
+ expect(mockRestService.delete).toHaveBeenCalledTimes(3);
541
+ });
542
+
543
+ test('should delete multiple elements using TI', async () => {
544
+ mockRestService.post.mockResolvedValue(mockResponse({}));
545
+
546
+ const elementNames = ['Element1', 'Element2', 'Element3'];
547
+
548
+ await elementService.deleteElements('TestDim', 'TestHierarchy', elementNames, true);
549
+
550
+ expect(mockRestService.post).toHaveBeenCalledWith(
551
+ "/ExecuteProcessWithReturn",
552
+ expect.objectContaining({
553
+ Name: expect.stringContaining('tm1npm_delete_elements_'),
554
+ PrologProcedure: expect.stringContaining("HierarchyElementDelete('TestDim','TestHierarchy','Element1');")
555
+ })
556
+ );
557
+ });
558
+
559
+ test('should handle empty element list for deletion', async () => {
560
+ await elementService.deleteElements('TestDim', 'TestHierarchy', [], true);
561
+
562
+ expect(mockRestService.post).not.toHaveBeenCalled();
563
+ });
564
+ });
565
+
566
+ describe('Element Attribute Operations', () => {
567
+ test('should get element attributes', async () => {
568
+ const attributesData = {
569
+ value: [
570
+ { Name: 'Attribute1', Type: 'String' },
571
+ { Name: 'Attribute2', Type: 'Numeric' }
572
+ ]
573
+ };
574
+ mockRestService.get.mockResolvedValue(mockResponse(attributesData));
575
+
576
+ const result = await elementService.getElementAttributes('TestDim', 'TestHierarchy');
577
+
578
+ expect(result).toHaveLength(2);
579
+ expect(ElementAttribute.fromDict).toHaveBeenCalledTimes(2);
580
+ expect(mockRestService.get).toHaveBeenCalledWith(
581
+ "/Dimensions('TestDim')/Hierarchies('TestHierarchy')/ElementAttributes"
582
+ );
583
+ });
584
+
585
+ test('should get element attribute names', async () => {
586
+ const attributeNamesData = {
587
+ value: [
588
+ { Name: 'Attribute1' },
589
+ { Name: 'Attribute2' }
590
+ ]
591
+ };
592
+ mockRestService.get.mockResolvedValue(mockResponse(attributeNamesData));
593
+
594
+ const result = await elementService.getElementAttributeNames('TestDim', 'TestHierarchy');
595
+
596
+ expect(result).toEqual(['Attribute1', 'Attribute2']);
597
+ expect(mockRestService.get).toHaveBeenCalledWith(
598
+ "/Dimensions('TestDim')/Hierarchies('TestHierarchy')/ElementAttributes?$select=Name"
599
+ );
600
+ });
601
+
602
+ test('should create element attribute', async () => {
603
+ mockRestService.post.mockResolvedValue(mockResponse({}));
604
+
605
+ const result = await elementService.createElementAttribute('TestDim', 'TestHierarchy', mockElementAttribute);
606
+
607
+ expect(result).toBeDefined();
608
+ expect(mockRestService.post).toHaveBeenCalledWith(
609
+ "/Dimensions('TestDim')/Hierarchies('TestHierarchy')/ElementAttributes",
610
+ mockElementAttribute.body
611
+ );
612
+ });
613
+
614
+ test('should delete element attribute', async () => {
615
+ mockRestService.delete.mockResolvedValue(mockResponse({}));
616
+
617
+ const result = await elementService.deleteElementAttribute('TestDim', 'TestHierarchy', 'TestAttribute');
618
+
619
+ expect(result).toBeDefined();
620
+ expect(mockRestService.delete).toHaveBeenCalledWith(
621
+ "/Dimensions('TestDim')/Hierarchies('TestHierarchy')/ElementAttributes('TestAttribute')"
622
+ );
623
+ });
624
+
625
+ test('should update element attribute value', async () => {
626
+ mockRestService.patch.mockResolvedValue(mockResponse({}));
627
+
628
+ const result = await elementService.updateElementAttribute(
629
+ 'TestDim', 'TestHierarchy', 'TestElement', 'TestAttribute', 'NewValue'
630
+ );
631
+
632
+ expect(result).toBeDefined();
633
+ expect(mockRestService.patch).toHaveBeenCalledWith(
634
+ "/Dimensions('TestDim')/Hierarchies('TestHierarchy')/Elements('TestElement')/Attributes('TestAttribute')",
635
+ { Value: 'NewValue' }
636
+ );
637
+ });
638
+
639
+ test('should get attribute values for multiple elements', async () => {
640
+ mockRestService.get
641
+ .mockResolvedValueOnce(mockResponse({ Value: 'Value1' })) // Element1 attribute
642
+ .mockResolvedValueOnce(mockResponse({ Value: 'Value2' })) // Element2 attribute
643
+ .mockRejectedValueOnce(new Error('Not found')); // Element3 attribute missing
644
+
645
+ const result = await elementService.getAttributeOfElements(
646
+ 'TestDim', 'TestHierarchy', ['Element1', 'Element2', 'Element3'], 'TestAttribute'
647
+ );
648
+
649
+ expect(result).toEqual({
650
+ Element1: 'Value1',
651
+ Element2: 'Value2',
652
+ Element3: null
653
+ });
654
+ expect(mockRestService.get).toHaveBeenCalledTimes(3);
655
+ });
656
+
657
+ test('should get alias element attributes', async () => {
658
+ const aliasAttributesData = {
659
+ value: [
660
+ { Name: 'Caption', Type: 'Alias' },
661
+ { Name: 'DisplayName', Type: 'Alias' }
662
+ ]
663
+ };
664
+ mockRestService.get.mockResolvedValue(mockResponse(aliasAttributesData));
665
+
666
+ const result = await elementService.getAliasElementAttributes('TestDim', 'TestHierarchy');
667
+
668
+ expect(result).toHaveLength(2);
669
+ expect(mockRestService.get).toHaveBeenCalledWith(
670
+ "/Dimensions('TestDim')/Hierarchies('TestHierarchy')/ElementAttributes?$filter=Type eq 'Alias'"
671
+ );
672
+ });
673
+ });
674
+
675
+ describe('MDX and Query Operations', () => {
676
+ test('should execute set MDX', async () => {
677
+ const mdxResult = {
678
+ value: ['Element1', 'Element2', 'Element3']
679
+ };
680
+ mockRestService.post.mockResolvedValue(mockResponse(mdxResult));
681
+
682
+ const mdx = "{[TestDim].[TestHierarchy].[All]}";
683
+ const result = await elementService.executeSetMdx('TestDim', 'TestHierarchy', mdx);
684
+
685
+ expect(result).toEqual(['Element1', 'Element2', 'Element3']);
686
+ expect(mockRestService.post).toHaveBeenCalledWith(
687
+ '/ExecuteMDXSetExpression',
688
+ {
689
+ MDX: mdx,
690
+ Dimension: 'TestDim',
691
+ Hierarchy: 'TestHierarchy'
692
+ }
693
+ );
694
+ });
695
+
696
+ test('should execute set MDX for element names', async () => {
697
+ const mdxResult = {
698
+ value: ['Element1', 'Element2']
699
+ };
700
+ mockRestService.post.mockResolvedValue(mockResponse(mdxResult));
701
+
702
+ const mdx = "DESCENDANTS({[TestDim].[TestHierarchy].[Total]}, 1, LEAVES)";
703
+ const result = await elementService.executeSetMdxElementNames('TestDim', 'TestHierarchy', mdx);
704
+
705
+ expect(result).toEqual(['Element1', 'Element2']);
706
+ });
707
+
708
+ test('should handle empty MDX results', async () => {
709
+ mockRestService.post.mockResolvedValue(mockResponse({}));
710
+
711
+ const result = await elementService.executeSetMdx('TestDim', 'TestHierarchy', '{[Empty]}');
712
+
713
+ expect(result).toEqual([]);
714
+ });
715
+ });
716
+
717
+ describe('Advanced Element Operations', () => {
718
+ test('should get leaf elements', async () => {
719
+ jest.spyOn(elementService, 'getElements').mockResolvedValue([mockElement]);
720
+
721
+ const result = await elementService.getLeafElements('TestDim', 'TestHierarchy');
722
+
723
+ expect(result).toEqual([mockElement]);
724
+ expect(elementService.getElements).toHaveBeenCalledWith('TestDim', 'TestHierarchy', true);
725
+ });
726
+
727
+ test('should get consolidated elements', async () => {
728
+ const consolidatedData = {
729
+ value: [
730
+ { Name: 'Consol1', Type: 'Consolidated' },
731
+ { Name: 'Consol2', Type: 'Consolidated' }
732
+ ]
733
+ };
734
+ mockRestService.get.mockResolvedValue(mockResponse(consolidatedData));
735
+
736
+ const result = await elementService.getConsolidatedElements('TestDim', 'TestHierarchy');
737
+
738
+ expect(result).toHaveLength(2);
739
+ expect(mockRestService.get).toHaveBeenCalledWith(
740
+ "/Dimensions('TestDim')/Hierarchies('TestHierarchy')/Elements?$expand=*&$filter=Type eq 'Consolidated'"
741
+ );
742
+ });
743
+
744
+ test('should get elements dataframe', async () => {
745
+ const elementsData = {
746
+ value: [
747
+ { Name: 'Element1', Type: 'Numeric', Attributes: { Caption: 'Elem1' } },
748
+ { Name: 'Element2', Type: 'String', Attributes: { Caption: 'Elem2' } }
749
+ ]
750
+ };
751
+ mockRestService.get.mockResolvedValue(mockResponse(elementsData));
752
+
753
+ const result = await elementService.getElementsDataframe('TestDim', 'TestHierarchy', ['Caption']);
754
+
755
+ expect(result).toEqual([
756
+ ['Name', 'Type', 'Caption'],
757
+ ['Element1', 'Numeric', 'Elem1'],
758
+ ['Element2', 'String', 'Elem2']
759
+ ]);
760
+ });
761
+
762
+ test('should get elements dataframe without attributes', async () => {
763
+ const elementsData = {
764
+ value: [
765
+ { Name: 'Element1', Type: 'Numeric' },
766
+ { Name: 'Element2', Type: 'String' }
767
+ ]
768
+ };
769
+ mockRestService.get.mockResolvedValue(mockResponse(elementsData));
770
+
771
+ const result = await elementService.getElementsDataframe('TestDim', 'TestHierarchy');
772
+
773
+ expect(result).toEqual([
774
+ ['Name', 'Type'],
775
+ ['Element1', 'Numeric'],
776
+ ['Element2', 'String']
777
+ ]);
778
+ });
779
+
780
+ test('should create hierarchy from dataframe', async () => {
781
+ const dataFrame = [
782
+ ['Name', 'Type', 'Parent1', 'Weight1'],
783
+ ['Child1', 'Numeric', 'Parent1', '1.0'],
784
+ ['Child2', 'String', 'Parent1', '2.0'],
785
+ ['Parent1', 'Consolidated', '', '']
786
+ ];
787
+
788
+ jest.spyOn(elementService, 'create').mockResolvedValue(mockResponse({}));
789
+ jest.spyOn(elementService, 'addEdges').mockResolvedValue();
790
+
791
+ await elementService.createHierarchyFromDataframe('TestDim', 'TestHierarchy', dataFrame);
792
+
793
+ expect(elementService.create).toHaveBeenCalledTimes(3);
794
+ expect(elementService.addEdges).toHaveBeenCalledWith('TestDim', 'TestHierarchy', [
795
+ { parent: 'Parent1', child: 'Child1', weight: 1.0 },
796
+ { parent: 'Parent1', child: 'Child2', weight: 2.0 }
797
+ ]);
798
+ });
799
+
800
+ test('should throw error for invalid dataframe structure', async () => {
801
+ const invalidDataFrame = [
802
+ ['InvalidHeader1', 'InvalidHeader2'],
803
+ ['Data1', 'Data2']
804
+ ];
805
+
806
+ await expect(elementService.createHierarchyFromDataframe('TestDim', 'TestHierarchy', invalidDataFrame))
807
+ .rejects.toThrow('DataFrame must contain Name and Type columns');
808
+ });
809
+ });
810
+
811
+ describe('Advanced Features and Parity Functions', () => {
812
+ test('should delete elements using TI method', async () => {
813
+ mockRestService.post
814
+ .mockResolvedValueOnce(mockResponse({})) // Create process
815
+ .mockResolvedValueOnce(mockResponse({})) // Execute process
816
+ .mockResolvedValueOnce(mockResponse({})); // Delete process
817
+
818
+ mockRestService.delete.mockResolvedValue(mockResponse({}));
819
+
820
+ await elementService.deleteElementsUseTi('TestDim', 'TestHierarchy', ['Element1', 'Element2']);
821
+
822
+ expect(mockRestService.post).toHaveBeenCalledTimes(2); // Create and execute
823
+ expect(mockRestService.delete).toHaveBeenCalledTimes(1); // Delete process
824
+ });
825
+
826
+ test('should handle empty element list in TI deletion', async () => {
827
+ await elementService.deleteElementsUseTi('TestDim', 'TestHierarchy', []);
828
+
829
+ expect(mockRestService.post).not.toHaveBeenCalled();
830
+ });
831
+
832
+ test('should delete edges using blob method', async () => {
833
+ mockRestService.post
834
+ .mockResolvedValueOnce(mockResponse({})) // Create process
835
+ .mockResolvedValueOnce(mockResponse({})); // Execute process
836
+
837
+ mockRestService.delete.mockResolvedValue(mockResponse({}));
838
+
839
+ const edges = [
840
+ { parent: 'Parent1', child: 'Child1' },
841
+ { parent: 'Parent2', child: 'Child2' }
842
+ ];
843
+
844
+ await elementService.deleteEdgesUseBlob('TestDim', 'TestHierarchy', edges);
845
+
846
+ expect(mockRestService.post).toHaveBeenCalledTimes(2);
847
+ expect(mockRestService.delete).toHaveBeenCalledTimes(1);
848
+ });
849
+
850
+ test('should get elements by level', async () => {
851
+ const allElements = [
852
+ { name: 'Leaf1', elementType: ElementType.NUMERIC },
853
+ { name: 'Consol1', elementType: ElementType.CONSOLIDATED }
854
+ ];
855
+ jest.spyOn(elementService, 'getElements').mockResolvedValue(allElements as any);
856
+
857
+ const result = await elementService.getElementsByLevel('TestDim', 'TestHierarchy', 1);
858
+
859
+ expect(result).toHaveLength(1);
860
+ expect(result[0].name).toBe('Consol1');
861
+ });
862
+
863
+ test('should get elements filtered by wildcard', async () => {
864
+ const filteredData = {
865
+ value: [
866
+ { Name: 'TestElement1', Type: 'Numeric' },
867
+ { Name: 'TestElement2', Type: 'String' }
868
+ ]
869
+ };
870
+ mockRestService.get.mockResolvedValue(mockResponse(filteredData));
871
+
872
+ const result = await elementService.getElementsFilteredByWildcard('TestDim', 'TestHierarchy', 'Test*');
873
+
874
+ expect(result).toHaveLength(2);
875
+ expect(mockRestService.get).toHaveBeenCalledWith(
876
+ expect.stringContaining("substringof('Test%',Name)")
877
+ );
878
+ });
879
+
880
+ test('should get elements filtered by attribute', async () => {
881
+ const allElements = [
882
+ { name: 'Element1', elementType: ElementType.NUMERIC },
883
+ { name: 'Element2', elementType: ElementType.STRING }
884
+ ];
885
+ jest.spyOn(elementService, 'getElements').mockResolvedValue(allElements as any);
886
+
887
+ mockRestService.get
888
+ .mockResolvedValueOnce(mockResponse({ Value: 'MatchingValue' })) // Element1 matches
889
+ .mockRejectedValueOnce(new Error('Not found')); // Element2 has no attribute
890
+
891
+ const result = await elementService.getElementsFilteredByAttribute(
892
+ 'TestDim', 'TestHierarchy', 'TestAttribute', 'MatchingValue'
893
+ );
894
+
895
+ expect(result).toHaveLength(1);
896
+ expect(result[0].name).toBe('Element1');
897
+ });
898
+
899
+ test('should lock element', async () => {
900
+ mockRestService.post.mockResolvedValue(mockResponse({}));
901
+
902
+ await elementService.elementLock('TestDim', 'TestHierarchy', 'TestElement');
903
+
904
+ expect(mockRestService.post).toHaveBeenCalledWith(
905
+ "/Dimensions('TestDim')/Hierarchies('TestHierarchy')/Elements('TestElement')/tm1.Lock",
906
+ {}
907
+ );
908
+ });
909
+
910
+ test('should unlock element', async () => {
911
+ mockRestService.post.mockResolvedValue(mockResponse({}));
912
+
913
+ await elementService.elementUnlock('TestDim', 'TestHierarchy', 'TestElement');
914
+
915
+ expect(mockRestService.post).toHaveBeenCalledWith(
916
+ "/Dimensions('TestDim')/Hierarchies('TestHierarchy')/Elements('TestElement')/tm1.Unlock",
917
+ {}
918
+ );
919
+ });
920
+
921
+ test('should get levels count', async () => {
922
+ const elements = [
923
+ { name: 'Leaf1', elementType: ElementType.NUMERIC },
924
+ { name: 'Consol1', elementType: ElementType.CONSOLIDATED },
925
+ { name: 'Leaf2', elementType: ElementType.STRING }
926
+ ];
927
+ jest.spyOn(elementService, 'getElements').mockResolvedValue(elements as any);
928
+
929
+ const result = await elementService.getLevelsCount('TestDim', 'TestHierarchy');
930
+
931
+ expect(result).toBe(2); // 1 consolidated level + 1 leaf level
932
+ });
933
+
934
+ test('should get level names', async () => {
935
+ jest.spyOn(elementService, 'getLevelsCount').mockResolvedValue(3);
936
+
937
+ const result = await elementService.getLevelNames('TestDim', 'TestHierarchy');
938
+
939
+ expect(result).toEqual(['Level 0', 'Level 1', 'Level 2']);
940
+ });
941
+
942
+ test('should get leaves under consolidation using MDX', async () => {
943
+ jest.spyOn(elementService, 'executeSetMdxElementNames').mockResolvedValue(['Leaf1', 'Leaf2']);
944
+ jest.spyOn(elementService, 'get')
945
+ .mockResolvedValueOnce(mockElement)
946
+ .mockResolvedValueOnce(mockElement);
947
+
948
+ const result = await elementService.getLeavesUnderConsolidation('TestDim', 'TestHierarchy', 'Consol1');
949
+
950
+ expect(result).toHaveLength(2);
951
+ expect(elementService.executeSetMdxElementNames).toHaveBeenCalledWith(
952
+ 'TestDim', 'TestHierarchy',
953
+ expect.stringContaining('FILTER(DESCENDANTS')
954
+ );
955
+ });
956
+
957
+ test('should get members under consolidation using MDX', async () => {
958
+ jest.spyOn(elementService, 'executeSetMdxElementNames').mockResolvedValue(['Member1', 'Member2']);
959
+ jest.spyOn(elementService, 'get')
960
+ .mockResolvedValueOnce(mockElement)
961
+ .mockResolvedValueOnce(mockElement);
962
+
963
+ const result = await elementService.getMembersUnderConsolidation('TestDim', 'TestHierarchy', 'Consol1');
964
+
965
+ expect(result).toHaveLength(2);
966
+ expect(elementService.executeSetMdxElementNames).toHaveBeenCalledWith(
967
+ 'TestDim', 'TestHierarchy',
968
+ expect.stringContaining('DESCENDANTS')
969
+ );
970
+ });
971
+
972
+ test('should get all element identifiers', async () => {
973
+ jest.spyOn(elementService, 'getNames').mockResolvedValue(['Element1', 'Element2', 'Element3']);
974
+
975
+ const result = await elementService.getAllElementIdentifiers('TestDim', 'TestHierarchy');
976
+
977
+ expect(result).toEqual([
978
+ '[TestDim].[TestHierarchy].[Element1]',
979
+ '[TestDim].[TestHierarchy].[Element2]',
980
+ '[TestDim].[TestHierarchy].[Element3]'
981
+ ]);
982
+ });
983
+
984
+ test('should get element identifiers with filter pattern', async () => {
985
+ const filteredElements = [
986
+ { name: 'FilteredElement1', elementType: ElementType.NUMERIC },
987
+ { name: 'FilteredElement2', elementType: ElementType.STRING }
988
+ ];
989
+ jest.spyOn(elementService, 'getElementsFilteredByWildcard').mockResolvedValue(filteredElements as any);
990
+
991
+ const result = await elementService.getElementIdentifiers('TestDim', 'TestHierarchy', 'Filtered*');
992
+
993
+ expect(result).toEqual([
994
+ '[TestDim].[TestHierarchy].[FilteredElement1]',
995
+ '[TestDim].[TestHierarchy].[FilteredElement2]'
996
+ ]);
997
+ });
998
+
999
+ test('should get element identifiers without filter', async () => {
1000
+ jest.spyOn(elementService, 'getNames').mockResolvedValue(['Element1', 'Element2']);
1001
+
1002
+ const result = await elementService.getElementIdentifiers('TestDim', 'TestHierarchy');
1003
+
1004
+ expect(result).toEqual([
1005
+ '[TestDim].[TestHierarchy].[Element1]',
1006
+ '[TestDim].[TestHierarchy].[Element2]'
1007
+ ]);
1008
+ });
1009
+ });
1010
+
1011
+ describe('MDXDrillMethod Enum', () => {
1012
+ test('should export all drill methods correctly', () => {
1013
+ expect(MDXDrillMethod.TM1DRILLDOWNMEMBER).toBe(1);
1014
+ expect(MDXDrillMethod.DESCENDANTS).toBe(2);
1015
+ });
1016
+ });
1017
+
1018
+ describe('Error Handling', () => {
1019
+ test('should handle element retrieval errors', async () => {
1020
+ const error = new Error('Element not found');
1021
+ mockRestService.get.mockRejectedValue(error);
1022
+
1023
+ await expect(elementService.get('TestDim', 'TestHierarchy', 'NonExistent'))
1024
+ .rejects.toThrow('Element not found');
1025
+ });
1026
+
1027
+ test('should handle element creation errors', async () => {
1028
+ const error = new Error('Element creation failed');
1029
+ mockRestService.post.mockRejectedValue(error);
1030
+
1031
+ await expect(elementService.create('TestDim', 'TestHierarchy', mockElement))
1032
+ .rejects.toThrow('Element creation failed');
1033
+ });
1034
+
1035
+ test('should handle MDX execution errors', async () => {
1036
+ const error = new Error('MDX execution failed');
1037
+ mockRestService.post.mockRejectedValue(error);
1038
+
1039
+ await expect(elementService.executeSetMdx('TestDim', 'TestHierarchy', 'INVALID MDX'))
1040
+ .rejects.toThrow('MDX execution failed');
1041
+ });
1042
+
1043
+ test('should handle attribute operation errors', async () => {
1044
+ const error = new Error('Attribute operation failed');
1045
+ mockRestService.get.mockRejectedValue(error);
1046
+
1047
+ await expect(elementService.getElementAttributes('TestDim', 'TestHierarchy'))
1048
+ .rejects.toThrow('Attribute operation failed');
1049
+ });
1050
+
1051
+ test('should handle hierarchy traversal errors', async () => {
1052
+ const error = new Error('Hierarchy access failed');
1053
+ mockRestService.get.mockRejectedValue(error);
1054
+
1055
+ await expect(elementService.getParents('TestDim', 'TestHierarchy', 'Element'))
1056
+ .rejects.toThrow('Hierarchy access failed');
1057
+ });
1058
+ });
1059
+
1060
+ describe('Edge Cases and Special Scenarios', () => {
1061
+ test('should handle empty results gracefully', async () => {
1062
+ mockRestService.get.mockResolvedValue(mockResponse({ value: [] }));
1063
+
1064
+ const names = await elementService.getNames('TestDim', 'TestHierarchy');
1065
+ const elements = await elementService.getElements('TestDim', 'TestHierarchy');
1066
+ const parents = await elementService.getParents('TestDim', 'TestHierarchy', 'Element');
1067
+ const children = await elementService.getChildren('TestDim', 'TestHierarchy', 'Element');
1068
+
1069
+ expect(names).toEqual([]);
1070
+ expect(elements).toEqual([]);
1071
+ expect(parents).toEqual([]);
1072
+ expect(children).toEqual([]);
1073
+ });
1074
+
1075
+ test('should handle special characters in element names', async () => {
1076
+ const specialName = "Element's & \"Special\" Name";
1077
+ mockRestService.get.mockResolvedValue(mockResponse({ Name: specialName }));
1078
+
1079
+ await elementService.get('TestDim', 'TestHierarchy', specialName);
1080
+
1081
+ // The formatUrl method encodes special characters, so we expect the encoded version
1082
+ expect(mockRestService.get).toHaveBeenCalledWith(
1083
+ expect.stringContaining("/Elements('Element's%20%26%20%22Special%22%20Name')")
1084
+ );
1085
+ });
1086
+
1087
+ test('should handle null/undefined values in element types', async () => {
1088
+ const typesData = {
1089
+ value: [
1090
+ { Name: 'Element1', Type: null },
1091
+ { Name: 'Element2', Type: undefined },
1092
+ { Name: 'Element3', Type: 'Numeric' }
1093
+ ]
1094
+ };
1095
+ mockRestService.get.mockResolvedValue(mockResponse(typesData));
1096
+
1097
+ const result = await elementService.getElementTypes('TestDim', 'TestHierarchy');
1098
+
1099
+ expect(result).toBeInstanceOf(CaseAndSpaceInsensitiveDict);
1100
+ });
1101
+
1102
+ test('should handle large datasets efficiently', async () => {
1103
+ const largeDataset = Array.from({ length: 10000 }, (_, i) => ({
1104
+ Name: `Element${i}`,
1105
+ Type: i % 2 === 0 ? 'Numeric' : 'String'
1106
+ }));
1107
+
1108
+ mockRestService.get.mockResolvedValue(mockResponse({ value: largeDataset }));
1109
+
1110
+ const result = await elementService.getNames('TestDim', 'TestHierarchy');
1111
+
1112
+ expect(result).toHaveLength(10000);
1113
+ expect(result[0]).toBe('Element0');
1114
+ expect(result[9999]).toBe('Element9999');
1115
+ });
1116
+
1117
+ test('should handle missing attribute values gracefully', async () => {
1118
+ const elementsData = {
1119
+ value: [
1120
+ { Name: 'Element1', Type: 'Numeric', Attributes: {} },
1121
+ { Name: 'Element2', Type: 'String' } // No Attributes property
1122
+ ]
1123
+ };
1124
+ mockRestService.get.mockResolvedValue(mockResponse(elementsData));
1125
+
1126
+ const result = await elementService.getElementsDataframe('TestDim', 'TestHierarchy', ['MissingAttribute']);
1127
+
1128
+ expect(result).toEqual([
1129
+ ['Name', 'Type', 'MissingAttribute'],
1130
+ ['Element1', 'Numeric', ''],
1131
+ ['Element2', 'String'] // No attribute value added when no Attributes property exists
1132
+ ]);
1133
+ });
1134
+ });
1135
+
1136
+ describe('Integration Patterns', () => {
1137
+ test('should support element lifecycle management', async () => {
1138
+ mockRestService.post.mockResolvedValue(mockResponse({}));
1139
+ mockRestService.patch.mockResolvedValue(mockResponse({}));
1140
+ mockRestService.delete.mockResolvedValue(mockResponse({}));
1141
+ jest.spyOn(elementService, 'exists').mockResolvedValue(true);
1142
+
1143
+ // Element lifecycle: create, add relationships, update, delete
1144
+ await elementService.create('TestDim', 'TestHierarchy', mockElement);
1145
+ await elementService.addEdges('TestDim', 'TestHierarchy', [
1146
+ { parent: 'Parent1', child: 'TestElement', weight: 1.5 }
1147
+ ]);
1148
+ await elementService.update('TestDim', 'TestHierarchy', mockElement);
1149
+ await elementService.delete('TestDim', 'TestHierarchy', 'TestElement');
1150
+
1151
+ expect(mockRestService.post).toHaveBeenCalledTimes(2); // create + add edge
1152
+ expect(mockRestService.patch).toHaveBeenCalledTimes(1);
1153
+ expect(mockRestService.delete).toHaveBeenCalledTimes(1);
1154
+ });
1155
+
1156
+ test('should support hierarchy building workflow', async () => {
1157
+ mockRestService.post.mockResolvedValue(mockResponse({}));
1158
+ jest.spyOn(elementService, 'create').mockResolvedValue(mockResponse({}));
1159
+ jest.spyOn(elementService, 'addEdges').mockResolvedValue();
1160
+
1161
+ const elements = [mockElement, mockElement, mockElement];
1162
+ const edges = [
1163
+ { parent: 'Parent1', child: 'Child1', weight: 1 },
1164
+ { parent: 'Parent1', child: 'Child2', weight: 2 }
1165
+ ];
1166
+
1167
+ // Hierarchy building workflow
1168
+ await elementService.addElements('TestDim', 'TestHierarchy', elements);
1169
+ await elementService.addEdges('TestDim', 'TestHierarchy', edges);
1170
+
1171
+ expect(elementService.create).toHaveBeenCalledTimes(3);
1172
+ expect(elementService.addEdges).toHaveBeenCalledWith('TestDim', 'TestHierarchy', edges);
1173
+ });
1174
+
1175
+ test('should support attribute management workflow', async () => {
1176
+ mockRestService.post.mockResolvedValue(mockResponse({}));
1177
+ mockRestService.patch.mockResolvedValue(mockResponse({}));
1178
+ mockRestService.delete.mockResolvedValue(mockResponse({}));
1179
+
1180
+ // Attribute management workflow
1181
+ await elementService.createElementAttribute('TestDim', 'TestHierarchy', mockElementAttribute);
1182
+ await elementService.updateElementAttribute('TestDim', 'TestHierarchy', 'Element1', 'TestAttribute', 'Value1');
1183
+ await elementService.deleteElementAttribute('TestDim', 'TestHierarchy', 'TestAttribute');
1184
+
1185
+ expect(mockRestService.post).toHaveBeenCalledTimes(1);
1186
+ expect(mockRestService.patch).toHaveBeenCalledTimes(1);
1187
+ expect(mockRestService.delete).toHaveBeenCalledTimes(1);
1188
+ });
1189
+ });
1190
+ });