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,786 @@
1
+ /**
2
+ * Comprehensive DimensionService Tests
3
+ * Target: Achieve 80%+ coverage for DimensionService (currently 45%)
4
+ * Testing all dimension operations including CRUD, hierarchy management, and service integration
5
+ */
6
+
7
+ import { DimensionService } from '../services/DimensionService';
8
+ import { RestService } from '../services/RestService';
9
+ import { HierarchyService } from '../services/HierarchyService';
10
+ import { SubsetService } from '../services/SubsetService';
11
+ import { Dimension } from '../objects/Dimension';
12
+ import { Hierarchy } from '../objects/Hierarchy';
13
+ import { TM1RestException } from '../exceptions/TM1Exception';
14
+
15
+ // Mock dependencies
16
+ jest.mock('../services/HierarchyService');
17
+ jest.mock('../services/SubsetService');
18
+ jest.mock('../objects/Dimension');
19
+ jest.mock('../objects/Hierarchy');
20
+
21
+ describe('DimensionService - Comprehensive Tests', () => {
22
+ let dimensionService: DimensionService;
23
+ let mockRestService: jest.Mocked<RestService>;
24
+ let mockHierarchyService: jest.Mocked<HierarchyService>;
25
+ let mockSubsetService: jest.Mocked<SubsetService>;
26
+
27
+ const mockResponse = (data: any) => ({
28
+ data: data,
29
+ status: 200,
30
+ statusText: 'OK',
31
+ headers: {},
32
+ config: { headers: {} }
33
+ } as any);
34
+
35
+ const mockDimension = {
36
+ name: 'TestDimension',
37
+ hierarchies: [
38
+ { name: 'TestDimension', dimensionName: 'TestDimension' },
39
+ { name: 'AltHierarchy', dimensionName: 'TestDimension' }
40
+ ],
41
+ hierarchyNames: ['TestDimension', 'AltHierarchy'],
42
+ defaultHierarchy: { name: 'TestDimension', dimensionName: 'TestDimension' },
43
+ body: {
44
+ Name: 'TestDimension',
45
+ Hierarchies: [
46
+ { Name: 'TestDimension' },
47
+ { Name: 'AltHierarchy' }
48
+ ]
49
+ },
50
+ addHierarchy: jest.fn(),
51
+ [Symbol.iterator]: function* () {
52
+ yield* this.hierarchies;
53
+ }
54
+ } as any;
55
+
56
+ const mockHierarchy = {
57
+ name: 'TestHierarchy',
58
+ dimensionName: 'TestDimension'
59
+ } as any;
60
+
61
+ beforeEach(() => {
62
+ mockRestService = {
63
+ get: jest.fn(),
64
+ post: jest.fn(),
65
+ patch: jest.fn(),
66
+ put: jest.fn(),
67
+ delete: jest.fn()
68
+ } as any;
69
+
70
+ // Mock the constructor-injected services
71
+ mockHierarchyService = {
72
+ getAllNames: jest.fn(),
73
+ exists: jest.fn(),
74
+ update: jest.fn(),
75
+ create: jest.fn(),
76
+ delete: jest.fn(),
77
+ updateElementAttributes: jest.fn()
78
+ } as any;
79
+
80
+ mockSubsetService = {} as any;
81
+
82
+ // Mock the service constructors to return our mocks
83
+ (HierarchyService as jest.MockedClass<typeof HierarchyService>).mockImplementation(() => mockHierarchyService);
84
+ (SubsetService as jest.MockedClass<typeof SubsetService>).mockImplementation(() => mockSubsetService);
85
+
86
+ dimensionService = new DimensionService(mockRestService);
87
+
88
+ // Mock Dimension.fromJSON and fromDict
89
+ (Dimension as any).fromJSON = jest.fn().mockReturnValue(mockDimension);
90
+ (Dimension as any).fromDict = jest.fn().mockReturnValue(mockDimension);
91
+
92
+ // Note: formatUrl and caseAndSpaceInsensitiveEquals are inherited from ObjectService
93
+ });
94
+
95
+ afterEach(() => {
96
+ jest.clearAllMocks();
97
+ jest.restoreAllMocks();
98
+ });
99
+
100
+ describe('Constructor and Initialization', () => {
101
+ test('should initialize DimensionService with sub-services', () => {
102
+ expect(dimensionService).toBeDefined();
103
+ expect(dimensionService).toBeInstanceOf(DimensionService);
104
+ expect(HierarchyService).toHaveBeenCalledWith(mockRestService);
105
+ expect(SubsetService).toHaveBeenCalledWith(mockRestService);
106
+ });
107
+
108
+ test('should extend ObjectService', () => {
109
+ expect(dimensionService).toBeInstanceOf(DimensionService);
110
+ });
111
+ });
112
+
113
+ describe('Dimension CRUD Operations', () => {
114
+ test('should create dimension successfully', async () => {
115
+ jest.spyOn(dimensionService, 'exists').mockResolvedValue(false);
116
+ mockRestService.post.mockResolvedValue(mockResponse({}));
117
+ mockHierarchyService.updateElementAttributes.mockResolvedValue();
118
+
119
+ const result = await dimensionService.create(mockDimension);
120
+
121
+ expect(dimensionService.exists).toHaveBeenCalledWith('TestDimension');
122
+ expect(mockRestService.post).toHaveBeenCalledWith('/Dimensions', mockDimension.body);
123
+ expect(mockHierarchyService.updateElementAttributes).toHaveBeenCalledTimes(2); // For non-Leaves hierarchies
124
+ expect(result).toBeDefined();
125
+ });
126
+
127
+ test('should throw error when creating existing dimension', async () => {
128
+ jest.spyOn(dimensionService, 'exists').mockResolvedValue(true);
129
+
130
+ await expect(dimensionService.create(mockDimension))
131
+ .rejects.toThrow("Dimension 'TestDimension' already exists");
132
+
133
+ expect(mockRestService.post).not.toHaveBeenCalled();
134
+ });
135
+
136
+ test('should handle creation failure and cleanup', async () => {
137
+ jest.spyOn(dimensionService, 'exists')
138
+ .mockResolvedValueOnce(false) // Initial check
139
+ .mockResolvedValueOnce(true); // Check during cleanup
140
+ jest.spyOn(dimensionService, 'delete').mockResolvedValue(mockResponse({}));
141
+
142
+ const error = new Error('Creation failed');
143
+ mockRestService.post.mockRejectedValue(error);
144
+
145
+ await expect(dimensionService.create(mockDimension)).rejects.toThrow('Creation failed');
146
+
147
+ expect(dimensionService.delete).toHaveBeenCalledWith('TestDimension');
148
+ });
149
+
150
+ test('should skip Leaves hierarchy during creation', async () => {
151
+ const dimensionWithLeaves = {
152
+ ...mockDimension,
153
+ hierarchies: [
154
+ { name: 'TestDimension', dimensionName: 'TestDimension' },
155
+ { name: 'Leaves', dimensionName: 'TestDimension' },
156
+ { name: 'AltHierarchy', dimensionName: 'TestDimension' }
157
+ ],
158
+ [Symbol.iterator]: function* () {
159
+ yield* this.hierarchies;
160
+ }
161
+ };
162
+
163
+ jest.spyOn(dimensionService, 'exists').mockResolvedValue(false);
164
+ mockRestService.post.mockResolvedValue(mockResponse({}));
165
+ mockHierarchyService.updateElementAttributes.mockResolvedValue();
166
+
167
+ await dimensionService.create(dimensionWithLeaves);
168
+
169
+ // Should skip 'Leaves' hierarchy, so only 2 calls instead of 3
170
+ expect(mockHierarchyService.updateElementAttributes).toHaveBeenCalledTimes(2);
171
+ });
172
+
173
+ test('should get dimension by name', async () => {
174
+ const dimensionData = {
175
+ Name: 'TestDimension',
176
+ Hierarchies: [{ Name: 'TestDimension' }]
177
+ };
178
+ mockRestService.get.mockResolvedValue(mockResponse(dimensionData));
179
+
180
+ const result = await dimensionService.get('TestDimension');
181
+
182
+ expect(mockRestService.get).toHaveBeenCalledWith("/Dimensions('TestDimension')?$expand=Hierarchies($expand=*)");
183
+ expect(Dimension.fromJSON).toHaveBeenCalledWith(JSON.stringify(dimensionData));
184
+ expect(result).toEqual(mockDimension);
185
+ });
186
+
187
+ test('should update dimension with existing hierarchies', async () => {
188
+ mockHierarchyService.getAllNames.mockResolvedValue(['TestDimension', 'OldHierarchy', 'AltHierarchy']);
189
+ mockHierarchyService.exists.mockResolvedValue(true);
190
+ mockHierarchyService.update.mockResolvedValue();
191
+ mockHierarchyService.delete.mockResolvedValue(mockResponse({}));
192
+
193
+ await dimensionService.update(mockDimension);
194
+
195
+ expect(mockHierarchyService.getAllNames).toHaveBeenCalledWith('TestDimension');
196
+ expect(mockHierarchyService.update).toHaveBeenCalledTimes(2); // For TestDimension and AltHierarchy
197
+ expect(mockHierarchyService.delete).toHaveBeenCalledWith('TestDimension', 'OldHierarchy'); // Remove old hierarchy
198
+ });
199
+
200
+ test('should update dimension and create new hierarchies', async () => {
201
+ mockHierarchyService.getAllNames.mockResolvedValue(['TestDimension']);
202
+ mockHierarchyService.exists
203
+ .mockResolvedValueOnce(true) // TestDimension exists
204
+ .mockResolvedValueOnce(false); // AltHierarchy doesn't exist
205
+ mockHierarchyService.update.mockResolvedValue();
206
+ mockHierarchyService.create.mockResolvedValue(mockResponse({}));
207
+
208
+ await dimensionService.update(mockDimension);
209
+
210
+ expect(mockHierarchyService.update).toHaveBeenCalledTimes(1); // For existing TestDimension
211
+ expect(mockHierarchyService.create).toHaveBeenCalledTimes(1); // For new AltHierarchy
212
+ });
213
+
214
+ test('should update dimension with keepExistingAttributes flag', async () => {
215
+ mockHierarchyService.getAllNames.mockResolvedValue(['TestDimension']);
216
+ mockHierarchyService.exists.mockResolvedValue(true);
217
+ mockHierarchyService.update.mockResolvedValue();
218
+
219
+ await dimensionService.update(mockDimension, true);
220
+
221
+ expect(mockHierarchyService.update).toHaveBeenCalledWith(
222
+ mockDimension.hierarchies[0],
223
+ true // keepExistingAttributes
224
+ );
225
+ });
226
+
227
+ test('should skip Leaves hierarchy during update', async () => {
228
+ const dimensionWithLeaves = {
229
+ ...mockDimension,
230
+ hierarchies: [
231
+ { name: 'TestDimension', dimensionName: 'TestDimension' },
232
+ { name: 'Leaves', dimensionName: 'TestDimension' }
233
+ ],
234
+ hierarchyNames: ['TestDimension', 'Leaves'],
235
+ [Symbol.iterator]: function* () {
236
+ yield* this.hierarchies;
237
+ }
238
+ };
239
+
240
+ mockHierarchyService.getAllNames.mockResolvedValue(['TestDimension', 'Leaves']);
241
+ mockHierarchyService.exists.mockResolvedValue(true);
242
+ mockHierarchyService.update.mockResolvedValue();
243
+
244
+ await dimensionService.update(dimensionWithLeaves);
245
+
246
+ // Should only update TestDimension, skip Leaves
247
+ expect(mockHierarchyService.update).toHaveBeenCalledTimes(1);
248
+ expect(mockHierarchyService.delete).not.toHaveBeenCalledWith('TestDimension', 'Leaves');
249
+ });
250
+
251
+ test('should delete dimension', async () => {
252
+ mockRestService.delete.mockResolvedValue(mockResponse({}));
253
+
254
+ const result = await dimensionService.delete('TestDimension');
255
+
256
+ expect(mockRestService.delete).toHaveBeenCalledWith("/Dimensions('TestDimension')");
257
+ expect(result).toBeDefined();
258
+ });
259
+
260
+ test('should check if dimension exists', async () => {
261
+ mockRestService.get.mockResolvedValue(mockResponse({}));
262
+
263
+ const result = await dimensionService.exists('TestDimension');
264
+
265
+ expect(result).toBe(true);
266
+ expect(mockRestService.get).toHaveBeenCalledWith("/Dimensions('TestDimension')");
267
+ });
268
+
269
+ test('should return false when dimension does not exist', async () => {
270
+ const error = new TM1RestException('Not found', 404);
271
+ error.statusCode = 404; // Set the statusCode property that DimensionService checks
272
+ mockRestService.get.mockRejectedValue(error);
273
+
274
+ const result = await dimensionService.exists('NonExistent');
275
+
276
+ expect(result).toBe(false);
277
+ });
278
+
279
+ test('should throw error for non-404 errors in exists check', async () => {
280
+ const error = new TM1RestException('Server error', 500);
281
+ mockRestService.get.mockRejectedValue(error);
282
+
283
+ await expect(dimensionService.exists('TestDimension')).rejects.toThrow('Server error');
284
+ });
285
+ });
286
+
287
+ describe('Dimension Retrieval Operations', () => {
288
+ test('should get all dimension names', async () => {
289
+ const dimensionsData = {
290
+ value: [
291
+ { Name: 'Dimension1' },
292
+ { Name: 'Dimension2' },
293
+ { Name: '}Stats' }
294
+ ]
295
+ };
296
+ mockRestService.get.mockResolvedValue(mockResponse(dimensionsData));
297
+
298
+ const result = await dimensionService.getAllNames();
299
+
300
+ expect(result).toEqual(['Dimension1', 'Dimension2', '}Stats']);
301
+ expect(mockRestService.get).toHaveBeenCalledWith('/Dimensions?$select=Name');
302
+ });
303
+
304
+ test('should get all dimension names excluding control dimensions', async () => {
305
+ const dimensionsData = {
306
+ value: [
307
+ { Name: 'Dimension1' },
308
+ { Name: 'Dimension2' }
309
+ ]
310
+ };
311
+ mockRestService.get.mockResolvedValue(mockResponse(dimensionsData));
312
+
313
+ const result = await dimensionService.getAllNames(true);
314
+
315
+ expect(result).toEqual(['Dimension1', 'Dimension2']);
316
+ expect(mockRestService.get).toHaveBeenCalledWith("/Dimensions?$select=Name&$filter=not startswith(Name,'}')");
317
+ });
318
+
319
+ test('should get all dimensions', async () => {
320
+ const dimensionsData = {
321
+ value: [
322
+ { Name: 'Dimension1', Hierarchies: [{ Name: 'Dimension1' }] },
323
+ { Name: 'Dimension2', Hierarchies: [{ Name: 'Dimension2' }] }
324
+ ]
325
+ };
326
+ mockRestService.get.mockResolvedValue(mockResponse(dimensionsData));
327
+
328
+ const result = await dimensionService.getAll();
329
+
330
+ expect(result).toHaveLength(2);
331
+ expect(Dimension.fromDict).toHaveBeenCalledTimes(2);
332
+ expect(mockRestService.get).toHaveBeenCalledWith('/Dimensions?$expand=Hierarchies($expand=*)');
333
+ });
334
+
335
+ test('should get all dimensions excluding control dimensions', async () => {
336
+ const dimensionsData = {
337
+ value: [
338
+ { Name: 'Dimension1', Hierarchies: [{ Name: 'Dimension1' }] }
339
+ ]
340
+ };
341
+ mockRestService.get.mockResolvedValue(mockResponse(dimensionsData));
342
+
343
+ const result = await dimensionService.getAll(true);
344
+
345
+ expect(result).toHaveLength(1);
346
+ expect(mockRestService.get).toHaveBeenCalledWith("/Dimensions?$expand=Hierarchies($expand=*)&$filter=not startswith(Name,'}')");
347
+ });
348
+
349
+ test('should get dimension names from cube', async () => {
350
+ const cubeData = {
351
+ Dimensions: [
352
+ { Name: 'Time' },
353
+ { Name: 'Account' },
354
+ { Name: 'Version' }
355
+ ]
356
+ };
357
+ mockRestService.get.mockResolvedValue(mockResponse(cubeData));
358
+
359
+ const result = await dimensionService.getDimensionNames('SalesCube');
360
+
361
+ expect(result).toEqual(['Time', 'Account', 'Version']);
362
+ expect(mockRestService.get).toHaveBeenCalledWith("/Cubes('SalesCube')?$select=Dimensions");
363
+ });
364
+ });
365
+
366
+ describe('Dimension Cloning Operations', () => {
367
+ test('should clone dimension with all hierarchies', async () => {
368
+ jest.spyOn(dimensionService, 'exists').mockResolvedValue(false);
369
+ jest.spyOn(dimensionService, 'get').mockResolvedValue(mockDimension);
370
+ jest.spyOn(dimensionService, 'create').mockResolvedValue(mockResponse({}));
371
+
372
+ const result = await dimensionService.clone('SourceDim', 'TargetDim', true);
373
+
374
+ expect(dimensionService.exists).toHaveBeenCalledWith('TargetDim');
375
+ expect(dimensionService.get).toHaveBeenCalledWith('SourceDim');
376
+ expect(dimensionService.create).toHaveBeenCalled();
377
+ expect(result).toBeDefined();
378
+ });
379
+
380
+ test('should clone dimension without additional hierarchies', async () => {
381
+ const sourceDimensionWithMultipleHierarchies = {
382
+ ...mockDimension,
383
+ hierarchies: [
384
+ { name: 'SourceDim', dimensionName: 'SourceDim' },
385
+ { name: 'AltHierarchy', dimensionName: 'SourceDim' },
386
+ { name: 'AnotherHierarchy', dimensionName: 'SourceDim' }
387
+ ],
388
+ defaultHierarchy: { name: 'SourceDim', dimensionName: 'SourceDim' },
389
+ addHierarchy: jest.fn()
390
+ };
391
+
392
+ jest.spyOn(dimensionService, 'exists').mockResolvedValue(false);
393
+ jest.spyOn(dimensionService, 'get').mockResolvedValue(sourceDimensionWithMultipleHierarchies);
394
+ jest.spyOn(dimensionService, 'create').mockResolvedValue(mockResponse({}));
395
+
396
+ await dimensionService.clone('SourceDim', 'TargetDim', false);
397
+
398
+ expect(sourceDimensionWithMultipleHierarchies.hierarchies.length).toBe(0);
399
+ expect(sourceDimensionWithMultipleHierarchies.addHierarchy).toHaveBeenCalledWith(
400
+ expect.objectContaining({ name: 'TargetDim' })
401
+ );
402
+ });
403
+
404
+ test('should rename hierarchies to match target dimension name', async () => {
405
+ const sourceDimension = {
406
+ name: 'SourceDim',
407
+ hierarchies: [
408
+ { name: 'SourceDim', dimensionName: 'SourceDim' }, // Should be renamed
409
+ { name: 'CustomHierarchy', dimensionName: 'SourceDim' } // Should not be renamed
410
+ ],
411
+ hierarchyNames: ['SourceDim', 'CustomHierarchy'],
412
+ defaultHierarchy: { name: 'SourceDim', dimensionName: 'SourceDim' },
413
+ body: {},
414
+ addHierarchy: jest.fn(),
415
+ [Symbol.iterator]: function* () {
416
+ yield* this.hierarchies;
417
+ }
418
+ };
419
+
420
+ jest.spyOn(dimensionService, 'exists').mockResolvedValue(false);
421
+ jest.spyOn(dimensionService, 'get').mockResolvedValue(sourceDimension as any);
422
+ jest.spyOn(dimensionService, 'create').mockResolvedValue(mockResponse({}));
423
+
424
+ await dimensionService.clone('SourceDim', 'TargetDim', true);
425
+
426
+ expect(sourceDimension.hierarchies[0].name).toBe('TargetDim'); // Renamed
427
+ expect(sourceDimension.hierarchies[1].name).toBe('CustomHierarchy'); // Not renamed
428
+ });
429
+
430
+ test('should throw error when cloning to existing dimension', async () => {
431
+ jest.spyOn(dimensionService, 'exists').mockResolvedValue(true);
432
+
433
+ await expect(dimensionService.clone('SourceDim', 'ExistingDim'))
434
+ .rejects.toThrow("Dimension 'ExistingDim' already exists");
435
+ });
436
+
437
+ test('should handle cloning when default hierarchy is null', async () => {
438
+ const sourceDimensionNoDefault = {
439
+ ...mockDimension,
440
+ defaultHierarchy: null
441
+ };
442
+
443
+ jest.spyOn(dimensionService, 'exists').mockResolvedValue(false);
444
+ jest.spyOn(dimensionService, 'get').mockResolvedValue(sourceDimensionNoDefault);
445
+ jest.spyOn(dimensionService, 'create').mockResolvedValue(mockResponse({}));
446
+
447
+ await dimensionService.clone('SourceDim', 'TargetDim', false);
448
+
449
+ expect(dimensionService.create).toHaveBeenCalled();
450
+ });
451
+ });
452
+
453
+ describe('Dimension Statistics Operations', () => {
454
+ test('should get elements count for dimension', async () => {
455
+ mockRestService.get.mockResolvedValue(mockResponse('150'));
456
+
457
+ const result = await dimensionService.getElementsCount('TestDimension');
458
+
459
+ expect(result).toBe(150);
460
+ expect(mockRestService.get).toHaveBeenCalledWith("/Dimensions('TestDimension')/Hierarchies('TestDimension')/Elements/$count");
461
+ });
462
+
463
+ test('should get elements count for specific hierarchy', async () => {
464
+ mockRestService.get.mockResolvedValue(mockResponse('75'));
465
+
466
+ const result = await dimensionService.getElementsCount('TestDimension', 'CustomHierarchy');
467
+
468
+ expect(result).toBe(75);
469
+ expect(mockRestService.get).toHaveBeenCalledWith("/Dimensions('TestDimension')/Hierarchies('CustomHierarchy')/Elements/$count");
470
+ });
471
+
472
+ test('should get hierarchies count for dimension', async () => {
473
+ mockRestService.get.mockResolvedValue(mockResponse('3'));
474
+
475
+ const result = await dimensionService.getHierarchiesCount('TestDimension');
476
+
477
+ expect(result).toBe(3);
478
+ expect(mockRestService.get).toHaveBeenCalledWith("/Dimensions('TestDimension')/Hierarchies/$count");
479
+ });
480
+
481
+ test('should handle non-numeric count responses', async () => {
482
+ mockRestService.get.mockResolvedValue(mockResponse('invalid'));
483
+
484
+ const result = await dimensionService.getElementsCount('TestDimension');
485
+
486
+ expect(isNaN(result)).toBe(true);
487
+ });
488
+ });
489
+
490
+ describe('Error Handling', () => {
491
+ test('should handle dimension retrieval errors', async () => {
492
+ const error = new Error('Dimension not found');
493
+ mockRestService.get.mockRejectedValue(error);
494
+
495
+ await expect(dimensionService.get('NonExistent')).rejects.toThrow('Dimension not found');
496
+ });
497
+
498
+ test('should handle dimension creation errors', async () => {
499
+ jest.spyOn(dimensionService, 'exists').mockResolvedValue(false);
500
+ const error = new Error('Creation failed');
501
+ mockRestService.post.mockRejectedValue(error);
502
+
503
+ await expect(dimensionService.create(mockDimension)).rejects.toThrow('Creation failed');
504
+ });
505
+
506
+ test('should handle dimension deletion errors', async () => {
507
+ const error = new Error('Deletion failed');
508
+ mockRestService.delete.mockRejectedValue(error);
509
+
510
+ await expect(dimensionService.delete('TestDimension')).rejects.toThrow('Deletion failed');
511
+ });
512
+
513
+ test('should handle hierarchy service errors during creation', async () => {
514
+ jest.spyOn(dimensionService, 'exists').mockResolvedValue(false);
515
+ mockRestService.post.mockResolvedValue(mockResponse({}));
516
+ mockHierarchyService.updateElementAttributes.mockRejectedValue(new Error('Hierarchy error'));
517
+
518
+ await expect(dimensionService.create(mockDimension)).rejects.toThrow('Hierarchy error');
519
+ });
520
+
521
+ test('should handle hierarchy service errors during update', async () => {
522
+ mockHierarchyService.getAllNames.mockRejectedValue(new Error('Hierarchy access failed'));
523
+
524
+ await expect(dimensionService.update(mockDimension)).rejects.toThrow('Hierarchy access failed');
525
+ });
526
+
527
+ test('should handle cube dimension retrieval errors', async () => {
528
+ const error = new Error('Cube not found');
529
+ mockRestService.get.mockRejectedValue(error);
530
+
531
+ await expect(dimensionService.getDimensionNames('NonExistentCube')).rejects.toThrow('Cube not found');
532
+ });
533
+ });
534
+
535
+ describe('Edge Cases and Special Scenarios', () => {
536
+ test('should handle empty dimension lists', async () => {
537
+ mockRestService.get.mockResolvedValue(mockResponse({ value: [] }));
538
+
539
+ const names = await dimensionService.getAllNames();
540
+ const dimensions = await dimensionService.getAll();
541
+
542
+ expect(names).toEqual([]);
543
+ expect(dimensions).toEqual([]);
544
+ });
545
+
546
+ test('should handle special characters in dimension names', async () => {
547
+ const specialName = "Dimension's & \"Special\" Name";
548
+ mockRestService.get.mockResolvedValue(mockResponse({}));
549
+
550
+ await dimensionService.exists(specialName);
551
+
552
+ // The formatUrl method encodes special characters
553
+ expect(mockRestService.get).toHaveBeenCalledWith(
554
+ expect.stringContaining("Dimension's%20%26%20%22Special%22%20Name")
555
+ );
556
+ });
557
+
558
+ test('should handle dimension with no hierarchies', async () => {
559
+ const emptyDimension = {
560
+ name: 'EmptyDimension',
561
+ hierarchies: [],
562
+ hierarchyNames: [],
563
+ body: { Name: 'EmptyDimension', Hierarchies: [] },
564
+ [Symbol.iterator]: function* () {
565
+ yield* this.hierarchies;
566
+ }
567
+ };
568
+
569
+ jest.spyOn(dimensionService, 'exists').mockResolvedValue(false);
570
+ mockRestService.post.mockResolvedValue(mockResponse({}));
571
+
572
+ await dimensionService.create(emptyDimension as any);
573
+
574
+ expect(mockHierarchyService.updateElementAttributes).not.toHaveBeenCalled();
575
+ });
576
+
577
+ test('should handle dimension update with no hierarchy changes', async () => {
578
+ mockHierarchyService.getAllNames.mockResolvedValue(['TestDimension', 'AltHierarchy']);
579
+ mockHierarchyService.exists.mockResolvedValue(true);
580
+ mockHierarchyService.update.mockResolvedValue();
581
+
582
+ await dimensionService.update(mockDimension);
583
+
584
+ expect(mockHierarchyService.delete).not.toHaveBeenCalled(); // No hierarchies to remove
585
+ expect(mockHierarchyService.create).not.toHaveBeenCalled(); // No new hierarchies
586
+ });
587
+
588
+ test('should handle large dimension lists efficiently', async () => {
589
+ const largeDimensionList = Array.from({ length: 1000 }, (_, i) => ({
590
+ Name: `Dimension${i}`
591
+ }));
592
+
593
+ mockRestService.get.mockResolvedValue(mockResponse({ value: largeDimensionList }));
594
+
595
+ const result = await dimensionService.getAllNames();
596
+
597
+ expect(result).toHaveLength(1000);
598
+ expect(result[0]).toBe('Dimension0');
599
+ expect(result[999]).toBe('Dimension999');
600
+ });
601
+
602
+ test('should handle cube with no dimensions', async () => {
603
+ mockRestService.get.mockResolvedValue(mockResponse({ Dimensions: [] }));
604
+
605
+ const result = await dimensionService.getDimensionNames('EmptyCube');
606
+
607
+ expect(result).toEqual([]);
608
+ });
609
+
610
+ test('should handle null/undefined values gracefully', async () => {
611
+ const malformedResponse = {
612
+ value: [
613
+ { Name: 'ValidDimension' },
614
+ { Name: null },
615
+ { Name: undefined },
616
+ {} // No Name property
617
+ ]
618
+ };
619
+
620
+ mockRestService.get.mockResolvedValue(mockResponse(malformedResponse));
621
+
622
+ const result = await dimensionService.getAllNames();
623
+
624
+ // Should handle malformed data gracefully
625
+ expect(result).toContain('ValidDimension');
626
+ });
627
+ });
628
+
629
+ describe('Service Integration', () => {
630
+ test('should integrate with HierarchyService for dimension operations', async () => {
631
+ jest.spyOn(dimensionService, 'exists').mockResolvedValue(false);
632
+ mockRestService.post.mockResolvedValue(mockResponse({}));
633
+ mockHierarchyService.updateElementAttributes.mockResolvedValue();
634
+
635
+ await dimensionService.create(mockDimension);
636
+
637
+ expect(mockHierarchyService.updateElementAttributes).toHaveBeenCalledWith(
638
+ mockDimension.hierarchies[0]
639
+ );
640
+ });
641
+
642
+ test('should coordinate hierarchy updates during dimension update', async () => {
643
+ // Create a fresh dimension object for this test
644
+ const testDimension = {
645
+ name: 'TestDimension',
646
+ hierarchies: [
647
+ { name: 'TestDimension', dimensionName: 'TestDimension' },
648
+ { name: 'AltHierarchy', dimensionName: 'TestDimension' }
649
+ ],
650
+ hierarchyNames: ['TestDimension', 'AltHierarchy'],
651
+ body: {},
652
+ [Symbol.iterator]: function* () {
653
+ yield* this.hierarchies;
654
+ }
655
+ };
656
+
657
+ // Clear any previous calls first
658
+ mockHierarchyService.getAllNames.mockClear();
659
+ mockHierarchyService.exists.mockClear();
660
+ mockHierarchyService.create.mockClear();
661
+ mockHierarchyService.delete.mockClear();
662
+
663
+ mockHierarchyService.getAllNames.mockResolvedValue(['OldHierarchy']);
664
+ mockHierarchyService.exists.mockResolvedValue(false);
665
+ mockHierarchyService.create.mockResolvedValue(mockResponse({}));
666
+ mockHierarchyService.delete.mockResolvedValue(mockResponse({}));
667
+
668
+ await dimensionService.update(testDimension as any);
669
+
670
+ expect(mockHierarchyService.create).toHaveBeenCalledTimes(2); // Create new hierarchies
671
+ expect(mockHierarchyService.delete).toHaveBeenLastCalledWith('TestDimension', 'OldHierarchy'); // Remove old
672
+ });
673
+
674
+ test('should handle hierarchy service initialization', () => {
675
+ const newService = new DimensionService(mockRestService);
676
+
677
+ expect(HierarchyService).toHaveBeenCalledWith(mockRestService);
678
+ expect(SubsetService).toHaveBeenCalledWith(mockRestService);
679
+ });
680
+
681
+ test('should maintain service state across operations', async () => {
682
+ // Test that the service maintains its internal state properly
683
+ jest.spyOn(dimensionService, 'exists').mockResolvedValue(true);
684
+
685
+ const exists1 = await dimensionService.exists('Dimension1');
686
+ const exists2 = await dimensionService.exists('Dimension2');
687
+
688
+ expect(exists1).toBe(true);
689
+ expect(exists2).toBe(true);
690
+ expect(dimensionService.exists).toHaveBeenCalledTimes(2);
691
+ });
692
+ });
693
+
694
+ describe('Complex Workflow Scenarios', () => {
695
+ test('should support complete dimension lifecycle', async () => {
696
+ // Create, update, clone, delete workflow
697
+ jest.spyOn(dimensionService, 'exists')
698
+ .mockResolvedValueOnce(false) // Create check
699
+ .mockResolvedValueOnce(false) // Clone target check
700
+ .mockResolvedValue(true); // Other operations
701
+
702
+ jest.spyOn(dimensionService, 'get').mockResolvedValue(mockDimension);
703
+ jest.spyOn(dimensionService, 'create').mockResolvedValue(mockResponse({}));
704
+ mockRestService.post.mockResolvedValue(mockResponse({}));
705
+ mockRestService.delete.mockResolvedValue(mockResponse({}));
706
+ mockHierarchyService.updateElementAttributes.mockResolvedValue();
707
+ mockHierarchyService.getAllNames.mockResolvedValue(['TestDimension']);
708
+ mockHierarchyService.exists.mockResolvedValue(true);
709
+ mockHierarchyService.update.mockResolvedValue();
710
+
711
+ // Full lifecycle
712
+ await dimensionService.create(mockDimension);
713
+ await dimensionService.update(mockDimension);
714
+ await dimensionService.clone('TestDimension', 'ClonedDimension');
715
+ await dimensionService.delete('TestDimension');
716
+
717
+ expect(dimensionService.create).toHaveBeenCalledTimes(2); // Original + clone
718
+ expect(mockHierarchyService.update).toHaveBeenCalled();
719
+ expect(mockRestService.delete).toHaveBeenCalled();
720
+ });
721
+
722
+ test('should handle complex hierarchy management scenario', async () => {
723
+ const complexDimension = {
724
+ name: 'ComplexDim',
725
+ hierarchies: [
726
+ { name: 'ComplexDim', dimensionName: 'ComplexDim' },
727
+ { name: 'NewHierarchy', dimensionName: 'ComplexDim' },
728
+ { name: 'Leaves', dimensionName: 'ComplexDim' } // Should be skipped
729
+ ],
730
+ hierarchyNames: ['ComplexDim', 'NewHierarchy', 'Leaves'],
731
+ body: {},
732
+ [Symbol.iterator]: function* () {
733
+ yield* this.hierarchies;
734
+ }
735
+ };
736
+
737
+ mockHierarchyService.getAllNames.mockResolvedValue(['ComplexDim', 'OldHierarchy', 'Leaves']);
738
+ mockHierarchyService.exists
739
+ .mockResolvedValueOnce(true) // ComplexDim exists
740
+ .mockResolvedValueOnce(false); // NewHierarchy doesn't exist
741
+ mockHierarchyService.update.mockResolvedValue();
742
+ mockHierarchyService.create.mockResolvedValue(mockResponse({}));
743
+ mockHierarchyService.delete.mockResolvedValue(mockResponse({}));
744
+
745
+ await dimensionService.update(complexDimension as any);
746
+
747
+ expect(mockHierarchyService.update).toHaveBeenCalledTimes(1); // ComplexDim updated
748
+ expect(mockHierarchyService.create).toHaveBeenCalledTimes(1); // NewHierarchy created
749
+ expect(mockHierarchyService.delete).toHaveBeenCalledWith('ComplexDim', 'OldHierarchy'); // Remove old
750
+ expect(mockHierarchyService.delete).not.toHaveBeenCalledWith('ComplexDim', 'Leaves'); // Skip Leaves
751
+ });
752
+
753
+ test('should handle error recovery during complex operations', async () => {
754
+ // Create a fresh dimension object for this test
755
+ const testDimension = {
756
+ name: 'TestDimension',
757
+ hierarchies: [
758
+ { name: 'TestDimension', dimensionName: 'TestDimension' }
759
+ ],
760
+ hierarchyNames: ['TestDimension'],
761
+ body: {},
762
+ [Symbol.iterator]: function* () {
763
+ yield* this.hierarchies;
764
+ }
765
+ };
766
+
767
+ // Create fresh spies for this test to avoid interference
768
+ const existsSpy = jest.spyOn(dimensionService, 'exists')
769
+ .mockResolvedValueOnce(false) // Initial check passes
770
+ .mockResolvedValueOnce(true); // Cleanup check - dimension was created
771
+
772
+ const deleteSpy = jest.spyOn(dimensionService, 'delete').mockResolvedValue(mockResponse({}));
773
+
774
+ mockRestService.post.mockClear().mockResolvedValue(mockResponse({})); // Creation succeeds
775
+ mockHierarchyService.updateElementAttributes.mockClear().mockRejectedValue(new Error('Hierarchy update failed')); // But hierarchy update fails
776
+
777
+ await expect(dimensionService.create(testDimension as any)).rejects.toThrow('Hierarchy update failed');
778
+
779
+ expect(deleteSpy).toHaveBeenLastCalledWith('TestDimension'); // Cleanup performed
780
+
781
+ // Clean up spies
782
+ existsSpy.mockRestore();
783
+ deleteSpy.mockRestore();
784
+ });
785
+ });
786
+ });